From 86118fbdbafe6af54b2da467e1073c49e1742116 Mon Sep 17 00:00:00 2001 From: hjl Date: Tue, 16 Jan 2018 11:17:49 +0000 Subject: [PATCH 7/9] x86: Add -mindirect-branch-register Add -mindirect-branch-register to force indirect branch via register. This is implemented by disabling patterns of indirect branch via memory, similar to TARGET_X32. -mindirect-branch= and -mfunction-return= tests are updated with -mno-indirect-branch-register to avoid false test failures when -mindirect-branch-register is added to RUNTESTFLAGS for "make check". gcc/ Backport from mainline 2018-01-14 H.J. Lu * 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. gcc/testsuite/ Backport from mainline 2018-01-14 H.J. Lu * 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. i386: Rename to ix86_indirect_branch_register Rename the variable for -mindirect-branch-register to ix86_indirect_branch_register to match the command-line option name. Backport from mainline 2018-01-15 H.J. Lu * 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. x86: Rewrite ix86_indirect_branch_register logic Rewrite ix86_indirect_branch_register logic with (and (not (match_test "ix86_indirect_branch_register")) (original condition before r256662)) Backport from mainline 2018-01-15 H.J. Lu * config/i386/predicates.md (constant_call_address_operand): Rewrite ix86_indirect_branch_register logic. (sibcall_insn_operand): Likewise. Don't check ix86_indirect_branch_register for GOT operand Since GOT_memory_operand and GOT32_symbol_operand are simple pattern matches, don't check ix86_indirect_branch_register here. If needed, -mindirect-branch= will convert indirect branch via GOT slot to a call and return thunk. Backport from mainline 2018-01-15 H.J. Lu * 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. i386: Rewrite indirect_branch_operand logic Backport from mainline 2018-01-15 H.J. Lu * config/i386/predicates.md (indirect_branch_operand): Rewrite ix86_indirect_branch_register logic. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@256735 138bc75d-0d04-0410-961f-82ee72b054a4 [Ubuntu note: Dropped indirect-thunk-5.c, indirect-thunk-6.c, indirect-thunk-bnd-3.c, indirect-thunk-bnd-4.c, indirect-thunk-extern-5.c, indirect-thunk-extern-6.c, indirect-thunk-inline-5.c, and indirect-thunk-inline-6.c tests due to gcc 5.4 and earlier not supporting the -fno-plt option. --sbeattie,] --- src/gcc/config/i386/constraints.md | 6 + src/gcc/config/i386/i386.md | 34 ++++++---- src/gcc/config/i386/i386.opt | 4 + src/gcc/config/i386/predicates.md | 9 +- src/gcc/doc/invoke.texi | 7 +- src/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c | 22 ++++++ src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c | 20 +++++ src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c | 19 +++++ src/gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 2 src/gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 2 39 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c Index: b/src/gcc/config/i386/constraints.md =================================================================== --- a/src/gcc/config/i386/constraints.md +++ b/src/gcc/config/i386/constraints.md @@ -157,12 +157,14 @@ (define_constraint "Bs" "@internal Sibcall memory operand." - (and (not (match_test "TARGET_X32")) + (and (not (match_test "ix86_indirect_branch_register")) + (not (match_test "TARGET_X32")) (match_operand 0 "sibcall_memory_operand"))) (define_constraint "Bw" "@internal Call memory operand." - (and (not (match_test "TARGET_X32")) + (and (not (match_test "ix86_indirect_branch_register")) + (not (match_test "TARGET_X32")) (match_operand 0 "memory_operand"))) (define_constraint "Bz" Index: b/src/gcc/config/i386/i386.md =================================================================== --- a/src/gcc/config/i386/i386.md +++ b/src/gcc/config/i386/i386.md @@ -11554,7 +11554,7 @@ [(set (pc) (match_operand 0 "indirect_branch_operand"))] "" { - if (TARGET_X32) + if (TARGET_X32 || ix86_indirect_branch_register) operands[0] = convert_memory_address (word_mode, operands[0]); cfun->machine->has_local_indirect_jump = true; }) @@ -11607,7 +11607,7 @@ OPTAB_DIRECT); } - if (TARGET_X32) + if (TARGET_X32 || ix86_indirect_branch_register) operands[0] = convert_memory_address (word_mode, operands[0]); cfun->machine->has_local_indirect_jump = true; }) @@ -11764,7 +11764,7 @@ [(call (mem:QI (match_operand:W 0 "memory_operand" "m")) (match_operand 1)) (unspec [(const_int 0)] UNSPEC_PEEPSIB)] - "!TARGET_X32" + "!TARGET_X32 && !ix86_indirect_branch_register" "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) @@ -11773,7 +11773,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 + && !ix86_indirect_branch_register + && SIBLING_CALL_P (peep2_next_insn (1)) && peep2_reg_dead_p (2, operands[0])" [(parallel [(call (mem:QI (match_dup 1)) (match_dup 3)) @@ -11785,7 +11787,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 + && !ix86_indirect_branch_register + && SIBLING_CALL_P (peep2_next_insn (2)) && peep2_reg_dead_p (3, operands[0])" [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE) (parallel [(call (mem:QI (match_dup 1)) @@ -11806,7 +11810,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) @@ -11826,7 +11830,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) @@ -11878,7 +11882,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 + && !ix86_indirect_branch_register + && peep2_reg_dead_p (2, operands[0])" [(set (pc) (match_dup 1))]) ;; Call subroutine, returning value in operand 0 @@ -11928,7 +11934,7 @@ (call (mem:QI (match_operand:W 1 "memory_operand" "m")) (match_operand 2))) (unspec [(const_int 0)] UNSPEC_PEEPSIB)] - "!TARGET_X32" + "!TARGET_X32 && !ix86_indirect_branch_register" "* return ix86_output_call_insn (insn, operands[1]);" [(set_attr "type" "callv")]) @@ -11938,7 +11944,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 + && !ix86_indirect_branch_register + && SIBLING_CALL_P (peep2_next_insn (1)) && peep2_reg_dead_p (2, operands[0])" [(parallel [(set (match_dup 2) (call (mem:QI (match_dup 1)) @@ -11952,7 +11960,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 + && !ix86_indirect_branch_register + && SIBLING_CALL_P (peep2_next_insn (2)) && peep2_reg_dead_p (3, operands[0])" [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE) (parallel [(set (match_dup 2) @@ -11976,7 +11986,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) Index: b/src/gcc/config/i386/i386.opt =================================================================== --- a/src/gcc/config/i386/i386.opt +++ b/src/gcc/config/i386/i386.opt @@ -900,3 +900,7 @@ Enum(indirect_branch) String(thunk-inlin 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. Index: b/src/gcc/config/i386/predicates.md =================================================================== --- a/src/gcc/config/i386/predicates.md +++ b/src/gcc/config/i386/predicates.md @@ -607,7 +607,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 "ix86_indirect_branch_register")) + (not (match_test "TARGET_X32")) (match_operand 0 "memory_operand")))) ;; Test for a valid operand for a call instruction. @@ -616,7 +617,8 @@ (ior (match_test "constant_call_address_operand (op, mode == VOIDmode ? mode : Pmode)") (match_operand 0 "call_register_no_elim_operand") - (and (not (match_test "TARGET_X32")) + (and (not (match_test "ix86_indirect_branch_register")) + (not (match_test "TARGET_X32")) (match_operand 0 "memory_operand")))) ;; Similarly, but for tail calls, in which we cannot allow memory references. @@ -624,7 +626,8 @@ (ior (match_test "constant_call_address_operand (op, mode == VOIDmode ? mode : Pmode)") (match_operand 0 "register_no_elim_operand") - (and (not (match_test "TARGET_X32")) + (and (not (match_test "ix86_indirect_branch_register")) + (not (match_test "TARGET_X32")) (match_operand 0 "sibcall_memory_operand")))) ;; Match exactly zero. Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { 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); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { 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); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ void func0 (void); void func1 (void); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */ void func0 (void); void func1 (void); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! x32 } } } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */ +/* { 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]; Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! x32 } } } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */ +/* { 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]; Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ void func0 (void); void func1 (void); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ typedef void (*dispatch_t)(long offset); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c +++ b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ void func0 (void); void func1 (void); Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c =================================================================== --- /dev/null +++ b/src/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" } } */ Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c =================================================================== --- /dev/null +++ b/src/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" } } */ Index: b/src/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c =================================================================== --- /dev/null +++ b/src/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" } } */ Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-10.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-10.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */ extern void (*bar) (void); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-11.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-11.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-11.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */ +/* { 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); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-12.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-12.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-12.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */ +/* { 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); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-13.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-13.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-13.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */ +/* { 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"))); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-14.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-14.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-14.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */ extern void (*bar) (void); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-15.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-15.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-15.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */ +/* { 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); Index: b/src/gcc/testsuite/gcc.target/i386/ret-thunk-9.c =================================================================== --- a/src/gcc/testsuite/gcc.target/i386/ret-thunk-9.c +++ b/src/gcc/testsuite/gcc.target/i386/ret-thunk-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */ extern void (*bar) (void);