aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog601
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/combine.c25
-rw-r--r--gcc/config/aarch64/aarch64.md3
-rw-r--r--gcc/config/alpha/alpha.c4
-rw-r--r--gcc/config/alpha/alpha.md10
-rw-r--r--gcc/config/arm/arm-builtins.c2
-rw-r--r--gcc/config/arm/arm.c16
-rw-r--r--gcc/config/arm/arm.h3
-rw-r--r--gcc/config/arm/arm.md9
-rw-r--r--gcc/config/arm/neon.md14
-rw-r--r--gcc/config/i386/constraints.md6
-rw-r--r--gcc/config/i386/i386-opts.h13
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c976
-rw-r--r--gcc/config/i386/i386.h68
-rw-r--r--gcc/config/i386/i386.md88
-rw-r--r--gcc/config/i386/i386.opt28
-rw-r--r--gcc/config/i386/predicates.md21
-rw-r--r--gcc/config/nvptx/nvptx.c5
-rw-r--r--gcc/config/pa/pa.c39
-rw-r--r--gcc/config/pa/pa.h18
-rw-r--r--gcc/config/pa/pa.md82
-rw-r--r--gcc/config/pa/pa.opt4
-rw-r--r--gcc/config/pa/pa64-hpux.h14
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def18
-rw-r--r--gcc/config/rs6000/rs6000-c.c9
-rw-r--r--gcc/config/rs6000/rs6000.c17
-rw-r--r--gcc/config/rs6000/rs6000.h4
-rw-r--r--gcc/config/rs6000/rs6000.md12
-rw-r--r--gcc/config/rs6000/sysv4.opt4
-rw-r--r--gcc/config/s390/s390.c2
-rw-r--r--gcc/config/sparc/sparc.c36
-rw-r--r--gcc/config/sparc/sparc.md12
-rwxr-xr-xgcc/configure4
-rw-r--r--gcc/configure.ac4
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/doc/extend.texi33
-rw-r--r--gcc/doc/gcov.texi7
-rw-r--r--gcc/doc/invoke.texi69
-rw-r--r--gcc/expr.c5
-rw-r--r--gcc/fortran/ChangeLog50
-rw-r--r--gcc/fortran/arith.c10
-rw-r--r--gcc/fortran/decl.c29
-rw-r--r--gcc/fortran/frontend-passes.c8
-rw-r--r--gcc/fortran/interface.c2
-rw-r--r--gcc/fortran/resolve.c13
-rw-r--r--gcc/fortran/simplify.c30
-rw-r--r--gcc/ipa-devirt.c11
-rw-r--r--gcc/ipa-icf.c11
-rw-r--r--gcc/lto/ChangeLog18
-rw-r--r--gcc/lto/lto-symtab.c13
-rw-r--r--gcc/testsuite/ChangeLog492
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for13.C44
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr82352.C93
-rw-r--r--gcc/testsuite/g++.dg/opt/pr77844.C32
-rw-r--r--gcc/testsuite/g++.dg/opt/pr85196.C89
-rw-r--r--gcc/testsuite/g++.dg/pr85026.C61
-rw-r--r--gcc/testsuite/g++.dg/torture/pr85496.C18
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr84748.c34
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr85248_0.c45
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr85248_1.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr84956.c27
-rw-r--r--gcc/testsuite/gcc.target/arm/fpscr.c9
-rw-r--r--gcc/testsuite/gcc.target/arm/pr82518.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/pr82989.c33
-rw-r--r--gcc/testsuite/gcc.target/arm/pr84826.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-10.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-3.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-4.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-5.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-6.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-7.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-8.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-9.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85193.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-10.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-11.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-12.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-13.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-14.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-15.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-16.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-17.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-18.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-19.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-20.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-21.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-22.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-23.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-24.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-25.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-26.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-4.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-7.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-8.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-9.c21
-rw-r--r--gcc/testsuite/gcc.target/nvptx/pr85056.c21
-rw-r--r--gcc/testsuite/gcc.target/nvptx/pr85056a.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/crypto-builtin-1-runnable.c109
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extend-divide-1.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extend-divide-2.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-sdata-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83660.C14
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c19
-rw-r--r--gcc/testsuite/gfortran.dg/array_constructor_52.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/interface_41.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_rank_1.f909
-rw-r--r--gcc/testsuite/gfortran.dg/pr64124.f905
-rw-r--r--gcc/testsuite/gfortran.dg/pr65453.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr70409.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/pr83939.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr84734.f904
-rw-r--r--gcc/testsuite/gfortran.dg/pr85520.f907
-rw-r--r--gcc/testsuite/lib/target-supports.exp3
-rw-r--r--gcc/tree-ssa-tail-merge.c4
-rw-r--r--gcc/valtrack.c20
160 files changed, 4841 insertions, 345 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f1274bfd957..a2fa483b3cd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,604 @@
+2018-04-25 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-04-17 Martin Liska <mliska@suse.cz>
+
+ PR lto/85405
+ * ipa-devirt.c (odr_types_equivalent_p): Remove trailing
+ in message, remote space in between '_G' and '('.
+
+2018-04-25 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-04-17 Jan Hubicka <jh@suse.cz>
+
+ PR lto/85405
+ * ipa-devirt.c (odr_types_equivalent_p): Handle bit fields.
+
+2018-04-23 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ Backport from mainline
+ 2018-04-16 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ PR target/83660
+ * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Mark
+ vec_extract expression as having side effects to make sure it gets
+ a cleanup point.
+
+2018-04-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/85496
+ * expr.c (store_field): In the bitfield case, if the value comes from
+ a function call and is returned in registers by means of a PARALLEL,
+ do not change the mode of the temporary unless BLKmode and VOIDmode.
+
+2018-04-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ Backport from mainline
+ 2018-04-11 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR target/85261
+ * config/arm/arm-builtins.c (arm_expand_builtin): Force input operand
+ into register.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-03-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84574
+ * config/i386/i386.c (indirect_thunk_needed): Update comments.
+ (indirect_thunk_bnd_needed): Likewise.
+ (indirect_thunks_used): Likewise.
+ (indirect_thunks_bnd_used): Likewise.
+ (indirect_return_needed): New.
+ (indirect_return_bnd_needed): Likewise.
+ (output_indirect_thunk_function): Add a bool argument for
+ function return.
+ (output_indirect_thunk_function): Don't generate alias for
+ function return thunk.
+ (ix86_code_end): Call output_indirect_thunk_function to generate
+ function return thunks.
+ (ix86_output_function_return): Set indirect_return_bnd_needed
+ and indirect_return_needed instead of indirect_thunk_bnd_needed
+ and indirect_thunk_needed.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84039
+ * config/i386/constraints.md (Bs): Replace
+ ix86_indirect_branch_register with
+ TARGET_INDIRECT_BRANCH_REGISTER.
+ (Bw): Likewise.
+ * config/i386/i386.md (indirect_jump): Likewise.
+ (tablejump): Likewise.
+ (*sibcall_memory): Likewise.
+ (*sibcall_value_memory): Likewise.
+ Peepholes of indirect call and jump via memory: Likewise.
+ (*sibcall_GOT_32): Disallowed for TARGET_INDIRECT_BRANCH_REGISTER.
+ (*sibcall_value_GOT_32): Likewise.
+ * config/i386/predicates.md (indirect_branch_operand): Likewise.
+ (GOT_memory_operand): Likewise.
+ (call_insn_operand): Likewise.
+ (sibcall_insn_operand): Likewise.
+ (GOT32_symbol_operand): Likewise.
+ * config/i386/i386.h (TARGET_INDIRECT_BRANCH_REGISTER): New.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_output_indirect_jmp): Update comments.
+
+ 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84530
+ * config/i386/i386-protos.h (ix86_output_indirect_jmp): Remove
+ the bool argument.
+ (ix86_output_indirect_function_return): New prototype.
+ (ix86_split_simple_return_pop_internal): Likewise.
+ * config/i386/i386.c (indirect_return_via_cx): New.
+ (indirect_return_via_cx_bnd): Likewise.
+ (indirect_thunk_name): Handle return va CX_REG.
+ (output_indirect_thunk_function): Create alias for
+ __x86_return_thunk_[re]cx and __x86_return_thunk_[re]cx_bnd.
+ (ix86_output_indirect_jmp): Remove the bool argument.
+ (ix86_output_indirect_function_return): New function.
+ (ix86_split_simple_return_pop_internal): Likewise.
+ * config/i386/i386.md (*indirect_jump): Don't pass false
+ to ix86_output_indirect_jmp.
+ (*tablejump_1): Likewise.
+ (simple_return_pop_internal): Change it to define_insn_and_split.
+ Call ix86_split_simple_return_pop_internal to split it for
+ -mfunction-return=.
+ (simple_return_indirect_internal): Call
+ ix86_output_indirect_function_return instead of
+ ix86_output_indirect_jmp.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-02-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_output_function_return): Pass
+ INVALID_REGNUM, instead of -1, as invalid register number to
+ indirect_thunk_name and output_indirect_thunk.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (indirect_thunk_name): Declare regno
+ as unsigned int. Compare regno with INVALID_REGNUM.
+ (output_indirect_thunk): Ditto.
+ (output_indirect_thunk_function): Ditto.
+ (ix86_code_end): Declare regno as unsigned int. Use INVALID_REGNUM
+ in the call to output_indirect_thunk_function.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_set_indirect_branch_type): Disallow
+ -mcmodel=large with -mindirect-branch=thunk,
+ -mindirect-branch=thunk-extern, -mfunction-return=thunk and
+ -mfunction-return=thunk-extern.
+ * doc/invoke.texi: Document -mcmodel=large is incompatible with
+ -mindirect-branch=thunk, -mindirect-branch=thunk-extern,
+ -mfunction-return=thunk and -mfunction-return=thunk-extern.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (print_reg): Print the name of the full
+ integer register without '%'.
+ (ix86_print_operand): Handle 'V'.
+ * doc/extend.texi: Document 'V' modifier.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/constraints.md (Bs): Disallow memory operand for
+ -mindirect-branch-register.
+ (Bw): Likewise.
+ * config/i386/predicates.md (indirect_branch_operand): Likewise.
+ (GOT_memory_operand): Likewise.
+ (call_insn_operand): Likewise.
+ (sibcall_insn_operand): Likewise.
+ (GOT32_symbol_operand): Likewise.
+ * config/i386/i386.md (indirect_jump): Call convert_memory_address
+ for -mindirect-branch-register.
+ (tablejump): Likewise.
+ (*sibcall_memory): Likewise.
+ (*sibcall_value_memory): Likewise.
+ Disallow peepholes of indirect call and jump via memory for
+ -mindirect-branch-register.
+ (*call_pop): Replace m with Bw.
+ (*call_value_pop): Likewise.
+ (*sibcall_pop_memory): Replace m with Bs.
+ * config/i386/i386.opt (mindirect-branch-register): New option.
+ * doc/invoke.texi: Document -mindirect-branch-register option.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/constraints.md (Bs): Replace
+ ix86_indirect_branch_thunk_register with
+ ix86_indirect_branch_register.
+ (Bw): Likewise.
+ * config/i386/i386.md (indirect_jump): Likewise.
+ (tablejump): Likewise.
+ (*sibcall_memory): Likewise.
+ (*sibcall_value_memory): Likewise.
+ Peepholes of indirect call and jump via memory: Likewise.
+ * config/i386/i386.opt: Likewise.
+ * config/i386/predicates.md (indirect_branch_operand): Likewise.
+ (GOT_memory_operand): Likewise.
+ (call_insn_operand): Likewise.
+ (sibcall_insn_operand): Likewise.
+ (GOT32_symbol_operand): Likewise.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/predicates.md (constant_call_address_operand):
+ Rewrite ix86_indirect_branch_register logic.
+ (sibcall_insn_operand): Likewise.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/constraints.md (Bs): Update
+ ix86_indirect_branch_register check. Don't check
+ ix86_indirect_branch_register with GOT_memory_operand.
+ (Bw): Likewise.
+ * config/i386/predicates.md (GOT_memory_operand): Don't check
+ ix86_indirect_branch_register here.
+ (GOT32_symbol_operand): Likewise.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/predicates.md (indirect_branch_operand): Rewrite
+ ix86_indirect_branch_register logic.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386-protos.h (ix86_output_function_return): New.
+ * config/i386/i386.c (ix86_set_indirect_branch_type): Also
+ set function_return_type.
+ (indirect_thunk_name): Add ret_p to indicate thunk for function
+ return.
+ (output_indirect_thunk_function): Pass false to
+ indirect_thunk_name.
+ (ix86_output_indirect_branch_via_reg): Likewise.
+ (ix86_output_indirect_branch_via_push): Likewise.
+ (output_indirect_thunk_function): Create alias for function
+ return thunk if regno < 0.
+ (ix86_output_function_return): New function.
+ (ix86_handle_fndecl_attribute): Handle function_return.
+ (ix86_attribute_table): Add function_return.
+ * config/i386/i386.h (machine_function): Add
+ function_return_type.
+ * config/i386/i386.md (simple_return_internal): Use
+ ix86_output_function_return.
+ (simple_return_internal_long): Likewise.
+ * config/i386/i386.opt (mfunction-return=): New option.
+ (indirect_branch): Mention -mfunction-return=.
+ * doc/extend.texi: Document function_return function attribute.
+ * doc/invoke.texi: Document -mfunction-return= option.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/83839
+ * config/i386/i386.c (output_indirect_thunk_function): Use
+ ASM_OUTPUT_LABEL, instead of ASM_OUTPUT_DEF, for TARGET_MACHO
+ for __x86.return_thunk.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386-opts.h (indirect_branch): New.
+ * config/i386/i386-protos.h (ix86_output_indirect_jmp): Likewise.
+ * config/i386/i386.c (ix86_using_red_zone): Disallow red-zone
+ with local indirect jump when converting indirect call and jump.
+ (ix86_set_indirect_branch_type): New.
+ (ix86_set_current_function): Call ix86_set_indirect_branch_type.
+ (indirectlabelno): New.
+ (indirect_thunk_needed): Likewise.
+ (indirect_thunk_bnd_needed): Likewise.
+ (indirect_thunks_used): Likewise.
+ (indirect_thunks_bnd_used): Likewise.
+ (INDIRECT_LABEL): Likewise.
+ (indirect_thunk_name): Likewise.
+ (output_indirect_thunk): Likewise.
+ (output_indirect_thunk_function): Likewise.
+ (ix86_output_indirect_branch_via_reg): Likewise.
+ (ix86_output_indirect_branch_via_push): Likewise.
+ (ix86_output_indirect_branch): Likewise.
+ (ix86_output_indirect_jmp): Likewise.
+ (ix86_code_end): Call output_indirect_thunk_function if needed.
+ (ix86_output_call_insn): Call ix86_output_indirect_branch if
+ needed.
+ (ix86_handle_fndecl_attribute): Handle indirect_branch.
+ (ix86_attribute_table): Add indirect_branch.
+ * config/i386/i386.h (machine_function): Add indirect_branch_type
+ and has_local_indirect_jump.
+ * config/i386/i386.md (indirect_jump): Set has_local_indirect_jump
+ to true.
+ (tablejump): Likewise.
+ (*indirect_jump): Use ix86_output_indirect_jmp.
+ (*tablejump_1): Likewise.
+ (simple_return_indirect_internal): Likewise.
+ * config/i386/i386.opt (mindirect-branch=): New option.
+ (indirect_branch): New.
+ (keep): Likewise.
+ (thunk): Likewise.
+ (thunk-inline): Likewise.
+ (thunk-extern): Likewise.
+ * doc/extend.texi: Document indirect_branch function attribute.
+ * doc/invoke.texi: Document -mindirect-branch= option.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ PR target/83905
+ * config/i386/i386.c (ix86_expand_prologue): Use cost reference
+ of struct ix86_frame.
+ (ix86_expand_epilogue): Likewise. Add a local variable for
+ the reg_save_offset field in struct ix86_frame.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2017-11-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_can_use_return_insn_p): Use reference
+ of struct ix86_frame.
+ (ix86_initial_elimination_offset): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2017-10-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/82499
+ * config/i386/i386.h (ix86_red_zone_size): New.
+
+ 2017-06-01 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * config/i386/i386.c (ix86_frame): Moved to ...
+ * config/i386/i386.h (ix86_frame): Here.
+ (machine_function): Add frame.
+ * config/i386/i386.c (ix86_compute_frame_layout): Repace the
+ frame argument with &cfun->machine->frame.
+ (ix86_can_use_return_insn_p): Don't pass &frame to
+ ix86_compute_frame_layout. Copy frame from cfun->machine->frame.
+ (ix86_can_eliminate): Likewise.
+ (ix86_expand_prologue): Likewise.
+ (ix86_expand_epilogue): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+
+2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/s390.c (s390_output_indirect_thunk_function): Check
+ also for flag_dwarf2_cfi_asm.
+
+2018-04-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/alpha.md (stack_probe_internal): Rename
+ from "probe_stack". Update all callers.
+
+2018-04-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/84748
+ * config/aarch64/aarch64.md (*compare_cstore<mode>_insn): Mark pattern
+ as clobbering CC_REGNUM.
+
+2018-04-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/85196
+ * config/sparc/sparc.c (sparc_expand_move): Deal with symbolic operands
+ based on LABEL_REF. Remove useless assertion.
+ (pic_address_needs_scratch): Fix formatting.
+ (sparc_legitimize_pic_address): Minor tweaks.
+ (sparc_delegitimize_address): Adjust assertion accordingly.
+ * config/sparc/sparc.md (movsi_pic_label_ref): Change label_ref_operand
+ into symbolic_operand.
+ (movsi_high_pic_label_ref): Likewise.
+ (movsi_lo_sum_pic_label_ref): Likewise.
+ (movdi_pic_label_ref): Likewise.
+ (movdi_high_pic_label_ref): Likewise.
+ (movdi_lo_sum_pic_label_ref): Likewise.
+
+2018-04-05 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/85193
+ * config/i386/i386.md (define_attr "memory"): Handle rotate1 type.
+
+2018-04-02 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2018-03-28 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/84912
+ * config/rs6000/rs6000.h: Update copyright date.
+ (RS6000_BTM_POWERPC64): New define.
+ (RS6000_BTM_COMMON): Add RS6000_BTM_POWERPC64.
+ * config/rs6000/rs6000.c: Update copyright date.
+ (rs6000_builtin_mask_calculate): Add support for RS6000_BTM_POWERPC64.
+ (rs6000_invalid_builtin): Add handling for RS6000_BTM_POWERPC64
+ (rs6000_builtin_mask_names): Add RS6000_BTM_POWERPC64.
+ * config/rs6000/rs6000-builtin.def: Update copyright date.
+ (BU_P7_POWERPC64_MISC_2): New macro definition.
+ (DIVDE): Use it.
+ (DIVDEU): Likewise.
+
+ Backport from mainline
+ 2018-03-28 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/84912
+ * config/rs6000/rs6000-builtin.def (DIVWEO): Delete macro expansion.
+ (DIVWEUO): Likewise.
+ (DIVDEO): Likewise.
+ (DIVDEUO): Likewise.
+ * config/rs6000/rs6000.c (builtin_function_type): Remove support for
+ DIVWEUO and DIVDEUO.
+ * config/rs6000/rs6000.md: Update copyright date.
+ (UNSPEC_DIVEO, UNSPEC_DIVEUO): Delete unspecs.
+ (UNSPEC_DIV_EXTEND): Remove deleted unspecs.
+ (div_extend): Likewise.
+ * doc/extend.texi: Update copyright date.
+ (__builtin_divweo): Remove documentation for deleted builtin function.
+ (__builtin_divweuo): Likewise.
+ (__builtin_divdeo): Likewise.
+ (__builtin_divdeuo): Likewise.
+
+2018-03-30 Cesar Philippidis <cesar@codesourcery.com>
+
+ Backport from mainline
+ 2018-03-27 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR target/85056
+ * config/nvptx/nvptx.c (nvptx_assemble_decl_begin): Add '[]' to
+ extern array declarations.
+
+2018-03-29 Sudakshina Das <sudi.das@arm.com>
+
+ Backport from mainline
+ 2018-03-22 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/84826
+ * config/arm/arm.h (machine_function): Add static_chain_stack_bytes.
+ * config/arm/arm.c (arm_compute_static_chain_stack_bytes): Avoid
+ re-computing once computed.
+ (arm_expand_prologue): Compute machine->static_chain_stack_bytes.
+ (arm_init_machine_status): Initialize
+ machine->static_chain_stack_bytes.
+
+2018-03-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/85026
+ * config/arm/arm.md (unaligned_loadhis): Remove first alternative.
+ Clean up attributes.
+
+2018-03-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ Backport from mainline
+ 2018-03-08 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/82411
+ * config/rs6000/rs6000.c (rs6000_elf_in_small_data_p): Don't put
+ readonly data in sdata, if that is disabled.
+ * config/rs6000/sysv4.opt (mreadonly-in-sdata): New option.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Document
+ -mreadonly-in-sdata option.
+
+2018-03-27 Carl Love <cel@us.ibm.com>
+
+ Backport from mainline
+ 2018-03-14 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/r6000.c (rtx_is_swappable_p): Add case UNSPEC_VPERMXOR.
+
+2018-03-27 Sudakshina Das <sudi.das@arm.com>
+
+ Backport from mainline:
+ 2018-03-20 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/82989
+ * config/arm/neon.md (ashldi3_neon): Update ?s for constraints
+ to favor GPR over NEON registers.
+ (<shift>di3_neon): Likewise.
+
+2018-03-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/82518
+ * config/arm/arm.c (arm_array_mode_supported_p): Return false for
+ BYTES_BIG_ENDIAN.
+
+2018-03-22 Tom de Vries <tom@codesourcery.com>
+
+ backport from trunk:
+ 2018-03-22 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/84956
+ * tree-ssa-tail-merge.c (find_clusters_1): Skip bbs with
+ bb_has_abnormal_pred.
+
+2018-03-18 John David Anglin <danglin@gcc.gnu.org>
+
+ Backport from mainline
+ 2016-12-11 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.c (pa_callee_copies): New function.
+ * config/pa/pa.opt (mcaller-copies): New option.
+ * doc/invoke.texi (mcaller-copies): Document option.
+
+2018-03-14 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/83451
+ * config/pa/pa.c (pa_emit_move_sequence): Always emit secondary reload
+ insn for floating-point loads and stores.
+
+2018-03-12 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/invoke.texi (-mclflushopt): Fix spelling of option.
+
+2018-03-11 John David Anglin <danglin@gcc.gnu.org>
+
+ Backport from mainline
+ 2018-02-14 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/83984
+ * config/pa/pa.md: Load address of PIC label using the linkage table
+ if the label is nonlocal.
+
+ Backport from mainline
+ 2018-03-06 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.h (ASM_GENERATE_INTERNAL_LABEL): Revise to use
+ sprint_ul.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Revise for above change.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
+ * config/pa/pa64-hpux.h (ASM_GENERATE_INTERNAL_LABEL): Revise as above.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2016-12-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/77844
+ * valtrack.c: Include rtl-iter.h.
+ (struct rtx_subst_pair): Add insn field.
+ (propagate_for_debug_subst): If pair->to contains at least 2
+ regs, create a DEBUG_INSN with a debug temp before pair->insn
+ and replace from with the debug temp instead of pair->to.
+ (propagate_for_debug): Initialize p.insn.
+ * combine.c (insn_uid_check): New inline function.
+ (INSN_COST, LOG_LINKS): Use it instead of INSN_UID.
+ (find_single_use, combine_instructions,
+ cant_combine_insn_p, try_combine): Use NONDEBUG_INSN_P instead of
+ INSN_P.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-04 Martin Liska <mliska@suse.cz>
+
+ PR ipa/82352
+ * ipa-icf.c (sem_function::merge): Do not cross comdat boundary.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2017-10-31 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/82633
+ * doc/gcov.texi: Document -fkeep-{static,inline}-functions and
+ their interaction with GCOV infrastructure.
+ * configure.ac: Add -fkeep-static-functions to
+ coverage_flags.
+ * configure: Regenerate.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2017-10-27 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/82457
+ * doc/invoke.texi: Document that one needs a non-strict ISO mode
+ for fork-like functions to be properly instrumented.
+
2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
Backport from mainline
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index d326f67838d..cdc90b450c7 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20180307
+20180425
diff --git a/gcc/combine.c b/gcc/combine.c
index 24f2af12b89..9b0386c99e7 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -329,8 +329,16 @@ struct insn_link {
static struct insn_link **uid_log_links;
-#define INSN_COST(INSN) (uid_insn_cost[INSN_UID (INSN)])
-#define LOG_LINKS(INSN) (uid_log_links[INSN_UID (INSN)])
+static inline int
+insn_uid_check (const_rtx insn)
+{
+ int uid = INSN_UID (insn);
+ gcc_checking_assert (uid <= max_uid_known);
+ return uid;
+}
+
+#define INSN_COST(INSN) (uid_insn_cost[insn_uid_check (INSN)])
+#define LOG_LINKS(INSN) (uid_log_links[insn_uid_check (INSN)])
#define FOR_EACH_LOG_LINK(L, INSN) \
for ((L) = LOG_LINKS (INSN); (L); (L) = (L)->next)
@@ -678,7 +686,7 @@ find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc)
for (next = NEXT_INSN (insn);
next && BLOCK_FOR_INSN (next) == bb;
next = NEXT_INSN (next))
- if (INSN_P (next) && dead_or_set_p (next, dest))
+ if (NONDEBUG_INSN_P (next) && dead_or_set_p (next, dest))
{
FOR_EACH_LOG_LINK (link, next)
if (link->insn == insn && link->regno == REGNO (dest))
@@ -1129,7 +1137,7 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
int new_direct_jump_p = 0;
- for (first = f; first && !INSN_P (first); )
+ for (first = f; first && !NONDEBUG_INSN_P (first); )
first = NEXT_INSN (first);
if (!first)
return 0;
@@ -2277,7 +2285,7 @@ cant_combine_insn_p (rtx_insn *insn)
/* If this isn't really an insn, we can't do anything.
This can occur when flow deletes an insn that it has merged into an
auto-increment address. */
- if (! INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
return 1;
/* Never combine loads and stores involving hard regs that are likely
@@ -4172,7 +4180,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|| insn != BB_HEAD (this_basic_block->next_bb));
insn = NEXT_INSN (insn))
{
- if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
+ if (NONDEBUG_INSN_P (insn)
+ && reg_referenced_p (ni2dest, PATTERN (insn)))
{
FOR_EACH_LOG_LINK (link, insn)
if (link->insn == i3)
@@ -4313,9 +4322,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
for (temp_insn = NEXT_INSN (i2);
temp_insn
&& (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
- || BB_HEAD (this_basic_block) != temp_insn);
+ || BB_HEAD (this_basic_block) != temp_insn);
temp_insn = NEXT_INSN (temp_insn))
- if (temp_insn != i3 && INSN_P (temp_insn))
+ if (temp_insn != i3 && NONDEBUG_INSN_P (temp_insn))
FOR_EACH_LOG_LINK (link, temp_insn)
if (link->insn == i2)
link->insn = i3;
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 517a26bbd95..07ffaf6bc39 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3079,7 +3079,8 @@
(define_insn_and_split "*compare_cstore<mode>_insn"
[(set (match_operand:GPI 0 "register_operand" "=r")
(EQL:GPI (match_operand:GPI 1 "register_operand" "r")
- (match_operand:GPI 2 "aarch64_imm24" "n")))]
+ (match_operand:GPI 2 "aarch64_imm24" "n")))
+ (clobber (reg:CC CC_REGNUM))]
"!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
&& !aarch64_plus_operand (operands[2], <MODE>mode)
&& !reload_completed"
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 1efe8879b82..b9315eb1def 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -7740,13 +7740,13 @@ alpha_expand_prologue (void)
int probed;
for (probed = 4096; probed < probed_size; probed += 8192)
- emit_insn (gen_probe_stack (GEN_INT (-probed)));
+ emit_insn (gen_stack_probe_internal (GEN_INT (-probed)));
/* We only have to do this probe if we aren't saving registers or
if we are probing beyond the frame because of -fstack-check. */
if ((sa_size == 0 && probed_size > probed - 4096)
|| flag_stack_check)
- emit_insn (gen_probe_stack (GEN_INT (-probed_size)));
+ emit_insn (gen_stack_probe_internal (GEN_INT (-probed_size)));
}
if (frame_size != 0)
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 3e4594bf4c6..be75067ac12 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4843,7 +4843,7 @@
;; Subroutine of stack space allocation. Perform a stack probe.
-(define_expand "probe_stack"
+(define_expand "stack_probe_internal"
[(set (match_dup 1) (match_operand:DI 0 "const_int_operand"))]
""
{
@@ -4878,12 +4878,14 @@
int probed = 4096;
- emit_insn (gen_probe_stack (GEN_INT (- probed)));
+ emit_insn (gen_stack_probe_internal (GEN_INT (- probed)));
while (probed + 8192 < INTVAL (operands[1]))
- emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192))));
+ emit_insn (gen_stack_probe_internal
+ (GEN_INT (- (probed += 8192))));
if (probed + 4096 < INTVAL (operands[1]))
- emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[1]))));
+ emit_insn (gen_stack_probe_internal
+ (GEN_INT (- INTVAL(operands[1]))));
}
operands[1] = GEN_INT (- INTVAL (operands[1]));
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index c36390539aa..22b7532d921 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -2464,7 +2464,7 @@ arm_expand_builtin (tree exp,
icode = CODE_FOR_set_fpscr;
arg0 = CALL_EXPR_ARG (exp, 0);
op0 = expand_normal (arg0);
- pat = GEN_FCN (icode) (op0);
+ pat = GEN_FCN (icode) (force_reg (SImode, op0));
}
emit_insn (pat);
return target;
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 0b12ca5ab09..3e7fc0b41c3 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -18992,6 +18992,11 @@ arm_r3_live_at_start_p (void)
static int
arm_compute_static_chain_stack_bytes (void)
{
+ /* Once the value is updated from the init value of -1, do not
+ re-compute. */
+ if (cfun->machine->static_chain_stack_bytes != -1)
+ return cfun->machine->static_chain_stack_bytes;
+
/* See the defining assertion in arm_expand_prologue. */
if (IS_NESTED (arm_current_func_type ())
&& ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
@@ -21298,6 +21303,11 @@ arm_expand_prologue (void)
emit_insn (gen_movsi (stack_pointer_rtx, r1));
}
+ /* Let's compute the static_chain_stack_bytes required and store it. Right
+ now the value must the -1 as stored by arm_init_machine_status (). */
+ cfun->machine->static_chain_stack_bytes
+ = arm_compute_static_chain_stack_bytes ();
+
/* The static chain register is the same as the IP register. If it is
clobbered when creating the frame, we need to save and restore it. */
clobber_ip = IS_NESTED (func_type)
@@ -24403,6 +24413,7 @@ arm_init_machine_status (void)
#if ARM_FT_UNKNOWN != 0
machine->func_type = ARM_FT_UNKNOWN;
#endif
+ machine->static_chain_stack_bytes = -1;
return machine;
}
@@ -26706,7 +26717,10 @@ static bool
arm_array_mode_supported_p (machine_mode mode,
unsigned HOST_WIDE_INT nelems)
{
- if (TARGET_NEON
+ /* We don't want to enable interleaved loads and stores for BYTES_BIG_ENDIAN
+ for now, as the lane-swapping logic needs to be extended in the expanders.
+ See PR target/82518. */
+ if (TARGET_NEON && !BYTES_BIG_ENDIAN
&& (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
&& (nelems >= 2 && nelems <= 4))
return true;
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 307eed3491d..c10c03a1b2a 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1464,6 +1464,9 @@ typedef struct GTY(()) machine_function
machine_mode thumb1_cc_mode;
/* Set to 1 after arm_reorg has started. */
int after_arm_reorg;
+ /* The number of bytes used to store the static chain register on the
+ stack, above the stack frame. */
+ int static_chain_stack_bytes;
}
machine_function;
#endif
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 49304de0222..6dbb97e2bee 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4510,16 +4510,13 @@
(set_attr "type" "load1")])
(define_insn "unaligned_loadhis"
- [(set (match_operand:SI 0 "s_register_operand" "=l,r")
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
(sign_extend:SI
- (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
+ (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
UNSPEC_UNALIGNED_LOAD)))]
"unaligned_access"
"ldrsh%?\t%0, %1\t@ unaligned"
- [(set_attr "arch" "t2,any")
- (set_attr "length" "2,4")
- (set_attr "predicable" "yes")
- (set_attr "predicable_short_it" "yes,no")
+ [(set_attr "predicable" "yes")
(set_attr "type" "load_byte")])
(define_insn "unaligned_loadhiu"
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 91479dc2b28..eaa7f4f0afc 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -1143,12 +1143,12 @@
)
(define_insn_and_split "ashldi3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r,?&r, ?w,w")
- (ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, 0, r, 0w,w")
- (match_operand:SI 2 "general_operand" "rUm, i, r, i, i,rUm,i")))
- (clobber (match_scratch:SI 3 "= X, X,?&r, X, X, X,X"))
- (clobber (match_scratch:SI 4 "= X, X,?&r, X, X, X,X"))
- (clobber (match_scratch:DI 5 "=&w, X, X, X, X, &w,X"))
+ [(set (match_operand:DI 0 "s_register_operand" "= w, w, &r, r, &r, ?w,?w")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, 0, r, 0w, w")
+ (match_operand:SI 2 "general_operand" "rUm, i, r, i, i,rUm, i")))
+ (clobber (match_scratch:SI 3 "= X, X, &r, X, X, X, X"))
+ (clobber (match_scratch:SI 4 "= X, X, &r, X, X, X, X"))
+ (clobber (match_scratch:DI 5 "=&w, X, X, X, X, &w, X"))
(clobber (reg:CC_C CC_REGNUM))]
"TARGET_NEON"
"#"
@@ -1243,7 +1243,7 @@
;; ashrdi3_neon
;; lshrdi3_neon
(define_insn_and_split "<shift>di3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r,?&r,?w,?w")
+ [(set (match_operand:DI 0 "s_register_operand" "= w, w, &r, r, &r,?w,?w")
(RSHIFTS:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, 0, r,0w, w")
(match_operand:SI 2 "reg_or_int_operand" " r, i, r, i, i, r, i")))
(clobber (match_scratch:SI 3 "=2r, X, &r, X, X,2r, X"))
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 1a4c701ad13..ef684a95497 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -172,14 +172,16 @@
(define_constraint "Bs"
"@internal Sibcall memory operand."
- (ior (and (not (match_test "TARGET_X32"))
+ (ior (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+ (not (match_test "TARGET_X32"))
(match_operand 0 "sibcall_memory_operand"))
(and (match_test "TARGET_X32 && Pmode == DImode")
(match_operand 0 "GOT_memory_operand"))))
(define_constraint "Bw"
"@internal Call memory operand."
- (ior (and (not (match_test "TARGET_X32"))
+ (ior (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+ (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand"))
(and (match_test "TARGET_X32 && Pmode == DImode")
(match_operand 0 "GOT_memory_operand"))))
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index b7f92e3bea1..cc21152875f 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -99,4 +99,17 @@ enum stack_protector_guard {
SSP_GLOBAL /* global canary */
};
+/* This is used to mitigate variant #2 of the speculative execution
+ vulnerabilities on x86 processors identified by CVE-2017-5715, aka
+ Spectre. They convert indirect branches and function returns to
+ call and return thunks to avoid speculative execution via indirect
+ call, jmp and ret. */
+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/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index ff47bc15600..c7a0ccb58d3 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -311,6 +311,10 @@ extern enum attr_cpu ix86_schedule;
#endif
extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+extern const char * ix86_output_indirect_jmp (rtx call_op);
+extern const char * ix86_output_function_return (bool long_p);
+extern const char * ix86_output_indirect_function_return (rtx ret_op);
+extern void ix86_split_simple_return_pop_internal (rtx);
extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
enum machine_mode mode);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 82309a11404..912e107a862 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2435,53 +2435,6 @@ struct GTY(()) stack_local_entry {
struct stack_local_entry *next;
};
-/* Structure describing stack frame layout.
- Stack grows downward:
-
- [arguments]
- <- ARG_POINTER
- saved pc
-
- saved static chain if ix86_static_chain_on_stack
-
- saved frame pointer if frame_pointer_needed
- <- HARD_FRAME_POINTER
- [saved regs]
- <- regs_save_offset
- [padding0]
-
- [saved SSE regs]
- <- sse_regs_save_offset
- [padding1] |
- | <- FRAME_POINTER
- [va_arg registers] |
- |
- [frame] |
- |
- [padding2] | = to_allocate
- <- STACK_POINTER
- */
-struct ix86_frame
-{
- int nsseregs;
- int nregs;
- int va_arg_size;
- int red_zone_size;
- int outgoing_arguments_size;
-
- /* The offsets relative to ARG_POINTER. */
- HOST_WIDE_INT frame_pointer_offset;
- HOST_WIDE_INT hard_frame_pointer_offset;
- HOST_WIDE_INT stack_pointer_offset;
- HOST_WIDE_INT hfp_save_offset;
- HOST_WIDE_INT reg_save_offset;
- HOST_WIDE_INT sse_reg_save_offset;
-
- /* When save_regs_using_mov is set, emit prologue using
- move instead of push instructions. */
- bool save_regs_using_mov;
-};
-
/* Which cpu are we scheduling for. */
enum attr_cpu ix86_schedule;
@@ -2573,7 +2526,7 @@ static unsigned int ix86_function_arg_boundary (machine_mode,
const_tree);
static rtx ix86_static_chain (const_tree, bool);
static int ix86_function_regparm (const_tree, const_tree);
-static void ix86_compute_frame_layout (struct ix86_frame *);
+static void ix86_compute_frame_layout (void);
static bool ix86_expand_vector_init_one_nonzero (bool, machine_mode,
rtx, rtx, int);
static void ix86_add_new_builtins (HOST_WIDE_INT);
@@ -3710,12 +3663,23 @@ make_pass_stv (gcc::context *ctxt)
return new pass_stv (ctxt);
}
-/* Return true if a red-zone is in use. */
+/* Return true if a red-zone is in use. We can't use red-zone when
+ there are local indirect jumps, like "indirect_jump" or "tablejump",
+ which jumps to another place in the function, since "call" in the
+ indirect thunk pushes the return address onto stack, destroying
+ red-zone.
+
+ TODO: If we can reserve the first 2 WORDs, for PUSH and, another
+ for CALL, in red-zone, we can allow local indirect jumps with
+ indirect thunk. */
bool
ix86_using_red_zone (void)
{
- return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
+ return (TARGET_RED_ZONE
+ && !TARGET_64BIT_MS_ABI
+ && (!cfun->machine->has_local_indirect_jump
+ || cfun->machine->indirect_branch_type == indirect_branch_keep));
}
/* Return a string that documents the current -m options. The caller is
@@ -6398,6 +6362,88 @@ ix86_reset_previous_fndecl (void)
ix86_previous_fndecl = NULL_TREE;
}
+/* Set the indirect_branch_type field from the function FNDECL. */
+
+static void
+ix86_set_indirect_branch_type (tree fndecl)
+{
+ if (cfun->machine->indirect_branch_type == indirect_branch_unset)
+ {
+ tree attr = lookup_attribute ("indirect_branch",
+ DECL_ATTRIBUTES (fndecl));
+ if (attr != NULL)
+ {
+ tree args = TREE_VALUE (attr);
+ if (args == NULL)
+ gcc_unreachable ();
+ tree cst = TREE_VALUE (args);
+ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
+ cfun->machine->indirect_branch_type = indirect_branch_keep;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
+ cfun->machine->indirect_branch_type = indirect_branch_thunk;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
+ cfun->machine->indirect_branch_type = indirect_branch_thunk_inline;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
+ cfun->machine->indirect_branch_type = indirect_branch_thunk_extern;
+ else
+ gcc_unreachable ();
+ }
+ else
+ cfun->machine->indirect_branch_type = ix86_indirect_branch;
+
+ /* -mcmodel=large is not compatible with -mindirect-branch=thunk
+ nor -mindirect-branch=thunk-extern. */
+ if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+ && ((cfun->machine->indirect_branch_type
+ == indirect_branch_thunk_extern)
+ || (cfun->machine->indirect_branch_type
+ == indirect_branch_thunk)))
+ error ("%<-mindirect-branch=%s%> and %<-mcmodel=large%> are not "
+ "compatible",
+ ((cfun->machine->indirect_branch_type
+ == indirect_branch_thunk_extern)
+ ? "thunk-extern" : "thunk"));
+ }
+
+ if (cfun->machine->function_return_type == indirect_branch_unset)
+ {
+ tree attr = lookup_attribute ("function_return",
+ DECL_ATTRIBUTES (fndecl));
+ if (attr != NULL)
+ {
+ tree args = TREE_VALUE (attr);
+ if (args == NULL)
+ gcc_unreachable ();
+ tree cst = TREE_VALUE (args);
+ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
+ cfun->machine->function_return_type = indirect_branch_keep;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
+ cfun->machine->function_return_type = indirect_branch_thunk;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
+ cfun->machine->function_return_type = indirect_branch_thunk_inline;
+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
+ cfun->machine->function_return_type = indirect_branch_thunk_extern;
+ else
+ gcc_unreachable ();
+ }
+ else
+ cfun->machine->function_return_type = ix86_function_return;
+
+ /* -mcmodel=large is not compatible with -mfunction-return=thunk
+ nor -mfunction-return=thunk-extern. */
+ if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+ && ((cfun->machine->function_return_type
+ == indirect_branch_thunk_extern)
+ || (cfun->machine->function_return_type
+ == indirect_branch_thunk)))
+ error ("%<-mfunction-return=%s%> and %<-mcmodel=large%> are not "
+ "compatible",
+ ((cfun->machine->function_return_type
+ == indirect_branch_thunk_extern)
+ ? "thunk-extern" : "thunk"));
+ }
+}
+
/* Establish appropriate back-end context for processing the function
FNDECL. The argument might be NULL to indicate processing at top
level, outside of any function scope. */
@@ -6408,7 +6454,13 @@ ix86_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 == ix86_previous_fndecl)
- return;
+ {
+ /* There may be 2 function bodies for the same function FNDECL,
+ one is extern inline and one isn't. */
+ if (fndecl != NULL_TREE)
+ ix86_set_indirect_branch_type (fndecl);
+ return;
+ }
tree old_tree;
if (ix86_previous_fndecl == NULL_TREE)
@@ -6425,6 +6477,8 @@ ix86_set_current_function (tree fndecl)
return;
}
+ ix86_set_indirect_branch_type (fndecl);
+
tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
if (new_tree == NULL_TREE)
new_tree = target_option_default_node;
@@ -10935,7 +10989,6 @@ symbolic_reference_mentioned_p (rtx op)
bool
ix86_can_use_return_insn_p (void)
{
- struct ix86_frame frame;
if (! reload_completed || frame_pointer_needed)
return 0;
@@ -10945,7 +10998,8 @@ ix86_can_use_return_insn_p (void)
if (crtl->args.pops_args && crtl->args.size >= 32768)
return 0;
- ix86_compute_frame_layout (&frame);
+ ix86_compute_frame_layout ();
+ struct ix86_frame &frame = cfun->machine->frame;
return (frame.stack_pointer_offset == UNITS_PER_WORD
&& (frame.nregs + frame.nsseregs) == 0);
}
@@ -11010,6 +11064,247 @@ ix86_setup_frame_addresses (void)
# endif
#endif
+/* Label count for call and return thunks. It is used to make unique
+ labels in call and return thunks. */
+static int indirectlabelno;
+
+/* True if call thunk function is needed. */
+static bool indirect_thunk_needed = false;
+/* True if call thunk function with the BND prefix is needed. */
+static bool indirect_thunk_bnd_needed = false;
+
+/* Bit masks of integer registers, which contain branch target, used
+ by call thunk functions. */
+static int indirect_thunks_used;
+/* Bit masks of integer registers, which contain branch target, used
+ by call thunk functions with the BND prefix. */
+static int indirect_thunks_bnd_used;
+
+/* True if return thunk function is needed. */
+static bool indirect_return_needed = false;
+/* True if return thunk function with the BND prefix is needed. */
+static bool indirect_return_bnd_needed = false;
+
+/* True if return thunk function via CX is needed. */
+static bool indirect_return_via_cx;
+/* True if return thunk function via CX with the BND prefix is
+ needed. */
+static bool indirect_return_via_cx_bnd;
+
+#ifndef INDIRECT_LABEL
+# define INDIRECT_LABEL "LIND"
+#endif
+
+/* Fills in the label name that should be used for the indirect thunk. */
+
+static void
+indirect_thunk_name (char name[32], unsigned int regno,
+ bool need_bnd_p, bool ret_p)
+{
+ if (regno != INVALID_REGNUM && regno != CX_REG && ret_p)
+ gcc_unreachable ();
+
+ if (USE_HIDDEN_LINKONCE)
+ {
+ const char *bnd = need_bnd_p ? "_bnd" : "";
+ const char *ret = ret_p ? "return" : "indirect";
+ if (regno != INVALID_REGNUM)
+ {
+ const char *reg_prefix;
+ if (LEGACY_INT_REGNO_P (regno))
+ reg_prefix = TARGET_64BIT ? "r" : "e";
+ else
+ reg_prefix = "";
+ sprintf (name, "__x86_%s_thunk%s_%s%s",
+ ret, bnd, reg_prefix, reg_names[regno]);
+ }
+ else
+ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
+ }
+ else
+ {
+ if (regno != INVALID_REGNUM)
+ {
+ if (need_bnd_p)
+ ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno);
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
+ }
+ else
+ {
+ if (ret_p)
+ {
+ if (need_bnd_p)
+ ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
+ }
+ else
+ {
+ if (need_bnd_p)
+ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
+ }
+ }
+ }
+}
+
+/* Output a call and return thunk for indirect branch. If BND_P is
+ true, the BND prefix is needed. If REGNO != -1, the function
+ address is in REGNO and the call and return thunk looks like:
+
+ call L2
+ L1:
+ pause
+ jmp L1
+ L2:
+ mov %REG, (%sp)
+ ret
+
+ Otherwise, the function address is on the top of stack and the
+ call and return thunk looks like:
+
+ call L2
+ L1:
+ pause
+ jmp L1
+ L2:
+ lea WORD_SIZE(%sp), %sp
+ ret
+ */
+
+static void
+output_indirect_thunk (bool need_bnd_p, unsigned int regno)
+{
+ char indirectlabel1[32];
+ char indirectlabel2[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1, INDIRECT_LABEL,
+ indirectlabelno++);
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2, INDIRECT_LABEL,
+ indirectlabelno++);
+
+ /* Call */
+ if (need_bnd_p)
+ fputs ("\tbnd call\t", asm_out_file);
+ else
+ fputs ("\tcall\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel2);
+ fputc ('\n', asm_out_file);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
+
+ /* Pause + lfence. */
+ fprintf (asm_out_file, "\tpause\n\tlfence\n");
+
+ /* Jump. */
+ fputs ("\tjmp\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel1);
+ fputc ('\n', asm_out_file);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+ if (regno != INVALID_REGNUM)
+ {
+ /* MOV. */
+ rtx xops[2];
+ xops[0] = gen_rtx_MEM (word_mode, stack_pointer_rtx);
+ xops[1] = gen_rtx_REG (word_mode, regno);
+ output_asm_insn ("mov\t{%1, %0|%0, %1}", xops);
+ }
+ else
+ {
+ /* LEA. */
+ rtx xops[2];
+ xops[0] = stack_pointer_rtx;
+ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
+ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
+ }
+
+ if (need_bnd_p)
+ fputs ("\tbnd ret\n", asm_out_file);
+ else
+ fputs ("\tret\n", asm_out_file);
+}
+
+/* Output a funtion with a call and return thunk for indirect branch.
+ If BND_P is true, the BND prefix is needed. If REGNO != INVALID_REGNUM,
+ the function address is in REGNO. Otherwise, the function address is
+ on the top of stack. Thunk is used for function return if RET_P is
+ true. */
+
+static void
+output_indirect_thunk_function (bool need_bnd_p, unsigned int regno,
+ bool ret_p)
+{
+ char name[32];
+ tree decl;
+
+ /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
+ indirect_thunk_name (name, regno, need_bnd_p, ret_p);
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (name),
+ 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 TARGET_MACHO
+ if (TARGET_MACHO)
+ {
+ switch_to_section (darwin_sections[picbase_thunk_section]);
+ fputs ("\t.weak_definition\t", asm_out_file);
+ assemble_name (asm_out_file, name);
+ fputs ("\n\t.private_extern\t", asm_out_file);
+ assemble_name (asm_out_file, name);
+ putc ('\n', asm_out_file);
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ DECL_WEAK (decl) = 1;
+ }
+ else
+#endif
+ 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, name);
+ fputs ("\t.hidden\t", asm_out_file);
+ assemble_name (asm_out_file, name);
+ putc ('\n', asm_out_file);
+ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
+ }
+ else
+ {
+ switch_to_section (text_section);
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ }
+
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ allocate_struct_function (decl, false);
+ init_function_start (decl);
+ /* We're about to hide the function body from callees of final_* by
+ emitting it directly; tell them we're a thunk, if they care. */
+ cfun->is_thunk = true;
+ first_function_block_is_cold = false;
+ /* Make sure unwind info is emitted for the thunk if needed. */
+ final_start_function (emit_barrier (), asm_out_file, 1);
+
+ output_indirect_thunk (need_bnd_p, regno);
+
+ final_end_function ();
+ init_insn_lengths ();
+ free_after_compilation (cfun);
+ set_cfun (NULL);
+ current_function_decl = NULL;
+}
+
static int pic_labels_used;
/* Fills in the label name that should be used for a pc thunk for
@@ -11034,13 +11329,44 @@ static void
ix86_code_end (void)
{
rtx xops[2];
- int regno;
+ unsigned int regno;
+
+ if (indirect_return_needed)
+ output_indirect_thunk_function (false, INVALID_REGNUM, true);
+ if (indirect_return_bnd_needed)
+ output_indirect_thunk_function (true, INVALID_REGNUM, true);
+
+ if (indirect_return_via_cx)
+ output_indirect_thunk_function (false, CX_REG, true);
+ if (indirect_return_via_cx_bnd)
+ output_indirect_thunk_function (true, CX_REG, true);
+
+ if (indirect_thunk_needed)
+ output_indirect_thunk_function (false, INVALID_REGNUM, false);
+ if (indirect_thunk_bnd_needed)
+ output_indirect_thunk_function (true, INVALID_REGNUM, false);
+
+ for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
+ {
+ unsigned int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1;
+ if ((indirect_thunks_used & (1 << i)))
+ output_indirect_thunk_function (false, regno, false);
+
+ if ((indirect_thunks_bnd_used & (1 << i)))
+ output_indirect_thunk_function (true, regno, false);
+ }
for (regno = AX_REG; regno <= SP_REG; regno++)
{
char name[32];
tree decl;
+ if ((indirect_thunks_used & (1 << regno)))
+ output_indirect_thunk_function (false, regno, false);
+
+ if ((indirect_thunks_bnd_used & (1 << regno)))
+ output_indirect_thunk_function (true, regno, false);
+
if (!(pic_labels_used & (1 << regno)))
continue;
@@ -11356,8 +11682,8 @@ ix86_can_eliminate (const int from, const int to)
HOST_WIDE_INT
ix86_initial_elimination_offset (int from, int to)
{
- struct ix86_frame frame;
- ix86_compute_frame_layout (&frame);
+ ix86_compute_frame_layout ();
+ struct ix86_frame &frame = cfun->machine->frame;
if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
return frame.hard_frame_pointer_offset;
@@ -11396,8 +11722,9 @@ ix86_builtin_setjmp_frame_value (void)
/* Fill structure ix86_frame about frame of currently computed function. */
static void
-ix86_compute_frame_layout (struct ix86_frame *frame)
+ix86_compute_frame_layout (void)
{
+ struct ix86_frame *frame = &cfun->machine->frame;
unsigned HOST_WIDE_INT stack_alignment_needed;
HOST_WIDE_INT offset;
unsigned HOST_WIDE_INT preferred_alignment;
@@ -12680,7 +13007,6 @@ ix86_expand_prologue (void)
{
struct machine_function *m = cfun->machine;
rtx insn, t;
- struct ix86_frame frame;
HOST_WIDE_INT allocate;
bool int_registers_saved;
bool sse_registers_saved;
@@ -12703,7 +13029,8 @@ ix86_expand_prologue (void)
m->fs.sp_offset = INCOMING_FRAME_SP_OFFSET;
m->fs.sp_valid = true;
- ix86_compute_frame_layout (&frame);
+ ix86_compute_frame_layout ();
+ const struct ix86_frame &frame = cfun->machine->frame;
if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
{
@@ -13375,12 +13702,12 @@ ix86_expand_epilogue (int style)
{
struct machine_function *m = cfun->machine;
struct machine_frame_state frame_state_save = m->fs;
- struct ix86_frame frame;
bool restore_regs_via_mov;
bool using_drap;
ix86_finalize_stack_realign_flags ();
- ix86_compute_frame_layout (&frame);
+ ix86_compute_frame_layout ();
+ const struct ix86_frame &frame = cfun->machine->frame;
m->fs.sp_valid = (!frame_pointer_needed
|| (crtl->sp_is_unchanging
@@ -13422,11 +13749,13 @@ ix86_expand_epilogue (int style)
+ UNITS_PER_WORD);
}
+ HOST_WIDE_INT reg_save_offset = frame.reg_save_offset;
+
/* Special care must be taken for the normal return case of a function
using eh_return: the eax and edx registers are marked as saved, but
not restored along this path. Adjust the save location to match. */
if (crtl->calls_eh_return && style != 2)
- frame.reg_save_offset -= 2 * UNITS_PER_WORD;
+ reg_save_offset -= 2 * UNITS_PER_WORD;
/* EH_RETURN requires the use of moves to function properly. */
if (crtl->calls_eh_return)
@@ -13442,11 +13771,11 @@ ix86_expand_epilogue (int style)
else if (TARGET_EPILOGUE_USING_MOVE
&& cfun->machine->use_fast_prologue_epilogue
&& (frame.nregs > 1
- || m->fs.sp_offset != frame.reg_save_offset))
+ || m->fs.sp_offset != reg_save_offset))
restore_regs_via_mov = true;
else if (frame_pointer_needed
&& !frame.nregs
- && m->fs.sp_offset != frame.reg_save_offset)
+ && m->fs.sp_offset != reg_save_offset)
restore_regs_via_mov = true;
else if (frame_pointer_needed
&& TARGET_USE_LEAVE
@@ -13484,7 +13813,7 @@ ix86_expand_epilogue (int style)
rtx t;
if (frame.nregs)
- ix86_emit_restore_regs_using_mov (frame.reg_save_offset, style == 2);
+ ix86_emit_restore_regs_using_mov (reg_save_offset, style == 2);
/* eh_return epilogues need %ecx added to the stack pointer. */
if (style == 2)
@@ -13574,19 +13903,19 @@ ix86_expand_epilogue (int style)
epilogues. */
if (!m->fs.sp_valid
|| (TARGET_SEH
- && (m->fs.sp_offset - frame.reg_save_offset
+ && (m->fs.sp_offset - reg_save_offset
>= SEH_MAX_FRAME_SIZE)))
{
pro_epilogue_adjust_stack (stack_pointer_rtx, hard_frame_pointer_rtx,
GEN_INT (m->fs.fp_offset
- - frame.reg_save_offset),
+ - reg_save_offset),
style, false);
}
- else if (m->fs.sp_offset != frame.reg_save_offset)
+ else if (m->fs.sp_offset != reg_save_offset)
{
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (m->fs.sp_offset
- - frame.reg_save_offset),
+ - reg_save_offset),
style,
m->fs.cfa_reg == stack_pointer_rtx);
}
@@ -13865,7 +14194,6 @@ static GTY(()) rtx split_stack_fn_large;
void
ix86_expand_split_stack_prologue (void)
{
- struct ix86_frame frame;
HOST_WIDE_INT allocate;
unsigned HOST_WIDE_INT args_size;
rtx_code_label *label;
@@ -13877,7 +14205,8 @@ ix86_expand_split_stack_prologue (void)
gcc_assert (flag_split_stack && reload_completed);
ix86_finalize_stack_realign_flags ();
- ix86_compute_frame_layout (&frame);
+ ix86_compute_frame_layout ();
+ struct ix86_frame &frame = cfun->machine->frame;
allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
/* This is the label we will branch to if we have enough stack
@@ -16557,6 +16886,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
If CODE is 'h', pretend the reg is the 'high' byte register.
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
If CODE is 'd', duplicate the operand for AVX instruction.
+ If CODE is 'V', print naked full integer register name without %.
*/
void
@@ -16567,7 +16897,7 @@ print_reg (rtx x, int code, FILE *file)
unsigned int regno;
bool duplicated;
- if (ASSEMBLER_DIALECT == ASM_ATT)
+ if (ASSEMBLER_DIALECT == ASM_ATT && code != 'V')
putc ('%', file);
if (x == pc_rtx)
@@ -16610,6 +16940,14 @@ print_reg (rtx x, int code, FILE *file)
&& regno != FPSR_REG
&& regno != FPCR_REG);
+ if (code == 'V')
+ {
+ if (GENERAL_REGNO_P (regno))
+ msize = GET_MODE_SIZE (word_mode);
+ else
+ error ("'V' modifier on non-integer register");
+ }
+
duplicated = code == 'd' && TARGET_AVX;
switch (msize)
@@ -16723,6 +17061,7 @@ print_reg (rtx x, int code, FILE *file)
& -- print some in-use local-dynamic symbol name.
H -- print a memory address offset by 8; used for sse high-parts
Y -- print condition for XOP pcom* instruction.
+ V -- print naked full integer register name without %.
+ -- print a branch hint as 'cs' or 'ds' prefix
; -- print a semicolon (after prefixes due to bug in older gas).
~ -- print "i" if TARGET_AVX2, "f" otherwise.
@@ -16947,6 +17286,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
case 'X':
case 'P':
case 'p':
+ case 'V':
break;
case 's':
@@ -27414,12 +27754,412 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
return false;
}
+/* Output indirect branch via a call and return thunk. CALL_OP is a
+ register which contains the branch target. XASM is the assembly
+ template for CALL_OP. Branch is a tail call if SIBCALL_P is true.
+ A normal call is converted to:
+
+ call __x86_indirect_thunk_reg
+
+ and a tail call is converted to:
+
+ jmp __x86_indirect_thunk_reg
+ */
+
+static void
+ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
+{
+ char thunk_name_buf[32];
+ char *thunk_name;
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+ int regno = REGNO (call_op);
+
+ if (cfun->machine->indirect_branch_type
+ != indirect_branch_thunk_inline)
+ {
+ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
+ {
+ int i = regno;
+ if (i >= FIRST_REX_INT_REG)
+ i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
+ if (need_bnd_p)
+ indirect_thunks_bnd_used |= 1 << i;
+ else
+ indirect_thunks_used |= 1 << i;
+ }
+ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
+ thunk_name = thunk_name_buf;
+ }
+ else
+ thunk_name = NULL;
+
+ if (sibcall_p)
+ {
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ else
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+ output_indirect_thunk (need_bnd_p, regno);
+ }
+ else
+ {
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+ fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name);
+ else
+ fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
+ return;
+ }
+
+ char indirectlabel1[32];
+ char indirectlabel2[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
+ INDIRECT_LABEL,
+ indirectlabelno++);
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
+ INDIRECT_LABEL,
+ indirectlabelno++);
+
+ /* Jump. */
+ if (need_bnd_p)
+ fputs ("\tbnd jmp\t", asm_out_file);
+ else
+ fputs ("\tjmp\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel2);
+ fputc ('\n', asm_out_file);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
+
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ else
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+ output_indirect_thunk (need_bnd_p, regno);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+ /* Call. */
+ if (need_bnd_p)
+ fputs ("\tbnd call\t", asm_out_file);
+ else
+ fputs ("\tcall\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel1);
+ fputc ('\n', asm_out_file);
+ }
+}
+
+/* Output indirect branch via a call and return thunk. CALL_OP is
+ the branch target. XASM is the assembly template for CALL_OP.
+ Branch is a tail call if SIBCALL_P is true. A normal call is
+ converted to:
+
+ jmp L2
+ L1:
+ push CALL_OP
+ jmp __x86_indirect_thunk
+ L2:
+ call L1
+
+ and a tail call is converted to:
+
+ push CALL_OP
+ jmp __x86_indirect_thunk
+ */
+
+static void
+ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
+ bool sibcall_p)
+{
+ char thunk_name_buf[32];
+ char *thunk_name;
+ char push_buf[64];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+ int regno = -1;
+
+ if (cfun->machine->indirect_branch_type
+ != indirect_branch_thunk_inline)
+ {
+ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
+ {
+ if (need_bnd_p)
+ indirect_thunk_bnd_needed = true;
+ else
+ indirect_thunk_needed = true;
+ }
+ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
+ thunk_name = thunk_name_buf;
+ }
+ else
+ thunk_name = NULL;
+
+ snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
+ TARGET_64BIT ? 'q' : 'l', xasm);
+
+ if (sibcall_p)
+ {
+ output_asm_insn (push_buf, &call_op);
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ else
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+ output_indirect_thunk (need_bnd_p, regno);
+ }
+ else
+ {
+ char indirectlabel1[32];
+ char indirectlabel2[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
+ INDIRECT_LABEL,
+ indirectlabelno++);
+ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
+ INDIRECT_LABEL,
+ indirectlabelno++);
+
+ /* Jump. */
+ if (need_bnd_p)
+ fputs ("\tbnd jmp\t", asm_out_file);
+ else
+ fputs ("\tjmp\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel2);
+ fputc ('\n', asm_out_file);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
+
+ /* An external function may be called via GOT, instead of PLT. */
+ if (MEM_P (call_op))
+ {
+ struct ix86_address parts;
+ rtx addr = XEXP (call_op, 0);
+ if (ix86_decompose_address (addr, &parts)
+ && parts.base == stack_pointer_rtx)
+ {
+ /* Since call will adjust stack by -UNITS_PER_WORD,
+ we must convert "disp(stack, index, scale)" to
+ "disp+UNITS_PER_WORD(stack, index, scale)". */
+ if (parts.index)
+ {
+ addr = gen_rtx_MULT (Pmode, parts.index,
+ GEN_INT (parts.scale));
+ addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ addr);
+ }
+ else
+ addr = stack_pointer_rtx;
+
+ rtx disp;
+ if (parts.disp != NULL_RTX)
+ disp = plus_constant (Pmode, parts.disp,
+ UNITS_PER_WORD);
+ else
+ disp = GEN_INT (UNITS_PER_WORD);
+
+ addr = gen_rtx_PLUS (Pmode, addr, disp);
+ call_op = gen_rtx_MEM (GET_MODE (call_op), addr);
+ }
+ }
+
+ output_asm_insn (push_buf, &call_op);
+
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ else
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+ output_indirect_thunk (need_bnd_p, regno);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+ /* Call. */
+ if (need_bnd_p)
+ fputs ("\tbnd call\t", asm_out_file);
+ else
+ fputs ("\tcall\t", asm_out_file);
+ assemble_name_raw (asm_out_file, indirectlabel1);
+ fputc ('\n', asm_out_file);
+ }
+}
+
+/* Output indirect branch via a call and return thunk. CALL_OP is
+ the branch target. XASM is the assembly template for CALL_OP.
+ Branch is a tail call if SIBCALL_P is true. */
+
+static void
+ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ bool sibcall_p)
+{
+ if (REG_P (call_op))
+ ix86_output_indirect_branch_via_reg (call_op, sibcall_p);
+ else
+ ix86_output_indirect_branch_via_push (call_op, xasm, sibcall_p);
+}
+
+/* Output indirect jump. CALL_OP is the jump target. */
+
+const char *
+ix86_output_indirect_jmp (rtx call_op)
+{
+ if (cfun->machine->indirect_branch_type != indirect_branch_keep)
+ {
+ /* We can't have red-zone since "call" in the indirect thunk
+ pushes the return address onto stack, destroying red-zone. */
+ if (ix86_red_zone_size != 0)
+ gcc_unreachable ();
+
+ ix86_output_indirect_branch (call_op, "%0", true);
+ return "";
+ }
+ else
+ return "%!jmp\t%A0";
+}
+
+/* Output function return. CALL_OP is the jump target. Add a REP
+ prefix to RET if LONG_P is true and function return is kept. */
+
+const char *
+ix86_output_function_return (bool long_p)
+{
+ if (cfun->machine->function_return_type != indirect_branch_keep)
+ {
+ char thunk_name[32];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+
+ if (cfun->machine->function_return_type
+ != indirect_branch_thunk_inline)
+ {
+ bool need_thunk = (cfun->machine->function_return_type
+ == indirect_branch_thunk);
+ indirect_thunk_name (thunk_name, INVALID_REGNUM, need_bnd_p,
+ true);
+ if (need_bnd_p)
+ {
+ indirect_return_bnd_needed |= need_thunk;
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ }
+ else
+ {
+ indirect_return_needed |= need_thunk;
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ }
+ else
+ output_indirect_thunk (need_bnd_p, INVALID_REGNUM);
+
+ return "";
+ }
+
+ if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
+ return "%!ret";
+
+ return "rep%; ret";
+}
+
+/* Output indirect function return. RET_OP is the function return
+ target. */
+
+const char *
+ix86_output_indirect_function_return (rtx ret_op)
+{
+ if (cfun->machine->function_return_type != indirect_branch_keep)
+ {
+ char thunk_name[32];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+ unsigned int regno = REGNO (ret_op);
+ gcc_assert (regno == CX_REG);
+
+ if (cfun->machine->function_return_type
+ != indirect_branch_thunk_inline)
+ {
+ bool need_thunk = (cfun->machine->function_return_type
+ == indirect_branch_thunk);
+ indirect_thunk_name (thunk_name, regno, need_bnd_p, true);
+ if (need_bnd_p)
+ {
+ if (need_thunk)
+ {
+ indirect_return_via_cx_bnd = true;
+ indirect_thunks_bnd_used |= 1 << CX_REG;
+ }
+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
+ }
+ else
+ {
+ if (need_thunk)
+ {
+ indirect_return_via_cx = true;
+ indirect_thunks_used |= 1 << CX_REG;
+ }
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ }
+ else
+ output_indirect_thunk (need_bnd_p, regno);
+
+ return "";
+ }
+ else
+ return "%!jmp\t%A0";
+}
+
+/* Split simple return with popping POPC bytes from stack to indirect
+ branch with stack adjustment . */
+
+void
+ix86_split_simple_return_pop_internal (rtx popc)
+{
+ struct machine_function *m = cfun->machine;
+ rtx ecx = gen_rtx_REG (SImode, CX_REG);
+ rtx_insn *insn;
+
+ /* There is no "pascal" calling convention in any 64bit ABI. */
+ gcc_assert (!TARGET_64BIT);
+
+ insn = emit_insn (gen_pop (ecx));
+ m->fs.cfa_offset -= UNITS_PER_WORD;
+ m->fs.sp_offset -= UNITS_PER_WORD;
+
+ rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
+ x = gen_rtx_SET (stack_pointer_rtx, x);
+ add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
+ add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
+ x = gen_rtx_SET (stack_pointer_rtx, x);
+ insn = emit_insn (x);
+ add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Now return address is in ECX. */
+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
+}
+
/* Output the assembly for a call instruction. */
const char *
ix86_output_call_insn (rtx_insn *insn, rtx call_op)
{
bool direct_p = constant_call_address_operand (call_op, VOIDmode);
+ bool output_indirect_p
+ = (!TARGET_SEH
+ && cfun->machine->indirect_branch_type != indirect_branch_keep);
bool seh_nop_p = false;
const char *xasm;
@@ -27428,7 +28168,13 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
if (direct_p)
{
if (ix86_nopic_noplt_attribute_p (call_op))
- xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ {
+ direct_p = false;
+ if (output_indirect_p)
+ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ else
+ xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ }
else
xasm = "%!jmp\t%P0";
}
@@ -27437,9 +28183,17 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
else if (TARGET_SEH)
xasm = "%!rex.W jmp\t%A0";
else
- xasm = "%!jmp\t%A0";
+ {
+ if (output_indirect_p)
+ xasm = "%0";
+ else
+ xasm = "%!jmp\t%A0";
+ }
- output_asm_insn (xasm, &call_op);
+ if (output_indirect_p && !direct_p)
+ ix86_output_indirect_branch (call_op, xasm, true);
+ else
+ output_asm_insn (xasm, &call_op);
return "";
}
@@ -27476,14 +28230,28 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
if (direct_p)
{
if (ix86_nopic_noplt_attribute_p (call_op))
- xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ {
+ direct_p = false;
+ if (output_indirect_p)
+ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ else
+ xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+ }
else
xasm = "%!call\t%P0";
}
else
- xasm = "%!call\t%A0";
+ {
+ if (output_indirect_p)
+ xasm = "%0";
+ else
+ xasm = "%!call\t%A0";
+ }
- output_asm_insn (xasm, &call_op);
+ if (output_indirect_p && !direct_p)
+ ix86_output_indirect_branch (call_op, xasm, false);
+ else
+ output_asm_insn (xasm, &call_op);
if (seh_nop_p)
return "nop";
@@ -44881,7 +45649,7 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int,
}
static tree
-ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
+ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_DECL)
@@ -44890,6 +45658,51 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
name);
*no_add_attrs = true;
}
+
+ if (is_attribute_p ("indirect_branch", name))
+ {
+ tree 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;
+ }
+ else if (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;
+ }
+ }
+
+ if (is_attribute_p ("function_return", name))
+ {
+ tree 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;
+ }
+ else if (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;
}
@@ -49117,6 +49930,11 @@ static const struct attribute_spec ix86_attribute_table[] =
false },
{ "callee_pop_aggregate_return", 1, 1, false, true, true,
ix86_handle_callee_pop_aggregate_return, true },
+ { "indirect_branch", 1, 1, true, false, false,
+ ix86_handle_fndecl_attribute, false },
+ { "function_return", 1, 1, true, false, false,
+ ix86_handle_fndecl_attribute, false },
+
/* End element. */
{ NULL, 0, 0, false, false, false, NULL, false }
};
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 8113f83c7fd..1816d710f4e 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2427,9 +2427,56 @@ enum avx_u128_state
#define FASTCALL_PREFIX '@'
+#ifndef USED_FOR_TARGET
+/* Structure describing stack frame layout.
+ Stack grows downward:
+
+ [arguments]
+ <- ARG_POINTER
+ saved pc
+
+ saved static chain if ix86_static_chain_on_stack
+
+ saved frame pointer if frame_pointer_needed
+ <- HARD_FRAME_POINTER
+ [saved regs]
+ <- regs_save_offset
+ [padding0]
+
+ [saved SSE regs]
+ <- sse_regs_save_offset
+ [padding1] |
+ | <- FRAME_POINTER
+ [va_arg registers] |
+ |
+ [frame] |
+ |
+ [padding2] | = to_allocate
+ <- STACK_POINTER
+ */
+struct GTY(()) ix86_frame
+{
+ int nsseregs;
+ int nregs;
+ int va_arg_size;
+ int red_zone_size;
+ int outgoing_arguments_size;
+
+ /* The offsets relative to ARG_POINTER. */
+ HOST_WIDE_INT frame_pointer_offset;
+ HOST_WIDE_INT hard_frame_pointer_offset;
+ HOST_WIDE_INT stack_pointer_offset;
+ HOST_WIDE_INT hfp_save_offset;
+ HOST_WIDE_INT reg_save_offset;
+ HOST_WIDE_INT sse_reg_save_offset;
+
+ /* When save_regs_using_mov is set, emit prologue using
+ move instead of push instructions. */
+ bool save_regs_using_mov;
+};
+
/* Machine specific frame tracking during prologue/epilogue generation. */
-#ifndef USED_FOR_TARGET
struct GTY(()) machine_frame_state
{
/* This pair tracks the currently active CFA as reg+offset. When reg
@@ -2475,6 +2522,9 @@ struct GTY(()) machine_function {
int varargs_fpr_size;
int optimize_mode_switching[MAX_386_ENTITIES];
+ /* Cached initial frame layout for the current function. */
+ struct ix86_frame frame;
+
/* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE
has been computed for. */
int use_fast_prologue_epilogue_nregs;
@@ -2522,6 +2572,16 @@ struct GTY(()) machine_function {
/* If true, it is safe to not save/restore DRAP register. */
BOOL_BITFIELD no_drap_save_restore : 1;
+ /* How to generate indirec branch. */
+ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
+
+ /* If true, the current function has local indirect jumps, like
+ "indirect_jump" or "tablejump". */
+ BOOL_BITFIELD has_local_indirect_jump : 1;
+
+ /* How to generate function return. */
+ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
+
/* If true, there is register available for argument passing. This
is used only in ix86_function_ok_for_sibcall by 32-bit to determine
if there is scratch register available for indirect sibcall. In
@@ -2554,6 +2614,7 @@ struct GTY(()) machine_function {
#define ix86_current_function_calls_tls_descriptor \
(ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
#define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
+#define ix86_red_zone_size (cfun->machine->frame.red_zone_size)
/* Control behavior of x86_file_start. */
#define X86_FILE_START_VERSION_DIRECTIVE false
@@ -2615,6 +2676,11 @@ extern void debug_dispatch_window (int);
#define TARGET_RECIP_VEC_DIV ((recip_mask & RECIP_MASK_VEC_DIV) != 0)
#define TARGET_RECIP_VEC_SQRT ((recip_mask & RECIP_MASK_VEC_SQRT) != 0)
+
+#define TARGET_INDIRECT_BRANCH_REGISTER \
+ (ix86_indirect_branch_register \
+ || cfun->machine->indirect_branch_type != indirect_branch_keep)
+
#define IX86_HLE_ACQUIRE (1 << 16)
#define IX86_HLE_RELEASE (1 << 17)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d2bfe314f71..9db79988ceb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -741,7 +741,7 @@
(if_then_else (match_operand 1 "constant_call_address_operand")
(const_string "none")
(const_string "load"))
- (and (eq_attr "type" "alu1,negnot,ishift1,sselog1,sseshuf1")
+ (and (eq_attr "type" "alu1,negnot,ishift1,rotate1,sselog1,sseshuf1")
(match_operand 1 "memory_operand"))
(const_string "both")
(and (match_operand 0 "memory_operand")
@@ -752,7 +752,7 @@
(match_operand 1 "memory_operand")
(const_string "load")
(and (eq_attr "type"
- "!alu1,negnot,ishift1,
+ "!alu1,negnot,ishift1,rotate1,
imov,imovx,icmp,test,bitmanip,
fmov,fcmp,fsgn,
sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
@@ -11805,15 +11805,20 @@
[(set (pc) (match_operand 0 "indirect_branch_operand"))]
""
{
- if (TARGET_X32)
+ if (TARGET_X32 || TARGET_INDIRECT_BRANCH_REGISTER)
operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
})
(define_insn "*indirect_jump"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
""
- "%!jmp\t%A0"
- [(set_attr "type" "ibr")
+ "* return ix86_output_indirect_jmp (operands[0]);"
+ [(set (attr "type")
+ (if_then_else (match_test "(cfun->machine->indirect_branch_type
+ != indirect_branch_keep)")
+ (const_string "multi")
+ (const_string "ibr")))
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
@@ -11854,16 +11859,21 @@
OPTAB_DIRECT);
}
- if (TARGET_X32)
+ if (TARGET_X32 || TARGET_INDIRECT_BRANCH_REGISTER)
operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
})
(define_insn "*tablejump_1"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
(use (label_ref (match_operand 1)))]
""
- "%!jmp\t%A0"
- [(set_attr "type" "ibr")
+ "* return ix86_output_indirect_jmp (operands[0]);"
+ [(set (attr "type")
+ (if_then_else (match_test "(cfun->machine->indirect_branch_type
+ != indirect_branch_keep)")
+ (const_string "multi")
+ (const_string "ibr")))
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
@@ -12019,7 +12029,10 @@
(match_operand:SI 0 "register_no_elim_operand" "U")
(match_operand:SI 1 "GOT32_symbol_operand"))))
(match_operand 2))]
- "!TARGET_MACHO && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "!TARGET_MACHO
+ && !TARGET_64BIT
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (insn)"
{
rtx fnaddr = gen_rtx_PLUS (Pmode, operands[0], operands[1]);
fnaddr = gen_const_mem (Pmode, fnaddr);
@@ -12038,7 +12051,7 @@
[(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
(match_operand 1))
(unspec [(const_int 0)] UNSPEC_PEEPSIB)]
- "!TARGET_X32"
+ "!TARGET_X32 && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[0]);"
[(set_attr "type" "call")])
@@ -12047,7 +12060,9 @@
(match_operand:W 1 "memory_operand"))
(call (mem:QI (match_dup 0))
(match_operand 3))]
- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
+ "!TARGET_X32
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (peep2_next_insn (1))
&& !reg_mentioned_p (operands[0],
CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
[(parallel [(call (mem:QI (match_dup 1))
@@ -12060,7 +12075,9 @@
(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
(call (mem:QI (match_dup 0))
(match_operand 3))]
- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
+ "!TARGET_X32
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (peep2_next_insn (2))
&& !reg_mentioned_p (operands[0],
CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
@@ -12082,7 +12099,7 @@
})
(define_insn "*call_pop"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
(match_operand 1))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -12102,7 +12119,7 @@
[(set_attr "type" "call")])
(define_insn "*sibcall_pop_memory"
- [(call (mem:QI (match_operand:SI 0 "memory_operand" "m"))
+ [(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
(match_operand 1))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -12156,7 +12173,9 @@
[(set (match_operand:W 0 "register_operand")
(match_operand:W 1 "memory_operand"))
(set (pc) (match_dup 0))]
- "!TARGET_X32 && peep2_reg_dead_p (2, operands[0])"
+ "!TARGET_X32
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && peep2_reg_dead_p (2, operands[0])"
[(set (pc) (match_dup 1))])
;; Call subroutine, returning value in operand 0
@@ -12213,7 +12232,10 @@
(match_operand:SI 1 "register_no_elim_operand" "U")
(match_operand:SI 2 "GOT32_symbol_operand"))))
(match_operand 3)))]
- "!TARGET_MACHO && !TARGET_64BIT && SIBLING_CALL_P (insn)"
+ "!TARGET_MACHO
+ && !TARGET_64BIT
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (insn)"
{
rtx fnaddr = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
fnaddr = gen_const_mem (Pmode, fnaddr);
@@ -12234,7 +12256,7 @@
(call (mem:QI (match_operand:W 1 "memory_operand" "m"))
(match_operand 2)))
(unspec [(const_int 0)] UNSPEC_PEEPSIB)]
- "!TARGET_X32"
+ "!TARGET_X32 && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[1]);"
[(set_attr "type" "callv")])
@@ -12244,7 +12266,9 @@
(set (match_operand 2)
(call (mem:QI (match_dup 0))
(match_operand 3)))]
- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
+ "!TARGET_X32
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (peep2_next_insn (1))
&& !reg_mentioned_p (operands[0],
CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
[(parallel [(set (match_dup 2)
@@ -12259,7 +12283,9 @@
(set (match_operand 2)
(call (mem:QI (match_dup 0))
(match_operand 3)))]
- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
+ "!TARGET_X32
+ && !TARGET_INDIRECT_BRANCH_REGISTER
+ && SIBLING_CALL_P (peep2_next_insn (2))
&& !reg_mentioned_p (operands[0],
CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
@@ -12284,7 +12310,7 @@
(define_insn "*call_value_pop"
[(set (match_operand 0)
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
(match_operand 2)))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -12479,7 +12505,7 @@
(define_insn "simple_return_internal"
[(simple_return)]
"reload_completed"
- "%!ret"
+ "* return ix86_output_function_return (false);"
[(set_attr "length" "1")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
@@ -12493,23 +12519,21 @@
[(simple_return)
(unspec [(const_int 0)] UNSPEC_REP)]
"reload_completed"
-{
- if (ix86_bnd_prefixed_insn_p (insn))
- return "%!ret";
-
- return "rep%; ret";
-}
+ "* return ix86_output_function_return (true);"
[(set_attr "length" "2")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "prefix_rep" "1")
(set_attr "modrm" "0")])
-(define_insn "simple_return_pop_internal"
+(define_insn_and_split "simple_return_pop_internal"
[(simple_return)
(use (match_operand:SI 0 "const_int_operand"))]
"reload_completed"
"%!ret\t%0"
+ "&& cfun->machine->function_return_type != indirect_branch_keep"
+ [(const_int 0)]
+ "ix86_split_simple_return_pop_internal (operands[0]); DONE;"
[(set_attr "length" "3")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "2")
@@ -12520,8 +12544,12 @@
[(simple_return)
(use (match_operand:SI 0 "register_operand" "r"))]
"reload_completed"
- "%!jmp\t%A0"
- [(set_attr "type" "ibr")
+ "* return ix86_output_indirect_function_return (operands[0]);"
+ [(set (attr "type")
+ (if_then_else (match_test "(cfun->machine->indirect_branch_type
+ != indirect_branch_keep)")
+ (const_string "multi")
+ (const_string "ibr")))
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index f304b621e6a..a97f84f68f2 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -897,3 +897,31 @@ Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
mmitigate-rop
Target Var(flag_mitigate_rop) Init(0)
Attempt to avoid generating instruction sequences containing ret bytes.
+
+mindirect-branch=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
+Convert indirect call and jump to call and return thunks.
+
+mfunction-return=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
+Convert function return to call and return thunk.
+
+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-register
+Target Report Var(ix86_indirect_branch_register) Init(0)
+Force indirect call and jump via register.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 93dda7bb0e7..5f8a98faead 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -593,7 +593,8 @@
;; Test for a valid operand for indirect branch.
(define_predicate "indirect_branch_operand"
(ior (match_operand 0 "register_operand")
- (and (not (match_test "TARGET_X32"))
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+ (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand"))))
;; Return true if OP is a memory operands that can be used in sibcalls.
@@ -636,20 +637,22 @@
(ior (match_test "constant_call_address_operand
(op, mode == VOIDmode ? mode : Pmode)")
(match_operand 0 "call_register_no_elim_operand")
- (ior (and (not (match_test "TARGET_X32"))
- (match_operand 0 "memory_operand"))
- (and (match_test "TARGET_X32 && Pmode == DImode")
- (match_operand 0 "GOT_memory_operand")))))
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+ (ior (and (not (match_test "TARGET_X32"))
+ (match_operand 0 "memory_operand"))
+ (and (match_test "TARGET_X32 && Pmode == DImode")
+ (match_operand 0 "GOT_memory_operand"))))))
;; Similarly, but for tail calls, in which we cannot allow memory references.
(define_special_predicate "sibcall_insn_operand"
(ior (match_test "constant_call_address_operand
(op, mode == VOIDmode ? mode : Pmode)")
(match_operand 0 "register_no_elim_operand")
- (ior (and (not (match_test "TARGET_X32"))
- (match_operand 0 "sibcall_memory_operand"))
- (and (match_test "TARGET_X32 && Pmode == DImode")
- (match_operand 0 "GOT_memory_operand")))))
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+ (ior (and (not (match_test "TARGET_X32"))
+ (match_operand 0 "sibcall_memory_operand"))
+ (and (match_test "TARGET_X32 && Pmode == DImode")
+ (match_operand 0 "GOT_memory_operand"))))))
;; Return true if OP is a 32-bit GOT symbol operand.
(define_predicate "GOT32_symbol_operand"
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 16e80421f69..8eb23097346 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1616,6 +1616,9 @@ static void
nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
const_tree type, HOST_WIDE_INT size, unsigned align)
{
+ bool atype = (TREE_CODE (type) == ARRAY_TYPE)
+ && (TYPE_DOMAIN (type) == NULL_TREE);
+
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
@@ -1655,6 +1658,8 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
/* We make everything an array, to simplify any initialization
emission. */
fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", init_frag.remaining);
+ else if (atype)
+ fprintf (file, "[]");
}
/* Called when the initializer for a decl has been completely output through
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 2ac2025e89d..ffa30641f8f 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -194,6 +194,8 @@ static bool pa_cannot_force_const_mem (machine_mode, rtx);
static bool pa_legitimate_constant_p (machine_mode, rtx);
static unsigned int pa_section_type_flags (tree, const char *, int);
static bool pa_legitimate_address_p (machine_mode, rtx, bool);
+static bool pa_callee_copies (cumulative_args_t, machine_mode,
+ const_tree, bool);
/* The following extra sections are only used for SOM. */
static GTY(()) section *som_readonly_data_section;
@@ -342,7 +344,7 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE pa_pass_by_reference
#undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#define TARGET_CALLEE_COPIES pa_callee_copies
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES pa_arg_partial_bytes
#undef TARGET_FUNCTION_ARG
@@ -1719,9 +1721,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
}
else
emit_move_insn (scratch_reg, XEXP (op1, 0));
- emit_insn (gen_rtx_SET (operand0,
- replace_equiv_address (op1, scratch_reg)));
- return 1;
+ op1 = replace_equiv_address (op1, scratch_reg);
}
}
else if ((!INT14_OK_STRICT && symbolic_memory_operand (op1, VOIDmode))
@@ -1731,10 +1731,10 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
/* Load memory address into SCRATCH_REG. */
scratch_reg = force_mode (word_mode, scratch_reg);
emit_move_insn (scratch_reg, XEXP (op1, 0));
- emit_insn (gen_rtx_SET (operand0,
- replace_equiv_address (op1, scratch_reg)));
- return 1;
+ op1 = replace_equiv_address (op1, scratch_reg);
}
+ emit_insn (gen_rtx_SET (operand0, op1));
+ return 1;
}
else if (scratch_reg
&& FP_REG_P (operand1)
@@ -1772,9 +1772,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
}
else
emit_move_insn (scratch_reg, XEXP (op0, 0));
- emit_insn (gen_rtx_SET (replace_equiv_address (op0, scratch_reg),
- operand1));
- return 1;
+ op0 = replace_equiv_address (op0, scratch_reg);
}
}
else if ((!INT14_OK_STRICT && symbolic_memory_operand (op0, VOIDmode))
@@ -1784,10 +1782,10 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
/* Load memory address into SCRATCH_REG. */
scratch_reg = force_mode (word_mode, scratch_reg);
emit_move_insn (scratch_reg, XEXP (op0, 0));
- emit_insn (gen_rtx_SET (replace_equiv_address (op0, scratch_reg),
- operand1));
- return 1;
+ op0 = replace_equiv_address (op0, scratch_reg);
}
+ emit_insn (gen_rtx_SET (op0, operand1));
+ return 1;
}
/* Handle secondary reloads for loads of FP registers from constant
expressions by forcing the constant into memory. For the most part,
@@ -10710,4 +10708,19 @@ pa_maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
return NULL_RTX;
}
+/* Implement TARGET_CALLEE_COPIES. The callee is responsible for copying
+ arguments passed by hidden reference in the 32-bit HP runtime. Users
+ can override this behavior for better compatibility with openmp at the
+ risk of library incompatibilities. Arguments are always passed by value
+ in the 64-bit HP runtime. */
+
+static bool
+pa_callee_copies (cumulative_args_t cum ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+ return !TARGET_CALLER_COPIES;
+}
+
#include "gt-pa.h"
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 742d0f9b569..c58bd87fdb5 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1159,8 +1159,18 @@ do { \
PREFIX is the class of label and NUM is the number within the class.
This is suitable for output with `assemble_name'. */
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*%c$%s%04ld", (PREFIX)[0], (PREFIX) + 1, (long)(NUM))
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ do \
+ { \
+ char *__p; \
+ (LABEL)[0] = '*'; \
+ (LABEL)[1] = (PREFIX)[0]; \
+ (LABEL)[2] = '$'; \
+ __p = stpcpy (&(LABEL)[3], &(PREFIX)[1]); \
+ sprint_ul (__p, (unsigned long) (NUM)); \
+ } \
+ while (0)
+
/* Output the definition of a compiler-generated label named NAME. */
@@ -1199,14 +1209,14 @@ do { \
/* This is how to output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "\t.word L$%04d\n", VALUE)
+ fprintf (FILE, "\t.word L$%d\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
Since we always place jump tables in the text section, the difference
is absolute and requires no relocation. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- fprintf (FILE, "\t.word L$%04d-L$%04d\n", VALUE, REL)
+ fprintf (FILE, "\t.word L$%d-L$%d\n", VALUE, REL)
/* This is how to output an absolute case-vector. */
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 8ac0192844b..29a0749f7a3 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -2536,24 +2536,40 @@
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = gen_label_rtx ();
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (xoperands[2]));
- output_asm_insn (\"mfia %0\", xoperands);
-
- /* If we're trying to load the address of a label that happens to be
- close, then we can use a shorter sequence. */
if (GET_CODE (operands[1]) == LABEL_REF
- && !LABEL_REF_NONLOCAL_P (operands[1])
- && INSN_ADDRESSES_SET_P ()
- && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
- - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
- output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ && !LABEL_REF_NONLOCAL_P (operands[1]))
+ {
+ xoperands[2] = gen_label_rtx ();
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[2]));
+ output_asm_insn (\"mfia %0\", xoperands);
+
+ /* If we're trying to load the address of a label that happens to be
+ close, then we can use a shorter sequence. */
+ if (INSN_ADDRESSES_SET_P ()
+ && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+ output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ else
+ {
+ output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+ output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ }
+ }
else
{
- output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
- output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ /* Load using linkage table. */
+ if (TARGET_64BIT)
+ {
+ output_asm_insn (\"addil LT%%%1,%%r27\", xoperands);
+ output_asm_insn (\"ldd RT%%%1(%0),%0\", xoperands);
+ }
+ else
+ {
+ output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+ output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
+ }
}
return \"\";
}"
@@ -2570,25 +2586,33 @@
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = gen_label_rtx ();
- output_asm_insn (\"bl .+8,%0\", xoperands);
- output_asm_insn (\"depi 0,31,2,%0\", xoperands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (xoperands[2]));
-
- /* If we're trying to load the address of a label that happens to be
- close, then we can use a shorter sequence. */
if (GET_CODE (operands[1]) == LABEL_REF
- && !LABEL_REF_NONLOCAL_P (operands[1])
- && INSN_ADDRESSES_SET_P ()
- && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
- - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
- output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ && !LABEL_REF_NONLOCAL_P (operands[1]))
+ {
+ xoperands[2] = gen_label_rtx ();
+ output_asm_insn (\"bl .+8,%0\", xoperands);
+ output_asm_insn (\"depi 0,31,2,%0\", xoperands);
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[2]));
+
+ /* If we're trying to load the address of a label that happens to be
+ close, then we can use a shorter sequence. */
+ if (INSN_ADDRESSES_SET_P ()
+ && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+ output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ else
+ {
+ output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+ output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ }
+ }
else
{
- output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
- output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ /* Load using linkage table. */
+ output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+ output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
}
return \"\";
}"
diff --git a/gcc/config/pa/pa.opt b/gcc/config/pa/pa.opt
index 9370b40ae80..c15353de353 100644
--- a/gcc/config/pa/pa.opt
+++ b/gcc/config/pa/pa.opt
@@ -41,6 +41,10 @@ mbig-switch
Target Ignore
Does nothing. Preserved for backward compatibility.
+mcaller-copies
+Target Report Mask(CALLER_COPIES)
+Caller copies function arguments passed by hidden reference.
+
mdisable-fpregs
Target Report Mask(DISABLE_FPREGS)
Disable FP regs.
diff --git a/gcc/config/pa/pa64-hpux.h b/gcc/config/pa/pa64-hpux.h
index 279406a01fb..90924c92aa7 100644
--- a/gcc/config/pa/pa64-hpux.h
+++ b/gcc/config/pa/pa64-hpux.h
@@ -247,8 +247,18 @@ do { \
/* We need to use the HP style for internal labels. */
#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
- sprintf (LABEL, "*%c$%s%04ld", (PREFIX)[0], (PREFIX) + 1, (long)(NUM))
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ do \
+ { \
+ char *__p; \
+ (LABEL)[0] = '*'; \
+ (LABEL)[1] = (PREFIX)[0]; \
+ (LABEL)[2] = '$'; \
+ __p = stpcpy (&(LABEL)[3], &(PREFIX)[1]); \
+ sprint_ul (__p, (unsigned long) (NUM)); \
+ } \
+ while (0)
+
#else /* USING_ELFOS_H */
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index a33faa6e5bc..5702ba622cb 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1,5 +1,5 @@
/* Builtin functions for rs6000/powerpc.
- Copyright (C) 2009-2016 Free Software Foundation, Inc.
+ Copyright (C) 2009-2018 Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
This file is part of GCC.
@@ -630,6 +630,14 @@
| RS6000_BTC_BINARY), \
CODE_FOR_ ## ICODE) /* ICODE */
+#define BU_P7_POWERPC64_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_POPCNTD /* MASK */ \
+ | RS6000_BTM_POWERPC64, \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
/* Miscellaneous builtins for instructions added in ISA 2.07. These
instructions do require the ISA 2.07 vector support, but they aren't vector
@@ -1801,13 +1809,9 @@ BU_P9V_OVERLOAD_2 (VADUW, "vaduw")
/* 2 argument extended divide functions added in ISA 2.06. */
BU_P7_MISC_2 (DIVWE, "divwe", CONST, dive_si)
-BU_P7_MISC_2 (DIVWEO, "divweo", CONST, diveo_si)
BU_P7_MISC_2 (DIVWEU, "divweu", CONST, diveu_si)
-BU_P7_MISC_2 (DIVWEUO, "divweuo", CONST, diveuo_si)
-BU_P7_MISC_2 (DIVDE, "divde", CONST, dive_di)
-BU_P7_MISC_2 (DIVDEO, "divdeo", CONST, diveo_di)
-BU_P7_MISC_2 (DIVDEU, "divdeu", CONST, diveu_di)
-BU_P7_MISC_2 (DIVDEUO, "divdeuo", CONST, diveuo_di)
+BU_P7_POWERPC64_MISC_2 (DIVDE, "divde", CONST, dive_di)
+BU_P7_POWERPC64_MISC_2 (DIVDEU, "divdeu", CONST, diveu_di)
/* 1 argument DFP (decimal floating point) functions added in ISA 2.05. */
BU_DFP_MISC_1 (DXEX, "dxex", CONST, dfp_dxex_dd)
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 74f7bd522dc..4a9a4794dcd 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -4919,6 +4919,15 @@ assignment for unaligned loads and stores");
stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1);
stmt = build_indirect_ref (loc, stmt, RO_NULL);
+ /* PR83660: We mark this as having side effects so that
+ downstream in fold_build_cleanup_point_expr () it will get a
+ CLEANUP_POINT_EXPR. If it does not we can run into an ICE
+ later in gimplify_cleanup_point_expr (). Potentially this
+ causes missed optimization because the actually is no side
+ effect. */
+ if (c_dialect_cxx ())
+ TREE_SIDE_EFFECTS (stmt) = 1;
+
return stmt;
}
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index bfa1df042fe..d7ee96901a0 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on IBM RS/6000.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -3775,6 +3775,7 @@ rs6000_builtin_mask_calculate (void)
| ((TARGET_P9_MISC) ? RS6000_BTM_P9_MISC : 0)
| ((TARGET_MODULO) ? RS6000_BTM_MODULO : 0)
| ((TARGET_64BIT) ? RS6000_BTM_64BIT : 0)
+ | ((TARGET_POWERPC64) ? RS6000_BTM_POWERPC64 : 0)
| ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)
| ((TARGET_HTM) ? RS6000_BTM_HTM : 0)
| ((TARGET_DFP) ? RS6000_BTM_DFP : 0)
@@ -15648,6 +15649,11 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("Builtin function %s requires the -mhard-float option", name);
else if ((fnmask & RS6000_BTM_FLOAT128) != 0)
error ("Builtin function %s requires the -mfloat128 option", name);
+ else if ((fnmask & (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64))
+ == (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64))
+ error ("builtin function %qs requires the %qs (or newer), and "
+ "%qs or %qs options",
+ name, "-mcpu=power7", "-m64", "-mpowerpc64");
else
error ("Builtin function %s is not supported with the current options",
name);
@@ -17233,9 +17239,7 @@ builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0,
case CRYPTO_BUILTIN_VPMSUM:
case MISC_BUILTIN_ADDG6S:
case MISC_BUILTIN_DIVWEU:
- case MISC_BUILTIN_DIVWEUO:
case MISC_BUILTIN_DIVDEU:
- case MISC_BUILTIN_DIVDEUO:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
h.uns_p[2] = 1;
@@ -32777,6 +32781,11 @@ rs6000_elf_in_small_data_p (const_tree decl)
}
else
{
+ /* If we are told not to put readonly data in sdata, then don't. */
+ if (TREE_READONLY (decl) && rs6000_sdata != SDATA_EABI
+ && !rs6000_readonly_in_sdata)
+ return false;
+
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
if (size > 0
@@ -36052,6 +36061,7 @@ static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
{ "hard-dfp", RS6000_BTM_DFP, false, false },
{ "hard-float", RS6000_BTM_HARD_FLOAT, false, false },
{ "long-double-128", RS6000_BTM_LDBL128, false, false },
+ { "powerpc64", RS6000_BTM_POWERPC64, false, false },
{ "float128", RS6000_BTM_FLOAT128, false, false },
};
@@ -38708,6 +38718,7 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
case UNSPEC_VPERM_UNS:
case UNSPEC_VPERMHI:
case UNSPEC_VPERMSI:
+ case UNSPEC_VPERMXOR:
case UNSPEC_VPKPX:
case UNSPEC_VSLDOI:
case UNSPEC_VSLO:
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 9aba7529e86..feed20897f1 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2018 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -2721,6 +2721,7 @@ extern int frame_pointer_needed;
#define RS6000_BTM_HARD_FLOAT MASK_SOFT_FLOAT /* Hardware floating point. */
#define RS6000_BTM_LDBL128 MASK_MULTIPLE /* 128-bit long double. */
#define RS6000_BTM_64BIT MASK_64BIT /* 64-bit addressing. */
+#define RS6000_BTM_POWERPC64 MASK_POWERPC64 /* 64-bit registers. */
#define RS6000_BTM_FLOAT128 MASK_FLOAT128 /* IEEE 128-bit float. */
#define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \
@@ -2740,6 +2741,7 @@ extern int frame_pointer_needed;
| RS6000_BTM_DFP \
| RS6000_BTM_HARD_FLOAT \
| RS6000_BTM_LDBL128 \
+ | RS6000_BTM_POWERPC64 \
| RS6000_BTM_FLOAT128)
/* Define builtin enum index. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 5cb37463cf6..db57d662568 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1,5 +1,5 @@
;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
-;; Copyright (C) 1990-2017 Free Software Foundation, Inc.
+;; Copyright (C) 1990-2018 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;; This file is part of GCC.
@@ -134,9 +134,7 @@
UNSPEC_CDTBCD
UNSPEC_CBCDTD
UNSPEC_DIVE
- UNSPEC_DIVEO
UNSPEC_DIVEU
- UNSPEC_DIVEUO
UNSPEC_UNPACK_128BIT
UNSPEC_PACK_128BIT
UNSPEC_LSQ
@@ -13290,14 +13288,10 @@
(set_attr "length" "4")])
(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE
- UNSPEC_DIVEO
- UNSPEC_DIVEU
- UNSPEC_DIVEUO])
+ UNSPEC_DIVEU])
(define_int_attr div_extend [(UNSPEC_DIVE "e")
- (UNSPEC_DIVEO "eo")
- (UNSPEC_DIVEU "eu")
- (UNSPEC_DIVEUO "euo")])
+ (UNSPEC_DIVEU "eu")])
(define_insn "div<div_extend>_<mode>"
[(set (match_operand:GPR 0 "register_operand" "=r")
diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt
index 581fcde4c55..18995281a8a 100644
--- a/gcc/config/rs6000/sysv4.opt
+++ b/gcc/config/rs6000/sysv4.opt
@@ -27,6 +27,10 @@ msdata=
Target RejectNegative Joined Var(rs6000_sdata_name)
Select method for sdata handling.
+mreadonly-in-sdata
+Target Report Var(rs6000_readonly_in_sdata) Init(1) Save
+Allow readonly data in sdata.
+
mtls-size=
Target RejectNegative Joined Var(rs6000_tls_size) Enum(rs6000_tls_size)
Specify bit size of immediate TLS offsets.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b061a680680..e5ff59407c1 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -15429,7 +15429,7 @@ s390_output_indirect_thunk_function (unsigned int regno, bool z10_p)
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)
+ if (flag_asynchronous_unwind_tables && flag_dwarf2_cfi_asm)
{
fputs ("\t.cfi_signal_frame\n", asm_out_file);
fprintf (asm_out_file, "\t.cfi_return_column %d\n", regno);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 48813f8a52c..6a73452ce59 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -1838,7 +1838,7 @@ sparc_expand_move (machine_mode mode, rtx *operands)
}
}
- /* Fixup TLS cases. */
+ /* Fix up TLS cases. */
if (TARGET_HAVE_TLS
&& CONSTANT_P (operands[1])
&& sparc_tls_referenced_p (operands [1]))
@@ -1847,15 +1847,20 @@ sparc_expand_move (machine_mode mode, rtx *operands)
return false;
}
- /* Fixup PIC cases. */
+ /* Fix up PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
if (pic_address_needs_scratch (operands[1]))
operands[1] = sparc_legitimize_pic_address (operands[1], NULL_RTX);
/* We cannot use the mov{si,di}_pic_label_ref patterns in all cases. */
- if (GET_CODE (operands[1]) == LABEL_REF
- && can_use_mov_pic_label_ref (operands[1]))
+ if ((GET_CODE (operands[1]) == LABEL_REF
+ && can_use_mov_pic_label_ref (operands[1]))
+ || (GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
+ && can_use_mov_pic_label_ref (XEXP (XEXP (operands[1], 0), 0))))
{
if (mode == SImode)
{
@@ -1865,7 +1870,6 @@ sparc_expand_move (machine_mode mode, rtx *operands)
if (mode == DImode)
{
- gcc_assert (TARGET_ARCH64);
emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
return true;
}
@@ -3852,10 +3856,11 @@ int
pic_address_needs_scratch (rtx x)
{
/* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
- if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
+ && !SMALL_INT (XEXP (XEXP (x, 0), 1)))
return 1;
return 0;
@@ -4296,16 +4301,15 @@ sparc_legitimize_tls_address (rtx addr)
static rtx
sparc_legitimize_pic_address (rtx orig, rtx reg)
{
- bool gotdata_op = false;
-
if (GET_CODE (orig) == SYMBOL_REF
/* See the comment in sparc_expand_move. */
|| (GET_CODE (orig) == LABEL_REF && !can_use_mov_pic_label_ref (orig)))
{
+ bool gotdata_op = false;
rtx pic_ref, address;
rtx_insn *insn;
- if (reg == 0)
+ if (!reg)
{
gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
@@ -4316,8 +4320,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
/* If not during reload, allocate another temp reg here for loading
in the address, so that these instructions can be optimized
properly. */
- rtx temp_reg = (! can_create_pseudo_p ()
- ? reg : gen_reg_rtx (Pmode));
+ rtx temp_reg = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : reg;
/* Must put the SYMBOL_REF inside an UNSPEC here so that cse
won't get confused into thinking that these two instructions
@@ -4333,6 +4336,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
emit_insn (gen_movsi_high_pic (temp_reg, orig));
emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
}
+
address = temp_reg;
gotdata_op = true;
}
@@ -4373,7 +4377,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
return orig;
- if (reg == 0)
+ if (!reg)
{
gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
@@ -4482,7 +4486,11 @@ sparc_delegitimize_address (rtx x)
&& XINT (XEXP (XEXP (x, 1), 1), 1) == UNSPEC_MOVE_PIC_LABEL)
{
x = XVECEXP (XEXP (XEXP (x, 1), 1), 0, 0);
- gcc_assert (GET_CODE (x) == LABEL_REF);
+ gcc_assert (GET_CODE (x) == LABEL_REF
+ || (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT));
}
return x;
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index cae6547bab7..34d01b49a62 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1525,7 +1525,7 @@
(define_expand "movsi_pic_label_ref"
[(set (match_dup 3) (high:SI
- (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
(match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:SI (match_dup 3)
(unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
@@ -1551,7 +1551,7 @@
(define_insn "*movsi_high_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI
- (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
(match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
"sethi\t%%hi(%a2-(%a1-.)), %0")
@@ -1559,7 +1559,7 @@
(define_insn "*movsi_lo_sum_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")
(match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
@@ -1661,7 +1661,7 @@
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
- (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
(match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:DI (match_dup 3)
(unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
@@ -1687,7 +1687,7 @@
(define_insn "*movdi_high_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI
- (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
(match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
"sethi\t%%hi(%a2-(%a1-.)), %0")
@@ -1695,7 +1695,7 @@
(define_insn "*movdi_lo_sum_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")
(match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
diff --git a/gcc/configure b/gcc/configure
index beec8574cf3..96a1eb7c4ce 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7353,10 +7353,10 @@ fi
if test "${enable_coverage+set}" = set; then :
enableval=$enable_coverage; case "${enableval}" in
yes|noopt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0"
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0 -fkeep-static-functions"
;;
opt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2"
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2 -fkeep-static-functions"
;;
no)
# a.k.a. --disable-coverage
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 2c12bd2a9fe..fedaa3431d0 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -717,10 +717,10 @@ AC_ARG_ENABLE(coverage,
default is noopt])],
[case "${enableval}" in
yes|noopt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0"
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0 -fkeep-static-functions"
;;
opt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2"
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2 -fkeep-static-functions"
;;
no)
# a.k.a. --disable-coverage
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 763a6947ec2..220130b1ff4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2018-03-29 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Backport from mainline
+ 2018-03-23 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Implement P0962
+ * parser.c (cp_parser_perform_range_for_lookup): Change
+ the condition for deciding whether to use members.
+
+2018-03-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/78489 - Substitution in wrong order
+ PR c++/84489
+ * pt.c (type_unification_real): Revert last two changes.
+
+2018-03-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/84785 - ICE with alias template and default targs.
+ * pt.c (type_unification_real): Set processing_template_decl if
+ saw_undeduced == 1.
+
2018-03-03 Jason Merrill <jason@redhat.com>
PR c++/84686 - missing volatile loads.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3a056e4135b..89be90a783c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11459,7 +11459,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
/*protect=*/2, /*want_type=*/false,
tf_warning_or_error);
- if (member_begin != NULL_TREE || member_end != NULL_TREE)
+ if (member_begin != NULL_TREE && member_end != NULL_TREE)
{
/* Use the member functions. */
if (member_begin != NULL_TREE)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 27e4c84ac79..9dbf17ba4d8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18603,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 (arg != error_mark_node && !uses_template_parms (arg))
+ if (!uses_template_parms (arg))
arg = convert_template_argument (parm, arg, targs, complain,
i, NULL_TREE);
- else if (saw_undeduced == 1)
+ else if (saw_undeduced < 2)
arg = NULL_TREE;
else
arg = error_mark_node;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 83b46988309..f6cdfdbbd6c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988-2016 Free Software Foundation, Inc.
+@c Copyright (C) 1988-2018 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -5419,6 +5419,25 @@ Specify which floating-point unit to use. You must specify the
@code{target("fpmath=sse,387")} option as
@code{target("fpmath=sse+387")} because the comma would separate
different options.
+
+@item indirect_branch("@var{choice}")
+@cindex @code{indirect_branch} function attribute, x86
+On x86 targets, the @code{indirect_branch} attribute causes the compiler
+to convert indirect call and jump with @var{choice}. @samp{keep}
+keeps indirect call and jump unmodified. @samp{thunk} converts indirect
+call and jump to call and return thunk. @samp{thunk-inline} converts
+indirect call and jump to inlined call and return thunk.
+@samp{thunk-extern} converts indirect call and jump to external call
+and return thunk provided in a separate object file.
+
+@item function_return("@var{choice}")
+@cindex @code{function_return} function attribute, x86
+On x86 targets, the @code{function_return} attribute causes the compiler
+to convert function return with @var{choice}. @samp{keep} keeps function
+return unmodified. @samp{thunk} converts function return to call and
+return thunk. @samp{thunk-inline} converts function return to inlined
+call and return thunk. @samp{thunk-extern} converts function return to
+external call and return thunk provided in a separate object file.
@end table
On the x86, the inliner does not inline a
@@ -8492,6 +8511,9 @@ The table below shows the list of supported modifiers and their effects.
@tab @code{2}
@end multitable
+@code{V} is a special modifier which prints the name of the full integer
+register without @code{%}.
+
@anchor{x86floatingpointasmoperands}
@subsubsection x86 Floating-Point @code{asm} Operands
@@ -13945,21 +13967,16 @@ or @option{-mpopcntd}):
@smallexample
long __builtin_bpermd (long, long);
int __builtin_divwe (int, int);
-int __builtin_divweo (int, int);
unsigned int __builtin_divweu (unsigned int, unsigned int);
-unsigned int __builtin_divweuo (unsigned int, unsigned int);
long __builtin_divde (long, long);
-long __builtin_divdeo (long, long);
unsigned long __builtin_divdeu (unsigned long, unsigned long);
-unsigned long __builtin_divdeuo (unsigned long, unsigned long);
unsigned int cdtbcd (unsigned int);
unsigned int cbcdtd (unsigned int);
unsigned int addg6s (unsigned int, unsigned int);
@end smallexample
-The @code{__builtin_divde}, @code{__builtin_divdeo},
-@code{__builtin_divdeu}, @code{__builtin_divdeou} functions require a
-64-bit environment support ISA 2.06 or later.
+The @code{__builtin_divde} and @code{__builtin_divdeu} functions
+require a 64-bit environment supporting ISA 2.06 or later.
The following built-in functions are available for the PowerPC family
of processors, starting with ISA 3.0 or later (@option{-mcpu=power9}):
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index ff1eca714b1..f7b84dd15e7 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -327,6 +327,13 @@ handlers, respectively. Given @samp{-a} option, unexecuted blocks are
marked @samp{$$$$$} or @samp{%%%%%}, depending on whether a basic block
is reachable via non-exceptional or exceptional paths.
+Note that GCC can completely remove the bodies of functions that are
+not needed -- for instance if they are inlined everywhere. Such functions
+are marked with @samp{-}, which can be confusing.
+Use the @option{-fkeep-inline-functions} and @option{-fkeep-static-functions}
+options to retain these functions and
+allow gcov to properly show their @var{execution_count}.
+
Some lines of information at the start have @var{line_number} of zero.
These preamble lines are of the form
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8b9fb2eb1ef..1809a7b313c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -745,7 +745,7 @@ Objective-C and Objective-C++ Dialects}.
@emph{HPPA Options}
@gccoptlist{-march=@var{architecture-type} @gol
--mdisable-fpregs -mdisable-indexing @gol
+-mcaller-copies -mdisable-fpregs -mdisable-indexing @gol
-mfast-indirect-calls -mgas -mgnu-ld -mhp-ld @gol
-mfixed-range=@var{register-range} @gol
-mjump-in-delay -mlinker-opt -mlong-calls @gol
@@ -993,7 +993,7 @@ See RS/6000 and PowerPC Options.
-mfloat-gprs=yes -mfloat-gprs=no -mfloat-gprs=single -mfloat-gprs=double @gol
-mprototype -mno-prototype @gol
-msim -mmvme -mads -myellowknife -memb -msdata @gol
--msdata=@var{opt} -mvxworks -G @var{num} -pthread @gol
+-msdata=@var{opt} -mreadonly-in-sdata -mvxworks -G @var{num} -pthread @gol
-mrecip -mrecip=@var{opt} -mno-recip -mrecip-precision @gol
-mno-recip-precision @gol
-mveclibabi=@var{type} -mfriz -mno-friz @gol
@@ -1172,7 +1172,8 @@ See RS/6000 and PowerPC Options.
-msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
-mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
-malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
--mmitigate-rop}
+-mmitigate-rop -mindirect-branch=@var{choice} @gol
+-mfunction-return=@var{choice} -mindirect-branch-register}
@emph{x86 Windows Options}
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
@@ -9708,9 +9709,9 @@ Link your object files with @option{-lgcov} or @option{-fprofile-arcs}
Run the program on a representative workload to generate the arc profile
information. This may be repeated any number of times. You can run
concurrent instances of your program, and provided that the file system
-supports locking, the data files will be correctly updated. Also
-@code{fork} calls are detected and correctly handled (double counting
-will not happen).
+supports locking, the data files will be correctly updated. Unless
+a strict ISO C dialect option is in effect, @code{fork} calls are
+detected and correctly handled without double counting.
@item
For profile-directed optimizations, compile the source files again with
@@ -16360,6 +16361,14 @@ other way around.
@opindex mpa-risc-2-0
Synonyms for @option{-march=1.0}, @option{-march=1.1}, and @option{-march=2.0} respectively.
+@item -mcaller-copies
+@opindex mcaller-copies
+The caller copies function arguments passed by hidden reference. This
+option should be used with care as it is not compatible with the default
+32-bit runtime. However, only aggregates larger than eight bytes are
+passed by hidden reference and the option provides better compatibility
+with OpenMP.
+
@item -mjump-in-delay
@opindex mjump-in-delay
This option is ignored and provided for compatibility purposes only.
@@ -20802,6 +20811,13 @@ On embedded PowerPC systems, put all initialized global and static data
in the @code{.data} section, and all uninitialized data in the
@code{.bss} section.
+@item -mreadonly-in-sdata
+@itemx -mreadonly-in-sdata
+@opindex mreadonly-in-sdata
+@opindex mno-readonly-in-sdata
+Put read-only objects in the @code{.sdata} section as well. This is the
+default.
+
@item -mblock-move-inline-limit=@var{num}
@opindex mblock-move-inline-limit
Inline all block moves (such as calls to @code{memcpy} or structure
@@ -23697,8 +23713,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mpclmul
@opindex mpclmul
@need 200
-@itemx -mclfushopt
-@opindex mclfushopt
+@itemx -mclflushopt
+@opindex mclflushopt
@need 200
@itemx -mfsgsbase
@opindex mfsgsbase
@@ -24286,6 +24302,43 @@ opcodes, to mitigate against certain forms of attack. At the moment,
this option is limited in what it can do and should not be relied
on to provide serious protection.
+@item -mindirect-branch=@var{choice}
+@opindex -mindirect-branch
+Convert indirect call and jump with @var{choice}. The default is
+@samp{keep}, which keeps indirect call and jump unmodified.
+@samp{thunk} converts indirect call and jump to call and return thunk.
+@samp{thunk-inline} converts indirect call and jump to inlined call
+and return thunk. @samp{thunk-extern} converts indirect call and jump
+to external call and return thunk provided in a separate object file.
+You can control this behavior for a specific function by using the
+function attribute @code{indirect_branch}. @xref{Function Attributes}.
+
+Note that @option{-mcmodel=large} is incompatible with
+@option{-mindirect-branch=thunk} nor
+@option{-mindirect-branch=thunk-extern} since the thunk function may
+not be reachable in large code model.
+
+@item -mfunction-return=@var{choice}
+@opindex -mfunction-return
+Convert function return with @var{choice}. The default is @samp{keep},
+which keeps function return unmodified. @samp{thunk} converts function
+return to call and return thunk. @samp{thunk-inline} converts function
+return to inlined call and return thunk. @samp{thunk-extern} converts
+function return to external call and return thunk provided in a separate
+object file. You can control this behavior for a specific function by
+using the function attribute @code{function_return}.
+@xref{Function Attributes}.
+
+Note that @option{-mcmodel=large} is incompatible with
+@option{-mfunction-return=thunk} nor
+@option{-mfunction-return=thunk-extern} since the thunk function may
+not be reachable in large code model.
+
+
+@item -mindirect-branch-register
+@opindex -mindirect-branch-register
+Force indirect call and jump via register.
+
@end table
These @samp{-m} switches are supported in addition to the above
diff --git a/gcc/expr.c b/gcc/expr.c
index 554175758fd..b26de6da765 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6693,8 +6693,9 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (GET_CODE (temp) == PARALLEL)
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
- machine_mode temp_mode
- = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+ machine_mode temp_mode = GET_MODE (temp);
+ if (temp_mode == BLKmode || temp_mode == VOIDmode)
+ temp_mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
rtx temp_target = gen_reg_rtx (temp_mode);
emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
temp = temp_target;
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 60159842746..e7c919c9f2f 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,53 @@
+2018-04-24 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/85520
+ * decl.c (gfc_match_char_spec): Check for negative length and set to 0.
+
+2018-03-28 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/85084
+ Backport from trunk.
+ * frontend-passes.c (gfc_run_passes): Do not run front-end
+ optimizations if a previous error occurred.
+
+2018-03-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ ChangeLog entry for r258698
+ PR fortran/85001
+ * interface.c (symbol_rank): Remove bogus null pointer check that
+ crept in when translating a ternary operator into an if-else
+ constructor.
+
+2018-03-19 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/84931
+ Backport from trunk
+ * simplify.c (gfc_convert_constant): Correctly handle iterators
+ for type conversion.
+
+2018-03-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/65453
+ * decl.c (get_proc_name): Catch clash between a procedure statement
+ and a contained subprogram
+
+2018-03-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83939
+ * resolve.c (resolve_fl_procedure): Enforce F2018:C15100.
+
+2018-03-10 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/84734
+ * arith.c (check_result, eval_intrinsic): If result overflows, pass
+ the expression up the chain instead of a NULL pointer.
+
+2018-03-08 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/64124
+ PR fortran/70409
+ * decl.c (gfc_match_char_spec): Try to reduce a charlen to a constant.
+
2018-03-06 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/56667
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index e849f598df1..b33ad2e80cc 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -555,10 +555,10 @@ check_result (arith rc, gfc_expr *x, gfc_expr *r, gfc_expr **rp)
val = ARITH_OK;
}
- if (val != ARITH_OK)
- gfc_free_expr (r);
- else
+ if (val == ARITH_OK || val == ARITH_OVERFLOW)
*rp = r;
+ else
+ gfc_free_expr (r);
return val;
}
@@ -1599,9 +1599,13 @@ eval_intrinsic (gfc_intrinsic_op op,
if (rc != ARITH_OK)
{
gfc_error (gfc_arith_error (rc), &op1->where);
+ if (rc == ARITH_OVERFLOW)
+ goto done;
return NULL;
}
+done:
+
gfc_free_expr (op1);
gfc_free_expr (op2);
return result;
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 64e0fee5c29..917b89f0a48 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1171,6 +1171,12 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry)
gfc_error_now ("Procedure %qs at %C is already defined at %L",
name, &sym->declared_at);
+ if (sym->attr.external && sym->attr.procedure
+ && gfc_current_state () == COMP_CONTAINS)
+ gfc_error_now ("Contained procedure %qs at %C clashes with "
+ "procedure defined at %L",
+ name, &sym->declared_at);
+
/* Trap a procedure with a name the same as interface in the
encompassing scope. */
if (sym->attr.generic != 0
@@ -3007,7 +3013,28 @@ done:
if (seen_length == 0)
cl->length = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
else
- cl->length = len;
+ {
+ /* If gfortran ends up here, then the len may be reducible to a
+ constant. Try to do that here. If it does not reduce, simply
+ assign len to the charlen. */
+ if (len && len->expr_type != EXPR_CONSTANT)
+ {
+ gfc_expr *e;
+ e = gfc_copy_expr (len);
+ gfc_reduce_init_expr (e);
+ if (e->expr_type == EXPR_CONSTANT)
+ {
+ gfc_replace_expr (len, e);
+ if (mpz_cmp_si (len->value.integer, 0) < 0)
+ mpz_set_ui (len->value.integer, 0);
+ }
+ else
+ gfc_free_expr (e);
+ cl->length = len;
+ }
+ else
+ cl->length = len;
+ }
ts->u.cl = cl;
ts->kind = kind == 0 ? gfc_default_character_kind : kind;
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 5bd8fb1e133..8941f359782 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -127,6 +127,10 @@ gfc_run_passes (gfc_namespace *ns)
doloop_list.release ();
int w, e;
+ gfc_get_errors (&w, &e);
+ if (e > 0)
+ return;
+
if (flag_frontend_optimize)
{
optimize_namespace (ns);
@@ -137,10 +141,6 @@ gfc_run_passes (gfc_namespace *ns)
expr_array.release ();
}
- gfc_get_errors (&w, &e);
- if (e > 0)
- return;
-
if (flag_realloc_lhs)
realloc_strings (ns);
}
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 04b92c994f1..725ffd18ed2 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1167,7 +1167,7 @@ symbol_rank (gfc_symbol *sym)
{
gfc_array_spec *as = NULL;
- if (sym->ts.type == BT_CLASS && CLASS_DATA (sym) && CLASS_DATA (sym)->as)
+ if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
as = CLASS_DATA (sym)->as;
else
as = sym->as;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index d2d1b583535..99ee31efeeb 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -11958,6 +11958,19 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
}
}
+ /* F2018, C15100: "The result of an elemental function shall be scalar,
+ and shall not have the POINTER or ALLOCATABLE attribute." The scalar
+ pointer is tested and caught elsewhere. */
+ if (sym->attr.elemental && sym->result
+ && (sym->result->attr.allocatable || sym->result->attr.pointer))
+ {
+ gfc_error ("Function result variable %qs at %L of elemental "
+ "function %qs shall not have an ALLOCATABLE or POINTER "
+ "attribute", sym->result->name,
+ &sym->result->declared_at, sym->name);
+ return false;
+ }
+
if (sym->attr.is_bind_c && sym->attr.is_c_interop != 1)
{
gfc_formal_arglist *curr_arg;
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index ac443d81f50..2d177399f44 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -6926,26 +6926,32 @@ gfc_convert_constant (gfc_expr *e, bt type, int kind)
{
gfc_expr *tmp;
if (c->iterator == NULL)
- tmp = f (c->expr, kind);
+ {
+ tmp = f (c->expr, kind);
+ if (tmp == NULL)
+ {
+ gfc_free_expr (result);
+ return NULL;
+ }
+
+ gfc_constructor_append_expr (&result->value.constructor,
+ tmp, &c->where);
+ }
else
{
+ gfc_constructor *n;
g = gfc_convert_constant (c->expr, type, kind);
- if (g == &gfc_bad_expr)
+ if (g == NULL || g == &gfc_bad_expr)
{
gfc_free_expr (result);
return g;
}
- tmp = g;
- }
-
- if (tmp == NULL)
- {
- gfc_free_expr (result);
- return NULL;
+ n = gfc_constructor_get ();
+ n->expr = g;
+ n->iterator = gfc_copy_iterator (c->iterator);
+ n->where = c->where;
+ gfc_constructor_append (&result->value.constructor, n);
}
-
- gfc_constructor_append_expr (&result->value.constructor,
- tmp, &c->where);
}
break;
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 9853c4a499c..0d06c3c237a 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -1576,8 +1576,15 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
"in another translation unit"));
return false;
}
- gcc_assert (DECL_NONADDRESSABLE_P (f1)
- == DECL_NONADDRESSABLE_P (f2));
+ if (DECL_BIT_FIELD (f1) != DECL_BIT_FIELD (f2))
+ {
+ warn_odr (t1, t2, f1, f2, warn, warned,
+ G_("one field is bitfield while other is not"));
+ return false;
+ }
+ else
+ gcc_assert (DECL_NONADDRESSABLE_P (f1)
+ == DECL_NONADDRESSABLE_P (f2));
}
/* If one aggregate has more fields than the other, they
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index d14314188e0..aa5ba454323 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -1116,6 +1116,17 @@ sem_function::merge (sem_item *alias_item)
return false;
}
+ if (!original->in_same_comdat_group_p (alias)
+ || original->comdat_local_p ())
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "Not unifying; alias nor wrapper cannot be created; "
+ "across comdat group boundary\n\n");
+
+ return false;
+ }
+
/* See if original is in a section that can be discarded if the main
symbol is not used. */
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index c755b383d6d..ddc3c6be92d 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,21 @@
+2018-04-25 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-04-10 Martin Liska <mliska@suse.cz>
+
+ PR lto/85248
+ * lto-symtab.c (lto_symtab_merge_p): Do not check for
+ TREE_VALUES of error attributes.
+
+2018-04-25 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-04-10 Richard Biener <rguenther@suse.de>
+ Martin Liska <mliska@suse.cz>
+
+ PR lto/85248
+ * lto-symtab.c (lto_symtab_merge_p): Handle noreturn attribute.
+
2018-03-07 Martin Liska <mliska@suse.cz>
Backport from mainline
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 6b3b785b674..32a53b3348f 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -568,6 +568,9 @@ lto_symtab_merge_p (tree prevailing, tree decl)
return false;
}
}
+
+ /* FIXME: after MPX is removed, use flags_from_decl_or_type
+ function instead. PR lto/85248. */
if (DECL_ATTRIBUTES (prevailing) != DECL_ATTRIBUTES (decl))
{
tree prev_attr = lookup_attribute ("error", DECL_ATTRIBUTES (prevailing));
@@ -595,6 +598,16 @@ lto_symtab_merge_p (tree prevailing, tree decl)
"warning attribute mismatch\n");
return false;
}
+
+ prev_attr = lookup_attribute ("noreturn", DECL_ATTRIBUTES (prevailing));
+ attr = lookup_attribute ("noreturn", DECL_ATTRIBUTES (decl));
+ if ((prev_attr == NULL) != (attr == NULL))
+ {
+ if (symtab->dump_file)
+ fprintf (symtab->dump_file, "Not merging decls; "
+ "noreturn attribute mismatch\n");
+ return false;
+ }
}
return true;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8eaa7830fd3..190eccbbbf6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,495 @@
+2018-04-25 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-04-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR lto/85248
+ * gcc.dg/lto/pr85248_0.c: New test.
+ * gcc.dg/lto/pr85248_1.c: New test.
+
+2018-04-24 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/85520
+ * gfortran.dg/pr85520.f90: New test.
+
+2018-04-23 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ Backport from mainline
+ 2018-04-16 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ PR target/83660
+ * gcc.target/powerpc/pr83660.C: New test.
+
+2018-04-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/torture/pr85496.C: New test.
+
+2018-04-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ Backport from mainline
+ 2018-04-11 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR target/85261
+ * gcc.target/arm/fpscr.c: Add call to __builtin_arm_set_fpscr with
+ literal value. Expect 2 MCR instruction. Fix function prototype.
+ Remove volatile keyword.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-03-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84574
+ * gcc.target/i386/ret-thunk-9.c: Expect __x86_return_thunk
+ label instead of __x86_indirect_thunk label.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84039
+ * gcc.target/i386/indirect-thunk-1.c: Updated.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/84530
+ * gcc.target/i386/ret-thunk-22.c: New test.
+ * gcc.target/i386/ret-thunk-23.c: Likewise.
+ * gcc.target/i386/ret-thunk-24.c: Likewise.
+ * gcc.target/i386/ret-thunk-25.c: Likewise.
+ * gcc.target/i386/ret-thunk-26.c: Likewise.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/indirect-thunk-10.c: New test.
+ * gcc.target/i386/indirect-thunk-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-9.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-10.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-11.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-9.c: Likewise.
+ * gcc.target/i386/ret-thunk-17.c: Likewise.
+ * gcc.target/i386/ret-thunk-18.c: Likewise.
+ * gcc.target/i386/ret-thunk-19.c: Likewise.
+ * gcc.target/i386/ret-thunk-20.c: Likewise.
+ * gcc.target/i386/ret-thunk-21.c: Likewise.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/indirect-thunk-register-4.c: New test.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/indirect-thunk-1.c (dg-options): Add
+ -mno-indirect-branch-register.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-1.c: New test.
+ * gcc.target/i386/indirect-thunk-register-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-3.c: Likewise.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/indirect-thunk-1.c (dg-options): Add
+ -mfunction-return=keep.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-1.c: New test.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-16.c: Likewise.
+ * gcc.target/i386/ret-thunk-2.c: Likewise.
+ * gcc.target/i386/ret-thunk-3.c: Likewise.
+ * gcc.target/i386/ret-thunk-4.c: Likewise.
+ * gcc.target/i386/ret-thunk-5.c: Likewise.
+ * gcc.target/i386/ret-thunk-6.c: Likewise.
+ * gcc.target/i386/ret-thunk-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-8.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+
+ Backport from mainline
+ 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/83839
+ * gcc.target/i386/indirect-thunk-1.c: Scan for "push" only on
+ Linux.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-4.c: Likewise.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Don't check the
+ __x86_return_thunk label.
+ Scan for "push" only for Linux.
+
+2018-04-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/indirect-thunk-1.c: New test.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+
+2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * gcc.target/s390/nobp-no-dwarf2-cfi.c: New test.
+
+2018-04-10 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR target/85056
+ * gcc.target/nvptx/pr85056.c (main): Initialize "sum".
+
+2018-04-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/84748
+ * gcc.c-torture/execute/pr84748.c: New test.
+
+2018-04-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/opt/pr85196.C: New test.
+
+2018-04-05 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/85193
+ * gcc.target/i386/pr85193.c: New test.
+
+2018-04-02 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2018-03-28 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/84912
+ * gcc.target/powerpc/extend-divide-1.c (div_weo): Remove test for
+ deleted builtin function.
+ (div_weuo): Likewise.
+ * gcc.target/powerpc/extend-divide-2.c (div_deo): Likewise.
+ (div_deuo): Likewise.
+
+2018-03-30 Cesar Philippidis <cesar@codesourcery.com>
+
+ Backport from mainline
+ 2018-03-27 Cesar Philippidis <cesar@codesourcery.com>
+
+ * testsuite/gcc.target/nvptx/pr85056.c: New test.
+ * testsuite/gcc.target/nvptx/pr85056a.c: New test.
+
+2018-03-29 Sudakshina Das <sudi.das@arm.com>
+
+ * gcc.target/arm/pr84826.c: Change dg-option to -fstack-check.
+
+ Backport from mainline
+ 2018-03-23 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/84826
+ * gcc.target/arm/pr84826.c: Add dg directive.
+
+ Backport from mainline
+ 2018-03-22 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/84826
+ * gcc.target/arm/pr84826.c: New test.
+
+2018-03-28 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/crypto-builtin-1-runnable: Add
+ p8vector_hw to dg-do run.
+
+2018-03-28 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/85084
+ Backport from trunk.
+ * frontend-passes.c (gfc_run_passes): Do not run front-end
+ optimizations if a previous error occurred.
+
+2018-03-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/85026
+ * g++.dg/pr85026.C: New test.
+
+2018-03-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ Backport from mainline
+ 2018-03-08 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/82411
+ * gcc.target/powerpc/ppc-sdata-2.c: Skip if -mno-readonly-in-sdata.
+
+2018-03-27 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/crypto-builtin-1-runnable.c: New test file.
+
+2018-03-27 Sudakshina Das <sudi.das@arm.com>
+
+ Backport from mainline:
+ 2018-03-20 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/82989
+ * gcc.target/arm/pr82989.c: New test.
+
+ Backport from mainline:
+ 2018-03-21 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/82989
+ * gcc.target/arm/pr82989.c: Change dg scan-assembly directives.
+
+2018-03-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2018-03-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/82518
+ * lib/target-supports.exp (check_effective_target_vect_load_lanes):
+ Disable for armeb targets.
+ * gcc.target/arm/pr82518.c: New test.
+
+2018-03-22 Tom de Vries <tom@codesourcery.com>
+
+ backport from trunk:
+ 2018-03-22 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/84956
+ * gcc.dg/pr84956.c: New test.
+
+2018-03-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ ChangeLog entry for r258698
+ PR fortran/85001
+ * gfortran.dg/interface_41.f90: New test.
+
+2018-03-19 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/84931
+ Backport from trunk
+ * gfortran.dg/array_constructor_52.f90: New test.
+
+2018-03-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/65453
+ * gfortran.dg/pr65453.f90: New test.
+
+2018-03-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83939
+ * gfortran.dg/pr83939.f90
+
+2018-03-10 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/84734
+ * gfortran.dg/pr84734.f90: New test.
+
+2018-03-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2018-01-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR ipa/82352
+ * g++.dg/ipa/pr82352.C (size_t): Define to __SIZE_TYPE__ instead of
+ long unsigned int.
+
+2018-03-08 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/64124
+ PR fortran/70409
+ * gfortran.dg/pr64124.f90: New tests.
+ * gfortran.dg/pr70409.f90: New tests.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2016-12-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/77844
+ * g++.dg/opt/pr77844.C: New test.
+
+2018-03-08 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-04 Martin Liska <mliska@suse.cz>
+
+ PR ipa/82352
+ * g++.dg/ipa/pr82352.C: New test.
+
2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
Backport from mainline
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
deleted file mode 100644
index 636bf1afd88..00000000000
--- a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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/range-for13.C b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
index 100f531f760..7babd713cfb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
@@ -3,16 +3,6 @@
// { dg-do compile { target c++11 } }
-//These should not be used
-template<typename T> int *begin(T &t)
-{
- T::fail;
-}
-template<typename T> int *end(T &t)
-{
- T::fail;
-}
-
struct container1
{
int *begin();
@@ -87,10 +77,37 @@ struct container10
static function end;
};
+namespace N
+{
+template<typename T> int *begin(T &t)
+{
+ return 0;
+}
+template<typename T> int *end(T &t)
+{
+ return 0;
+}
+struct container11
+{
+ int *begin();
+ //no end
+};
+
+struct container12
+{
+ int *end();
+ //no begin
+};
+
+struct container13
+{
+};
+}
+
void test1()
{
- for (int x : container1()); // { dg-error "member but not" }
- for (int x : container2()); // { dg-error "member but not" }
+ for (int x : container1()); // { dg-error "'begin' was not declared|'end' was not declared" }
+ for (int x : container2()); // { dg-error "'begin' was not declared|'end' was not declared" }
for (int x : container3()); // { dg-error "within this context" }
for (int x : container4()); // { dg-error "cannot be used as a function" }
for (int x : container5()); // { dg-error "invalid use of" }
@@ -99,4 +116,7 @@ void test1()
for (int x : container8());
for (int x : container9()); // { dg-error "within this context" }
for (int x : container10());
+ for (int x : N::container11());
+ for (int x : N::container12());
+ for (int x : N::container13());
}
diff --git a/gcc/testsuite/g++.dg/ipa/pr82352.C b/gcc/testsuite/g++.dg/ipa/pr82352.C
new file mode 100644
index 00000000000..08516da0c8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr82352.C
@@ -0,0 +1,93 @@
+// PR ipa/82352
+// { dg-do compile }
+// { dg-options "-O2" }
+
+typedef __SIZE_TYPE__ size_t;
+
+class A
+{
+public :
+ typedef enum { Zero = 0, One = 1 } tA;
+ A(tA a) { m_a = a; }
+
+private :
+ tA m_a;
+};
+
+class B
+{
+public :
+ void *operator new(size_t t) { return (void*)(42); };
+};
+
+class C
+{
+public:
+ virtual void ffff () = 0;
+};
+
+class D
+{
+ public :
+ virtual void g() = 0;
+ virtual void h() = 0;
+};
+
+template<class T> class IIII: public T, public D
+{
+public:
+ void ffff()
+ {
+ if (!m_i2) throw A(A::One);
+ };
+
+ void h()
+ {
+ if (m_i2) throw A(A::Zero);
+ }
+
+protected:
+ virtual void g()
+ {
+ if (m_i1 !=0) throw A(A::Zero);
+ };
+
+private :
+ int m_i1;
+ void *m_i2;
+};
+
+class E
+{
+private:
+ size_t m_e;
+ static const size_t Max;
+
+public:
+ E& i(size_t a, size_t b, size_t c)
+ {
+ if ((a > Max) || (c > Max)) throw A(A::Zero );
+ if (a + b > m_e) throw A(A::One );
+ return (*this);
+ }
+
+ inline E& j(const E &s)
+ {
+ return i(0,0,s.m_e);
+ }
+};
+
+class F : public C { };
+class G : public C { };
+class HHHH : public B, public F, public G { };
+
+void k()
+{
+ new IIII<HHHH>();
+}
+
+void l()
+{
+ E e1, e2;
+ e1.j(e2);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr77844.C b/gcc/testsuite/g++.dg/opt/pr77844.C
new file mode 100644
index 00000000000..66eb978ddb7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr77844.C
@@ -0,0 +1,32 @@
+// PR debug/77844
+// { dg-do compile }
+// { dg-options "-O3 -g" }
+
+#include <vector>
+
+void
+foo (std::vector<bool>& v, int i, int j)
+{
+ for (int k = 0; k < 5; ++k)
+ v[5 * i + k] = v[5 * i + k] | v[5 * j + k];
+}
+
+void
+bar (std::vector<bool>& v, int i, int j)
+{
+ for (int k = 0; k < 5; ++k)
+ v[5 * i + k] = v[5 * i + k] ^ v[5 * j + k];
+}
+
+void
+baz (std::vector<bool>& v)
+{
+ foo (v, 4, 1);
+ foo (v, 4, 2);
+ foo (v, 4, 3);
+ foo (v, 4, 4);
+ bar (v, 4, 1);
+ bar (v, 4, 2);
+ bar (v, 4, 3);
+ bar (v, 4, 4);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr85196.C b/gcc/testsuite/g++.dg/opt/pr85196.C
new file mode 100644
index 00000000000..04d7abde4fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr85196.C
@@ -0,0 +1,89 @@
+// PR target/85196
+// Testcase by Rainer Orth <ro@gcc.gnu.org>
+
+// { dg-do compile }
+// { dg-options "-O -fpermissive -w" }
+// { dg-additional-options "-fPIC" { target fpic } }
+
+class a;
+template <typename> class b;
+template <typename k> class d : public b<k> {};
+class e {};
+void f(int);
+template <class> class g {
+public:
+ h();
+ a i();
+};
+template <> class b<e> : public g<e> {};
+typedef (*j)(d<e>);
+template <class k> class l {
+public:
+ k operator->() { return 0; }
+};
+enum m { n, aa, o, ab, q, p };
+inline s(m ac) {
+ switch (ac) {
+ case n:
+ case aa:
+ case p:
+ return 1;
+ case o:
+ case ab:
+ return 2;
+ }
+}
+class D {
+ int ad;
+
+public:
+ *ae() { return &ad; }
+};
+class a {
+ l<D *> af;
+
+public:
+ *r() { return af->ae(); }
+ t(int *c) {
+ int *w = af->ae();
+ return w == c;
+ }
+};
+class F : a {
+public:
+ static int ah[];
+ static e v(F *);
+ unsigned long ai() const;
+};
+inline unsigned long F::ai() const {
+ m aj = r() - &ah[0];
+ return s(aj);
+}
+inline e F::v(F *ak) {
+ long al = ak->ai();
+ f(al);
+}
+template <typename> am() { return q; }
+class an : F {
+public:
+ static ao(d<e> u) {
+ int *ap;
+ m aq = am<unsigned>();
+ ap = &ah[aq];
+ return u.h() && u.i().t(ap);
+ }
+ template <e ar(F *)> static as() {
+ F at;
+ ar(&at);
+ }
+ template <e ar(F *)> static au(int *, unsigned, e *) {
+ j av = ao;
+ d<e> aw;
+ if (av(aw))
+ as<ar>();
+ }
+};
+int *ax;
+int ay;
+e az;
+ba() { an::au<an::v>(ax, ay, &az); }
diff --git a/gcc/testsuite/g++.dg/pr85026.C b/gcc/testsuite/g++.dg/pr85026.C
new file mode 100644
index 00000000000..e1e3ccd2e35
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr85026.C
@@ -0,0 +1,61 @@
+/* PR target/85026. */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -std=gnu++11" } */
+
+template <class> class a;
+class b;
+struct c {
+ typedef a<b> &g;
+};
+template <typename d> struct e { typedef typename d::f iter; };
+class h {
+public:
+ void __attribute__((noreturn)) i();
+} ab;
+template <class> class a {
+public:
+ typedef b *f;
+ b &operator[](unsigned m) {
+ if (ac)
+ ab.i();
+ return ad[m];
+ }
+ f n() { return ad; }
+ f m_fn3();
+ b *ad;
+ unsigned ac;
+};
+class b {
+public:
+ short j;
+ short k;
+ signed l;
+} __attribute__((__packed__));
+void o(a<b> &m, b &p2, b &p) {
+ p2 = p = m[0];
+ if (bool at = false)
+ ;
+ else
+ for (c::g au(m);; at = true)
+ if (bool av = false)
+ ;
+ else
+ for (e<a<int>>::iter aw = au.n(), ax = au.m_fn3(); ax;
+ av ? (void)0 : (void)0)
+ if (bool ay = 0)
+ ;
+ else
+ for (b az = *aw; !ay; ay = true) {
+ if (p2.j)
+ p2.j = az.j;
+ else if (p.j)
+ p.j = az.j;
+ if (p2.k)
+ p2.k = az.k;
+ else if (az.k > p.k)
+ p.k = az.k;
+ if (az.l < p2.l)
+ if (az.l > p.l)
+ p.l = az.l;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr85496.C b/gcc/testsuite/g++.dg/torture/pr85496.C
new file mode 100644
index 00000000000..3f504a37791
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr85496.C
@@ -0,0 +1,18 @@
+// PR middle-end/85496
+// Reported by Marek Polacek <mpolacek@gcc.gnu.org>
+
+template <typename> class complex;
+template <typename _Tp> complex<_Tp> operator*(complex<_Tp>, complex<_Tp>);
+template <> struct complex<float> { _Complex float _M_value; };
+class A {
+ complex<float> _f0, _f1;
+
+public:
+ complex<float> &m_fn1() { return _f1; }
+};
+complex<float> a;
+void cos() {
+ A b;
+ complex<float> c;
+ b.m_fn1() = c * a;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84748.c b/gcc/testsuite/gcc.c-torture/execute/pr84748.c
new file mode 100644
index 00000000000..9572ab285c6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr84748.c
@@ -0,0 +1,34 @@
+/* { dg-require-effective-target int128 } */
+
+typedef unsigned __int128 u128;
+
+int a, c, d;
+u128 b;
+
+unsigned long long g0, g1;
+
+void
+store (unsigned long long a0, unsigned long long a1)
+{
+ g0 = a0;
+ g1 = a1;
+}
+
+void
+foo (void)
+{
+ b += a;
+ c = d != 84347;
+ b /= c;
+ u128 x = b;
+ store (x >> 0, x >> 64);
+}
+
+int
+main (void)
+{
+ foo ();
+ if (g0 != 0 || g1 != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr85248_0.c b/gcc/testsuite/gcc.dg/lto/pr85248_0.c
new file mode 100644
index 00000000000..df61ac976a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr85248_0.c
@@ -0,0 +1,45 @@
+/* PR lto/85248 */
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -flto -O2 } } } */
+
+extern void test_alias (int s, int e) __asm__ (__USER_LABEL_PREFIX__ "test");
+extern void test_noreturn (int s, int e) __asm__ (__USER_LABEL_PREFIX__ "test")
+ __attribute__ ((__noreturn__));
+
+extern inline __attribute__ ((__always_inline__, __gnu_inline__)) void
+test (int s, int e)
+{
+ if (__builtin_constant_p (s) && s != 0)
+ test_noreturn (s, e);
+ else
+ test_alias (s, e);
+}
+
+int
+foo (void)
+{
+ static volatile int a;
+ return a;
+}
+
+static void
+bar (void)
+{
+ test (0, 1);
+ __builtin_exit (0);
+}
+
+static void
+baz ()
+{
+ test (1, 0);
+}
+
+int
+main ()
+{
+ if (foo ())
+ baz ();
+ bar ();
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr85248_1.c b/gcc/testsuite/gcc.dg/lto/pr85248_1.c
new file mode 100644
index 00000000000..5ce257181fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr85248_1.c
@@ -0,0 +1,9 @@
+/* { dg-options "-fno-lto" } */
+
+void
+test (int s, int e)
+{
+ asm volatile ("" : "+g" (s), "+g" (e) : : "memory");
+ if (s)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr84956.c b/gcc/testsuite/gcc.dg/pr84956.c
new file mode 100644
index 00000000000..055a749d635
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr84956.c
@@ -0,0 +1,27 @@
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+char a;
+int c;
+unsigned b ();
+
+unsigned
+setjmp ()
+{
+}
+
+static void
+d ()
+{
+ if (b ())
+ c = 3;
+}
+
+void
+e ()
+{
+ d ();
+ a && ({ setjmp (); });
+ a && ({ setjmp (); });
+ a && ({ setjmp (); });
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/fpscr.c b/gcc/testsuite/gcc.target/arm/fpscr.c
index 7b4d71d72d8..4c3eaf7fcf7 100644
--- a/gcc/testsuite/gcc.target/arm/fpscr.c
+++ b/gcc/testsuite/gcc.target/arm/fpscr.c
@@ -6,11 +6,14 @@
/* { dg-add-options arm_fp } */
void
-test_fpscr ()
+test_fpscr (void)
{
- volatile unsigned int status = __builtin_arm_get_fpscr ();
+ unsigned status;
+
+ __builtin_arm_set_fpscr (0);
+ status = __builtin_arm_get_fpscr ();
__builtin_arm_set_fpscr (status);
}
/* { dg-final { scan-assembler "mrc\tp10, 7, r\[0-9\]+, cr1, cr0, 0" } } */
-/* { dg-final { scan-assembler "mcr\tp10, 7, r\[0-9\]+, cr1, cr0, 0" } } */
+/* { dg-final { scan-assembler-times "mcr\tp10, 7, r\[0-9\]+, cr1, cr0, 0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr82518.c b/gcc/testsuite/gcc.target/arm/pr82518.c
new file mode 100644
index 00000000000..ce820b78a8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr82518.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-additional-options "-O3 -fno-inline -std=gnu99" } */
+/* { dg-add-options arm_neon } */
+
+typedef struct { int x, y; } X;
+
+void f4(X *p, int n)
+{
+ for (int i = 0; i < n; i++)
+ { p[i].x = i;
+ p[i].y = i + 1;
+ }
+}
+
+__attribute ((aligned (16))) X arr[100];
+
+int main(void)
+{
+ volatile int fail = 0;
+ f4 (arr, 100);
+ for (int i = 0; i < 100; i++)
+ if (arr[i].y != i+1 || arr[i].x != i)
+ fail = 1;
+ if (fail)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr82989.c b/gcc/testsuite/gcc.target/arm/pr82989.c
new file mode 100644
index 00000000000..8519c3fdc82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr82989.c
@@ -0,0 +1,33 @@
+/* PR target/82989. */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { "-mcpu=*" } { "-mcpu=cortex-a8" } } */
+/* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { "-mfpu=*" } { "-mfpu=neon" } } */
+/* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-O2 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=hard" } */
+/* { dg-add-options arm_neon } */
+
+typedef unsigned long long uint64_t;
+
+void f_shr_imm (uint64_t *a)
+{
+ *a += *a >> 32;
+}
+
+void f_shr_reg (uint64_t *a, uint64_t b)
+{
+ *a += *a >> b;
+}
+
+void f_shl_imm (uint64_t *a)
+{
+ *a += *a << 32;
+}
+
+void f_shl_reg (uint64_t *a, uint64_t b)
+{
+ *a += *a << b;
+}
+/* { dg-final { scan-assembler-not "vshl*" } } */
+/* { dg-final { scan-assembler-not "vshr*" } } */
+/* { dg-final { scan-assembler-not "vmov*" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr84826.c b/gcc/testsuite/gcc.target/arm/pr84826.c
new file mode 100644
index 00000000000..563ce51b76f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr84826.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-options "-Ofast -fstack-check" } */
+
+void d (void *);
+
+void a ()
+{
+ int b;
+ void bar (int c)
+ {
+ if (__builtin_expect (c, 0))
+ ++b;
+ }
+ d (bar);
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
new file mode 100644
index 00000000000..6e94d2c4865
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c
new file mode 100644
index 00000000000..a0674bd2363
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk-inline -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
new file mode 100644
index 00000000000..3c467078964
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
new file mode 100644
index 00000000000..2c7fb52b59d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
new file mode 100644
index 00000000000..0d3f895009d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
new file mode 100644
index 00000000000..fb26c005e80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
new file mode 100644
index 00000000000..aa03fbd8446
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 { target x32 } } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
new file mode 100644
index 00000000000..3c72036dbaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c
new file mode 100644
index 00000000000..7a80a8986e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c
new file mode 100644
index 00000000000..d4d45c5114d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
new file mode 100644
index 00000000000..7106407b83d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+extern void male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk")));
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c
new file mode 100644
index 00000000000..3a2aeaddbc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk-extern")))
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c
new file mode 100644
index 00000000000..8e52f032b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk-inline")))
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
new file mode 100644
index 00000000000..27c7e5b029b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk")))
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
new file mode 100644
index 00000000000..89a2bac8403
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+extern int male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk-inline")));
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
new file mode 100644
index 00000000000..3eb83c3779a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk-inline")))
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
new file mode 100644
index 00000000000..0098dd1133d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+extern int male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk-extern")));
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
new file mode 100644
index 00000000000..ece8de15a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk-extern")))
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
new file mode 100644
index 00000000000..d53fc887dcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+__attribute__ ((indirect_branch("thunk-extern")))
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
new file mode 100644
index 00000000000..d730d31bda1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+__attribute__ ((indirect_branch("keep")))
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c
new file mode 100644
index 00000000000..bdaa4f6911b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk")))
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
new file mode 100644
index 00000000000..73d16baddc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { ! x32 } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+void (*dispatch) (char *);
+char buf[10];
+
+void
+foo (void)
+{
+ dispatch (buf);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_rax" { target lp64 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
new file mode 100644
index 00000000000..856751ac224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { ! x32 } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+void (*dispatch) (char *);
+char buf[10];
+
+int
+foo (void)
+{
+ dispatch (buf);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_(r|e)ax" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
new file mode 100644
index 00000000000..42312f65588
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+void
+foo (void)
+{
+ bar (buf);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_rax" { target lp64 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
new file mode 100644
index 00000000000..c8ca102c8df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+int
+foo (void)
+{
+ bar (buf);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
new file mode 100644
index 00000000000..c09dd0afd2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
new file mode 100644
index 00000000000..826425a5115
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
new file mode 100644
index 00000000000..385626850a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
new file mode 100644
index 00000000000..1ae49b137ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
new file mode 100644
index 00000000000..53282390977
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
new file mode 100644
index 00000000000..8ae43482d0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
new file mode 100644
index 00000000000..2b9a33e93dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
new file mode 100644
index 00000000000..869d9040838
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
new file mode 100644
index 00000000000..c5c16ed8bd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
new file mode 100644
index 00000000000..4a63ebed8ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
new file mode 100644
index 00000000000..a395ffca018
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
new file mode 100644
index 00000000000..21cbfd39582
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
new file mode 100644
index 00000000000..d1300f18dc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
new file mode 100644
index 00000000000..ea009245a58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
new file mode 100644
index 00000000000..7d396a31953
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk\n" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk_bnd\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
new file mode 100644
index 00000000000..e7e616bb271
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
new file mode 100644
index 00000000000..5320e923be2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not {\t(pause|pause|nop)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
new file mode 100644
index 00000000000..f0cd9b75be8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=keep -fno-pic" } */
+
+extern void (*func_p) (void);
+
+void
+foo (void)
+{
+ asm("call __x86_indirect_thunk_%V0" : : "a" (func_p));
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_rax" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85193.c b/gcc/testsuite/gcc.target/i386/pr85193.c
new file mode 100644
index 00000000000..98e3dafc7ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85193.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wno-psabi -O2 -fno-tree-ccp -fno-tree-fre -mno-sse" } */
+
+typedef unsigned char U __attribute__((vector_size(16)));
+typedef unsigned int V __attribute__((vector_size(16)));
+typedef unsigned long long W __attribute__((vector_size(16)));
+
+extern void bar(U, U);
+
+V v;
+
+void
+foo(U f)
+{
+ f[0] = f[0] << (unsigned char)~v[0] | f[~((W)(U){0, 0, 0, 0, 0, 0, 0, 0, 5})[1] & 5] >> (-(unsigned char)~v[0] & 7);
+ bar(f, (U){});
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
new file mode 100644
index 00000000000..7223f67ba5e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
new file mode 100644
index 00000000000..af9023af613
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
new file mode 100644
index 00000000000..ba467c59b36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
new file mode 100644
index 00000000000..43e57cac2c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
new file mode 100644
index 00000000000..55f156c4376
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+extern void (*bar) (void);
+extern int foo (void) __attribute__ ((function_return("thunk")));
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 3 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 3 } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
new file mode 100644
index 00000000000..1c790436a53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("thunk-inline")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
new file mode 100644
index 00000000000..58aba319cba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("thunk-extern"), indirect_branch("thunk")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
new file mode 100644
index 00000000000..a16cad16aaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk-extern -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("keep"), indirect_branch("keep")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-17.c b/gcc/testsuite/gcc.target/i386/ret-thunk-17.c
new file mode 100644
index 00000000000..0605e2c6542
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-17.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-18.c b/gcc/testsuite/gcc.target/i386/ret-thunk-18.c
new file mode 100644
index 00000000000..307019dc242
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-18.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-19.c b/gcc/testsuite/gcc.target/i386/ret-thunk-19.c
new file mode 100644
index 00000000000..772617f4010
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-19.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+
+__attribute__ ((function_return("thunk")))
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
new file mode 100644
index 00000000000..c6659e3ad09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-20.c b/gcc/testsuite/gcc.target/i386/ret-thunk-20.c
new file mode 100644
index 00000000000..1e9f9bd5a66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-20.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((function_return("thunk-extern")))
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-21.c b/gcc/testsuite/gcc.target/i386/ret-thunk-21.c
new file mode 100644
index 00000000000..eea07f7abe1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-21.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((function_return("thunk-inline")))
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
new file mode 100644
index 00000000000..89e086de97b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
new file mode 100644
index 00000000000..43f0ccaa854
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {\tpause} } } */
+/* { dg-final { scan-assembler-not {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
new file mode 100644
index 00000000000..8729e35147e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-25.c b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
new file mode 100644
index 00000000000..f73553c9a9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_bnd_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
new file mode 100644
index 00000000000..9144e988735
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
@@ -0,0 +1,40 @@
+/* PR target/r84530 */
+/* { dg-do run } */
+/* { dg-options "-Os -mfunction-return=thunk" } */
+
+struct S { int i; };
+__attribute__((const, noinline, noclone))
+struct S foo (int x)
+{
+ struct S s;
+ s.i = x;
+ return s;
+}
+
+int a[2048], b[2048], c[2048], d[2048];
+struct S e[2048];
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ {
+ e[i] = foo (i);
+ a[i+2] = a[i] + a[i+1];
+ b[10] = b[10] + i;
+ c[i] = c[2047 - i];
+ d[i] = d[i + 1];
+ }
+}
+
+int
+main ()
+{
+ int i;
+ bar ();
+ for (i = 0; i < 1024; i++)
+ if (e[i].i != i)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
new file mode 100644
index 00000000000..0f7f388f459
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
new file mode 100644
index 00000000000..9ae37e835a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
new file mode 100644
index 00000000000..4bd0d2a27bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+extern void foo (void) __attribute__ ((function_return("thunk")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
new file mode 100644
index 00000000000..053841f6f7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+__attribute__ ((function_return("thunk-inline")))
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
new file mode 100644
index 00000000000..262e6780112
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+__attribute__ ((function_return("thunk-extern")))
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
new file mode 100644
index 00000000000..c1658e96673
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+extern void foo (void) __attribute__ ((function_return("keep")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
new file mode 100644
index 00000000000..eee230ca2f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "__x86_return_thunk:" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/pr85056.c b/gcc/testsuite/gcc.target/nvptx/pr85056.c
new file mode 100644
index 00000000000..2471cb83b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/pr85056.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-sources "pr85056a.c" } */
+
+extern void abort ();
+
+extern int a[];
+
+int
+main ()
+{
+ int i, sum;
+
+ sum = 0;
+ for (i = 0; i < 10; i++)
+ sum += a[i];
+
+ if (sum != 55)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/pr85056a.c b/gcc/testsuite/gcc.target/nvptx/pr85056a.c
new file mode 100644
index 00000000000..a45a5f2b07f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/pr85056a.c
@@ -0,0 +1,3 @@
+/* { dg-skip-if "" { *-*-* } } */
+
+int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
diff --git a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1-runnable.c b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1-runnable.c
new file mode 100644
index 00000000000..25c27bf9a37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1-runnable.c
@@ -0,0 +1,109 @@
+/* { dg-do run { target { powerpc*-*-* && p8vector_hw } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2 " } */
+
+/* Make sure the test case compiled with -O2 generates the same expected
+ results. The expected results were generated with -O0. */
+
+#include <altivec.h>
+#define TRUE 1
+#define FALSE 0
+
+#define DEBUG 1
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+void abort (void);
+
+typedef vector unsigned long long crypto_t;
+typedef vector unsigned long long v2di_t;
+typedef vector unsigned int v4si_t;
+typedef vector unsigned short v8hi_t;
+typedef vector unsigned char v16qi_t;
+
+v16qi_t crypto6a (v16qi_t a, v16qi_t b, v16qi_t c)
+{
+ return __builtin_crypto_vpermxor (a, b, c);
+}
+
+v8hi_t crypto6b (v8hi_t a, v8hi_t b, v8hi_t c)
+{
+ return __builtin_crypto_vpermxor (a, b, c);
+}
+
+v4si_t crypto6c (v4si_t a, v4si_t b, v4si_t c)
+{
+ return __builtin_crypto_vpermxor (a, b, c);
+}
+
+v2di_t crypto6d (v2di_t a, v2di_t b, v2di_t c)
+{
+ return __builtin_crypto_vpermxor (a, b, c);
+}
+
+int main()
+{
+ int i;
+ v16qi_t expected_v16qi, result_v16qi;
+ v8hi_t expected_v8hi, result_v8hi;
+ v4si_t expected_v4si, result_v4si;
+ v2di_t expected_v2di, result_v2di;
+ v16qi_t v16qi_arg_a, v16qi_arg_b, v16qi_arg_c;
+ v8hi_t v8hi_arg_a, v8hi_arg_b, v8hi_arg_c;
+ v4si_t v4si_arg_a, v4si_arg_b, v4si_arg_c;
+ v2di_t v2di_arg_a, v2di_arg_b, v2di_arg_c;
+
+ v16qi_arg_a = (vector unsigned char){ 7, 6, 5, 4, 3, 2, 1, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8 };
+ v16qi_arg_b = (vector unsigned char){ 1, 2, 3, 4, 5, 6, 7, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0 };
+ v16qi_arg_c = (vector unsigned char){ 7, 2, 5, 4, 3, 6, 1, 8,
+ 1, 6, 3, 4, 5, 2, 7, 0 };
+ expected_v16qi = (vector unsigned char){ 15, 10, 13, 12, 11, 14, 9, 0,
+ 9, 14, 11, 12, 13, 10, 15, 8 };
+
+ result_v16qi = crypto6a (v16qi_arg_a, v16qi_arg_b, v16qi_arg_c);
+
+ for (i = 0; i < 16; i++)
+ if (expected_v16qi[i] != result_v16qi[i])
+ printf("crypto6a: result_v16qi[%d] = %d, expected = %d\n",
+ i, result_v16qi[i], expected_v16qi[i]);
+
+ v8hi_arg_a = (vector unsigned short int){ 7, 6, 5, 4, 3, 2, 1, 0};
+ v8hi_arg_b = (vector unsigned short int){ 1, 2, 3, 4, 5, 6, 7, 8};
+ v8hi_arg_c = (vector unsigned short int){ 7, 2, 5, 4, 3, 6, 1, 8};
+ expected_v8hi = (vector unsigned short int){ 5, 0, 6, 0, 7, 0, 8};
+
+ result_v8hi = crypto6b (v8hi_arg_a, v8hi_arg_b, v8hi_arg_c);
+
+ for (i = 0; i < 8; i++)
+ if (expected_v8hi[i] != result_v8hi[i])
+ printf("crypto6a: result_v8hi[%d] = %d, expected = %d\n",
+ i, result_v8hi[i], expected_v8hi[i]);
+
+ v4si_arg_a = (vector unsigned int){ 7, 6, 5, 4};
+ v4si_arg_b = (vector unsigned int){ 15, 6, 7, 8};
+ v4si_arg_c = (vector unsigned int){ 7, 14, 3, 6};
+ expected_v4si = (vector unsigned int){ 7, 0, 8, 0};
+
+ result_v4si = crypto6c (v4si_arg_a, v4si_arg_b, v4si_arg_c);
+
+ for (i = 0; i < 4; i++)
+ if (expected_v4si[i] != result_v4si[i])
+ printf("crypto6a: result_v4si[%d] = %d, expected = %d\n",
+ i, result_v4si[i], expected_v4si[i]);
+
+ v2di_arg_a = (vector unsigned long long int){ 7, 6, };
+ v2di_arg_b = (vector unsigned long long int){ 15, 6, };
+ v2di_arg_c = (vector unsigned long long int){ 7, 14};
+ expected_v2di = (vector unsigned long long int){ 6, 0};
+
+ result_v2di = crypto6d (v2di_arg_a, v2di_arg_b, v2di_arg_c);
+
+ for (i = 0; i < 2; i++)
+ if (expected_v2di[i] != result_v2di[i])
+ printf("crypto6a: result_v2di[%d] = %d, expected = %d\n",
+ i, result_v2di[i], expected_v2di[i]);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c
index 365dead9fac..aaf9b40fc24 100644
--- a/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c
@@ -5,9 +5,7 @@
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
/* { dg-options "-mcpu=power7 -O2" } */
/* { dg-final { scan-assembler-times "divwe " 1 } } */
-/* { dg-final { scan-assembler-times "divweo " 1 } } */
/* { dg-final { scan-assembler-times "divweu " 1 } } */
-/* { dg-final { scan-assembler-times "divweuo " 1 } } */
/* { dg-final { scan-assembler-not "bl __builtin" } } */
int
@@ -16,20 +14,8 @@ div_we (int a, int b)
return __builtin_divwe (a, b);
}
-int
-div_weo (int a, int b)
-{
- return __builtin_divweo (a, b);
-}
-
unsigned int
div_weu (unsigned int a, unsigned int b)
{
return __builtin_divweu (a, b);
}
-
-unsigned int
-div_weuo (unsigned int a, unsigned int b)
-{
- return __builtin_divweuo (a, b);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c
index 829cd40cae8..92e494aa136 100644
--- a/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c
@@ -5,9 +5,7 @@
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
/* { dg-options "-mcpu=power7 -O2" } */
/* { dg-final { scan-assembler-times "divde " 1 } } */
-/* { dg-final { scan-assembler-times "divdeo " 1 } } */
/* { dg-final { scan-assembler-times "divdeu " 1 } } */
-/* { dg-final { scan-assembler-times "divdeuo " 1 } } */
/* { dg-final { scan-assembler-not "bl __builtin" } } */
long
@@ -16,20 +14,8 @@ div_de (long a, long b)
return __builtin_divde (a, b);
}
-long
-div_deo (long a, long b)
-{
- return __builtin_divdeo (a, b);
-}
-
unsigned long
div_deu (unsigned long a, unsigned long b)
{
return __builtin_divdeu (a, b);
}
-
-unsigned long
-div_deuo (unsigned long a, unsigned long b)
-{
- return __builtin_divdeuo (a, b);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-sdata-2.c b/gcc/testsuite/gcc.target/powerpc/ppc-sdata-2.c
index 570c81f7e33..ee77456ca4f 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-sdata-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-sdata-2.c
@@ -5,6 +5,7 @@
/* { dg-final { scan-assembler-not "\\.section\[ \t\]\\.sdata2," } } */
/* { dg-final { scan-assembler "sdat@sdarel\\(13\\)" } } */
/* { dg-final { scan-assembler "sdat2@sdarel\\(13\\)" } } */
+/* { dg-skip-if "" { *-*-* } { "-mno-readonly-in-sdata" } { "" } } */
int sdat = 2;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83660.C b/gcc/testsuite/gcc.target/powerpc/pr83660.C
new file mode 100644
index 00000000000..60adcdacb4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83660.C
@@ -0,0 +1,14 @@
+/* PR target/83660 */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=power7" } */
+
+#include <altivec.h>
+
+typedef __vector unsigned int uvec32_t __attribute__((__aligned__(16)));
+
+unsigned get_word(uvec32_t v)
+{
+ return ({const unsigned _B1 = 32;
+ vec_extract((uvec32_t)v, 2);});
+}
+
diff --git a/gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c b/gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c
new file mode 100644
index 00000000000..75e32a1c7c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table -fno-dwarf2-cfi-asm" } */
+
+/* Make sure that we do not emit .cfi directives when -fno-dwarf2-cfi-asm is being used. */
+
+int
+main ()
+{
+ return 0;
+}
+
+/* 1 x main
+/* { 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/gfortran.dg/array_constructor_52.f90 b/gcc/testsuite/gfortran.dg/array_constructor_52.f90
new file mode 100644
index 00000000000..63581acf989
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/array_constructor_52.f90
@@ -0,0 +1,11 @@
+! { dg-do run }
+! PR 84931 - long array constructors with type conversion were not
+! handled correctly.
+program test
+ implicit none
+ integer, parameter :: n = 2**16
+ real, dimension(n) :: y
+ integer :: i
+ y = (/ (1, i=1, n) /)
+ if (y(2) /= 1) stop 1
+end program test
diff --git a/gcc/testsuite/gfortran.dg/interface_41.f90 b/gcc/testsuite/gfortran.dg/interface_41.f90
new file mode 100644
index 00000000000..b5ea8af189d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_41.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! PR fortran/85001
+! Contributed by Gerhard Steinmetz.
+program p
+ type t
+ end type
+ call s
+contains
+ real function f(x)
+ class(t) :: x
+ dimension :: x(:)
+ f = 1.0
+ end
+ subroutine s
+ type(t) :: x(2)
+ real :: z
+ z = f(x) ! { dg-error "Rank mismatch in argument" }
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/matmul_rank_1.f90 b/gcc/testsuite/gfortran.dg/matmul_rank_1.f90
new file mode 100644
index 00000000000..f111b26018f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_rank_1.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! { dg-additional-options "-ffrontend-optimize" }
+! PR 85044 - used to die on allocating a negative amount of memory.
+! Test case by Gerhard Steinmetz.
+program p
+ real :: a(3,3) = 1.0
+ real :: b(33)
+ b = matmul(a, a) ! { dg-error "Incompatible ranks" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr64124.f90 b/gcc/testsuite/gfortran.dg/pr64124.f90
new file mode 100644
index 00000000000..349c20de204
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr64124.f90
@@ -0,0 +1,5 @@
+! { dg-do compile }
+! PR fortran/64124.f90
+ character(len=kind(1)) x
+ integer(len(x)) y
+ end
diff --git a/gcc/testsuite/gfortran.dg/pr65453.f90 b/gcc/testsuite/gfortran.dg/pr65453.f90
new file mode 100644
index 00000000000..8d30116b79d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr65453.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/65453
+! Contributed by Tobias Burnus <burnus at gcc.gnu.org>
+procedure() :: foo ! { dg-error "(1)" }
+ contains
+ subroutine foo() ! { dg-error "clashes with procedure" }
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/pr70409.f90 b/gcc/testsuite/gfortran.dg/pr70409.f90
new file mode 100644
index 00000000000..0372f6e9632
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr70409.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! PR fortran/70409
+! Contriubted by Harald Anlauf <anlauf at gmx dot de>
+program foo
+ integer, parameter :: huge_1 = huge(0_1)
+ character( huge_1 ), parameter :: x = 'abc'
+ character( huge(0_1) ), parameter :: y = 'abc'
+ character( huge(0_1)+0 ), parameter :: z = 'abcdef'
+ character( huge(0_1) ) :: a = 'abc'
+ integer, parameter :: huge_2 = huge(0_2)
+ character( huge_2 ), parameter :: u = 'abc'
+ character( huge(0_2) ), parameter :: v = 'abc'
+ character(int(huge(0_2),4)), parameter :: w = 'abcdef'
+ character( huge(0_2) ) :: b = 'abc'
+ if (len(x) /= huge_1) stop 1
+ if (len(y) /= huge_1) stop 2
+ if (len(z) /= huge_1) stop 3
+ if (len(a) /= huge_1) stop 4
+ if (len(u) /= huge_2) stop 5
+ if (len(v) /= huge_2) stop 6
+ if (len(w) /= huge_2) stop 7
+ if (len(b) /= huge_2) stop 8
+end program foo
diff --git a/gcc/testsuite/gfortran.dg/pr83939.f90 b/gcc/testsuite/gfortran.dg/pr83939.f90
new file mode 100644
index 00000000000..dfeaac71630
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr83939.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+elemental function f() result(s) ! { dg-error "shall not have an ALLOCATABLE or POINTER" }
+ allocatable s
+ allocate(s)
+ s = 3.5
+end function
+
+elemental function g() result(s) ! { dg-error "shall not have an ALLOCATABLE or POINTER" }
+ pointer s
+ allocate(s)
+ s = 3.5
+end function
diff --git a/gcc/testsuite/gfortran.dg/pr84734.f90 b/gcc/testsuite/gfortran.dg/pr84734.f90
new file mode 100644
index 00000000000..4b117ae43e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr84734.f90
@@ -0,0 +1,4 @@
+! { dg-do compile }
+! PR fortran/84734
+ integer :: b(huge(1_8)+1_8) = 0 ! { dg-error "Arithmetic overflow" }
+ end
diff --git a/gcc/testsuite/gfortran.dg/pr85520.f90 b/gcc/testsuite/gfortran.dg/pr85520.f90
new file mode 100644
index 00000000000..3e66a9020f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr85520.f90
@@ -0,0 +1,7 @@
+! { dg-do run }
+! PR fortran/85520
+! Original code from Gerhard Steinmetz <gscfq at t-online dot de>
+program p
+ character(-huge(1)) :: c = ' '
+ if (len(c) /= 0) stop 1
+end
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 29faf59b998..c392488e5bd 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -5386,7 +5386,8 @@ proc check_effective_target_vect_load_lanes { } {
verbose "check_effective_target_vect_load_lanes: using cached result" 2
} else {
set et_vect_load_lanes 0
- if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok])
+ # We don't support load_lanes correctly on big-endian arm.
+ if { ([istarget arm-*-*] && [check_effective_target_arm_neon_ok])
|| [istarget aarch64*-*-*] } {
set et_vect_load_lanes 1
}
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 53bdd423fb3..a51b1b81740 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1436,7 +1436,7 @@ find_clusters_1 (same_succ *same_succ)
/* TODO: handle blocks with phi-nodes. We'll have to find corresponding
phi-nodes in bb1 and bb2, with the same alternatives for the same
preds. */
- if (bb_has_non_vop_phi (bb1))
+ if (bb_has_non_vop_phi (bb1) || bb_has_abnormal_pred (bb1))
continue;
nr_comparisons = 0;
@@ -1444,7 +1444,7 @@ find_clusters_1 (same_succ *same_succ)
{
bb2 = BASIC_BLOCK_FOR_FN (cfun, j);
- if (bb_has_non_vop_phi (bb2))
+ if (bb_has_non_vop_phi (bb2) || bb_has_abnormal_pred (bb2))
continue;
if (BB_CLUSTER (bb1) != NULL && BB_CLUSTER (bb1) == BB_CLUSTER (bb2))
diff --git a/gcc/valtrack.c b/gcc/valtrack.c
index 26a15ea42cd..702a6261973 100644
--- a/gcc/valtrack.c
+++ b/gcc/valtrack.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "valtrack.h"
#include "regs.h"
#include "emit-rtl.h"
+#include "rtl-iter.h"
/* gen_lowpart_no_emit hook implementation for DEBUG_INSNs. In DEBUG_INSNs,
all lowpart SUBREGs are valid, despite what the machine requires for
@@ -148,6 +149,7 @@ struct rtx_subst_pair
{
rtx to;
bool adjusted;
+ rtx_insn *insn;
};
/* DATA points to an rtx_subst_pair. Return the value that should be
@@ -165,6 +167,23 @@ propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data)
pair->adjusted = true;
pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode);
pair->to = make_compound_operation (pair->to, SET);
+ /* Avoid propagation from growing DEBUG_INSN expressions too much. */
+ int cnt = 0;
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, pair->to, ALL)
+ if (REG_P (*iter) && ++cnt > 1)
+ {
+ rtx dval = make_debug_expr_from_rtl (old_rtx);
+ /* Emit a debug bind insn. */
+ rtx bind
+ = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx),
+ DEBUG_EXPR_TREE_DECL (dval), pair->to,
+ VAR_INIT_STATUS_INITIALIZED);
+ rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn);
+ df_insn_rescan (bind_insn);
+ pair->to = dval;
+ break;
+ }
return pair->to;
}
return copy_rtx (pair->to);
@@ -185,6 +204,7 @@ propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src,
struct rtx_subst_pair p;
p.to = src;
p.adjusted = false;
+ p.insn = NEXT_INSN (insn);
next = NEXT_INSN (insn);
last = NEXT_INSN (last);