On Fri, Jan 31, 2025 at 12:09 PM H.J. Lu <[email protected]> wrote:
>
> -mindirect-branch-register requires indirect call and jump via register.
> For -mindirect-branch-register, expanding indirect call via register and
> update call patterns and peepholes to disable indirect call via memory.
I think the approach is wrong, we already have
TARGET_INDIRECT_BRANCH_REGISTER that includes
ix86_indirect_branch_register:
#define TARGET_INDIRECT_BRANCH_REGISTER \
(ix86_indirect_branch_register \
|| cfun->machine->indirect_branch_type != indirect_branch_keep)
and:
(define_constraint "Bs"
"@internal Sibcall memory operand."
(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")
(match_test "Pmode == DImode")
(match_operand 0 "GOT_memory_operand"))))
(define_constraint "Bw"
"@internal Call memory operand."
(ior (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
(not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand"))
(and (match_test "TARGET_X32")
(match_test "Pmode == DImode")
(match_operand 0 "GOT_memory_operand"))))
So, the changes in the patch are mostly redundant, the remaining cases
should use TARGET_INDIRECT_BRANCH_REGISTER instead.
Uros.
>
> gcc/
>
> PR target/115673
> * config/i386/i386-expand.cc (ix86_expand_call): Force indirect
> call via register for -mindirect-branch-register.
> * config/i386/i386.md (*call): Disable indirect call via memory
> for -mindirect-branch-register.
> (*call_got_x32): Likewise.
> (*sibcall_GOT_32): Likewise.
> (*sibcall): Likewise.
> (*sibcall_memory): Likewise.
> (*call_pop): Likewise.
> (*sibcall_pop): Likewise.
> (*sibcall_pop_memory): Likewise.
> (*call_value): Likewise.
> (*call_value_got_x32): Likewise.
> (*sibcall_value_GOT_32): Likewise.
> (*sibcall_value): Likewise.
> (*sibcall_value_memory): Likewise.
> (*call_value_pop): Likewise.
> (*sibcall_value_pop): Likewise.
> (*sibcall_value_pop_memory): Likewise.
> Disable indirect call via memory peepholes for
> -mindirect-branch-register.
>
> gcc/testsuite/
>
> PR target/115673
> * gcc.target/i386/pr115673-1-x32.c: New test.
> * gcc.target/i386/pr115673-1.c: Likewise.
> * gcc.target/i386/pr115673-2-x32.c: Likewise.
> * gcc.target/i386/pr115673-2.c: Likewise.
> * gcc.target/i386/pr115673-3-x32.c: Likewise.
> * gcc.target/i386/pr115673-3.c: Likewise.
> * gcc.target/i386/pr115673-4-x32.c: Likewise.
> * gcc.target/i386/pr115673-4.c: Likewise.
> * gcc.target/i386/pr115673-5-x32.c: Likewise.
> * gcc.target/i386/pr115673-5.c: Likewise.
> * gcc.target/i386/pr115673-6-x32.c: Likewise.
> * gcc.target/i386/pr115673-6.c: Likewise.
> * gcc.target/i386/pr115673-7-x32.c: Likewise.
> * gcc.target/i386/pr115673-7.c: Likewise.
> * gcc.target/i386/pr115673-8-x32.c: Likewise.
> * gcc.target/i386/pr115673-8.c: Likewise.
> * gcc.target/i386/pr115673-9-x32.c: Likewise.
> * gcc.target/i386/pr115673-9.c: Likewise.
> * gcc.target/i386/pr115673-10-x32.c: Likewise.
> * gcc.target/i386/pr115673-10.c: Likewise.
> * gcc.target/i386/pr115673-11-x32.c: Likewise.
> * gcc.target/i386/pr115673-11.c: Likewise.
> * gcc.target/i386/pr115673-12-x32.c: Likewise.
> * gcc.target/i386/pr115673-12.c: Likewise.
>
> Co-Authored-By: Uros Bizjak <[email protected]>
> Signed-off-by: H.J. Lu <[email protected]>
> ---
> gcc/config/i386/i386-expand.cc | 20 +--
> gcc/config/i386/i386.md | 118 ++++++++++++------
> .../gcc.target/i386/pr115673-1-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-1.c | 14 +++
> .../gcc.target/i386/pr115673-10-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-10.c | 15 +++
> .../gcc.target/i386/pr115673-11-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-11.c | 14 +++
> .../gcc.target/i386/pr115673-12-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-12.c | 14 +++
> .../gcc.target/i386/pr115673-2-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-2.c | 15 +++
> .../gcc.target/i386/pr115673-3-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-3.c | 14 +++
> .../gcc.target/i386/pr115673-4-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-4.c | 14 +++
> .../gcc.target/i386/pr115673-5-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-5.c | 13 ++
> .../gcc.target/i386/pr115673-6-x32.c | 15 +++
> gcc/testsuite/gcc.target/i386/pr115673-6.c | 14 +++
> .../gcc.target/i386/pr115673-7-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-7.c | 13 ++
> .../gcc.target/i386/pr115673-8-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-8.c | 13 ++
> .../gcc.target/i386/pr115673-9-x32.c | 8 ++
> gcc/testsuite/gcc.target/i386/pr115673-9.c | 14 +++
> 26 files changed, 365 insertions(+), 43 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-1-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-1.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-10-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-10.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-11-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-11.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-12-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-12.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-2-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-3-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-3.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-4-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-4.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-5-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-5.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-6-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-6.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-7-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-7.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-8-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-8.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-9-x32.c
> create mode 100644 gcc/testsuite/gcc.target/i386/pr115673-9.c
>
> diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
> index 117f6f6f7eb..2fbb95aebaf 100644
> --- a/gcc/config/i386/i386-expand.cc
> +++ b/gcc/config/i386/i386-expand.cc
> @@ -10223,15 +10223,21 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx
> callarg1,
> && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
> && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
> fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
> + else if (ix86_indirect_branch_register && MEM_P (fnaddr))
> + {
> + fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
> + fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
> + }
> /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
Probably only the above hunk is needed, but using
TARGET_INDIRECT_BRANCH_REGISTER.
> branch via x32 GOT slot is OK. */
> - else if (!(TARGET_X32
> - && MEM_P (fnaddr)
> - && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
> - && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode))
> - && (sibcall
> - ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
> - : !call_insn_operand (XEXP (fnaddr, 0), word_mode)))
> + if (TARGET_X32
> + && MEM_P (fnaddr)
> + && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
> + && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode))
> + ;
> + else if (sibcall
> + ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
> + : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
> {
> fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
> fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index 52c02b6351a..25b29947930 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -20122,18 +20122,23 @@ (define_expand "sibcall"
> })
>
> (define_insn "*call"
> - [(call (mem:QI (match_operand:W 0 "call_insn_operand" "<c>BwBz"))
> + [(call (mem:QI (match_operand:W 0 "call_insn_operand" "<c>,BwBz"))
> (match_operand 1))]
> "!SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[0]);"
> - [(set_attr "type" "call")])
> + [(set_attr "type" "call")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> ;; This covers both call and sibcall since only GOT slot is allowed.
> (define_insn "*call_got_x32"
> [(call (mem:QI (zero_extend:DI
> (match_operand:SI 0 "GOT_memory_operand" "Bg")))
> (match_operand 1))]
> - "TARGET_X32"
> + "TARGET_X32 && !ix86_indirect_branch_register"
This also needs !TARGET_INDIRECT_BRANCH_REGISTER.
> {
> rtx fnaddr = gen_const_mem (DImode, XEXP (operands[0], 0));
> return ix86_output_call_insn (insn, fnaddr);
> @@ -20149,7 +20154,7 @@ (define_insn "*sibcall_GOT_32"
> (match_operand:SI 1 "GOT32_symbol_operand"))))
> (match_operand 2))]
> "!TARGET_MACHO
> - && !TARGET_64BIT
> + && !TARGET_64BIT && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
!T_I_B_R is enough, it already includes ix86_indirect_branch_register.
> && SIBLING_CALL_P (insn)"
> {
> @@ -20160,17 +20165,23 @@ (define_insn "*sibcall_GOT_32"
> [(set_attr "type" "call")])
>
> (define_insn "*sibcall"
> - [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
> + [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "U,BsBz"))
> (match_operand 1))]
> "SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[0]);"
> - [(set_attr "type" "call")])
> + [(set_attr "type" "call")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_memory"
> [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
> (match_operand 1))
> (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> - "!TARGET_X32 && !TARGET_INDIRECT_BRANCH_REGISTER"
> + "!TARGET_X32 && !ix86_indirect_branch_register
> + && !TARGET_INDIRECT_BRANCH_REGISTER"
> "* return ix86_output_call_insn (insn, operands[0]);"
> [(set_attr "type" "call")])
>
> @@ -20179,7 +20190,7 @@ (define_peephole2
> (match_operand:W 1 "memory_operand"))
> (call (mem:QI (match_dup 0))
> (match_operand 3))]
> - "!TARGET_X32
> + "!TARGET_X32 && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
> && SIBLING_CALL_P (peep2_next_insn (1))
> && !reg_mentioned_p (operands[0],
> @@ -20194,7 +20205,7 @@ (define_peephole2
> (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
> (call (mem:QI (match_dup 0))
> (match_operand 3))]
> - "!TARGET_X32
> + "!TARGET_X32 && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
> && SIBLING_CALL_P (peep2_next_insn (2))
> && !reg_mentioned_p (operands[0],
> @@ -20218,24 +20229,34 @@ (define_expand "call_pop"
> })
>
> (define_insn "*call_pop"
> - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
> + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "l,BwBz"))
> (match_operand 1))
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> - (match_operand:SI 2 "immediate_operand" "i")))]
> + (match_operand:SI 2 "immediate_operand" "i,i")))]
> "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[0]);"
> - [(set_attr "type" "call")])
> + [(set_attr "type" "call")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_pop"
> - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "UBsBz"))
> + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "U,BsBz"))
> (match_operand 1))
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> - (match_operand:SI 2 "immediate_operand" "i")))]
> + (match_operand:SI 2 "immediate_operand" "i,i")))]
> "!TARGET_64BIT && SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[0]);"
> - [(set_attr "type" "call")])
> + [(set_attr "type" "call")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_pop_memory"
> [(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
> @@ -20244,7 +20265,7 @@ (define_insn "*sibcall_pop_memory"
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 2 "immediate_operand" "i")))
> (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> - "!TARGET_64BIT"
> + "!TARGET_64BIT && !ix86_indirect_branch_register"
> "* return ix86_output_call_insn (insn, operands[0]);"
> [(set_attr "type" "call")])
>
> @@ -20256,7 +20277,8 @@ (define_peephole2
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 4 "immediate_operand")))])]
> - "!TARGET_64BIT && SIBLING_CALL_P (peep2_next_insn (1))
> + "!TARGET_64BIT && !ix86_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))
> @@ -20275,7 +20297,8 @@ (define_peephole2
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 4 "immediate_operand")))])]
> - "!TARGET_64BIT && SIBLING_CALL_P (peep2_next_insn (2))
> + "!TARGET_64BIT && !ix86_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)
> @@ -20325,11 +20348,16 @@ (define_expand "sibcall_value"
>
> (define_insn "*call_value"
> [(set (match_operand 0)
> - (call (mem:QI (match_operand:W 1 "call_insn_operand" "<c>BwBz"))
> + (call (mem:QI (match_operand:W 1 "call_insn_operand" "<c>,BwBz"))
> (match_operand 2)))]
> "!SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[1]);"
> - [(set_attr "type" "callv")])
> + [(set_attr "type" "callv")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> ;; This covers both call and sibcall since only GOT slot is allowed.
> (define_insn "*call_value_got_x32"
> @@ -20338,7 +20366,7 @@ (define_insn "*call_value_got_x32"
> (zero_extend:DI
> (match_operand:SI 1 "GOT_memory_operand" "Bg")))
> (match_operand 2)))]
> - "TARGET_X32"
> + "TARGET_X32 && !ix86_indirect_branch_register"
> {
> rtx fnaddr = gen_const_mem (DImode, XEXP (operands[1], 0));
> return ix86_output_call_insn (insn, fnaddr);
> @@ -20355,7 +20383,7 @@ (define_insn "*sibcall_value_GOT_32"
> (match_operand:SI 2 "GOT32_symbol_operand"))))
> (match_operand 3)))]
> "!TARGET_MACHO
> - && !TARGET_64BIT
> + && !TARGET_64BIT && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
> && SIBLING_CALL_P (insn)"
> {
> @@ -20367,18 +20395,24 @@ (define_insn "*sibcall_value_GOT_32"
>
> (define_insn "*sibcall_value"
> [(set (match_operand 0)
> - (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
> + (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "U,BsBz"))
> (match_operand 2)))]
> "SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[1]);"
> - [(set_attr "type" "callv")])
> + [(set_attr "type" "callv")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_value_memory"
> [(set (match_operand 0)
> (call (mem:QI (match_operand:W 1 "memory_operand" "m"))
> (match_operand 2)))
> (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> - "!TARGET_X32 && !TARGET_INDIRECT_BRANCH_REGISTER"
> + "!TARGET_X32 && !ix86_indirect_branch_register
> + && !TARGET_INDIRECT_BRANCH_REGISTER"
> "* return ix86_output_call_insn (insn, operands[1]);"
> [(set_attr "type" "callv")])
>
> @@ -20388,7 +20422,7 @@ (define_peephole2
> (set (match_operand 2)
> (call (mem:QI (match_dup 0))
> (match_operand 3)))]
> - "!TARGET_X32
> + "!TARGET_X32 && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
> && SIBLING_CALL_P (peep2_next_insn (1))
> && !reg_mentioned_p (operands[0],
> @@ -20405,7 +20439,7 @@ (define_peephole2
> (set (match_operand 2)
> (call (mem:QI (match_dup 0))
> (match_operand 3)))]
> - "!TARGET_X32
> + "!TARGET_X32 && !ix86_indirect_branch_register
> && !TARGET_INDIRECT_BRANCH_REGISTER
> && SIBLING_CALL_P (peep2_next_insn (2))
> && !reg_mentioned_p (operands[0],
> @@ -20432,25 +20466,35 @@ (define_expand "call_value_pop"
>
> (define_insn "*call_value_pop"
> [(set (match_operand 0)
> - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
> + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "l,BwBz"))
> (match_operand 2)))
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> - (match_operand:SI 3 "immediate_operand" "i")))]
> + (match_operand:SI 3 "immediate_operand" "i,i")))]
> "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[1]);"
> - [(set_attr "type" "callv")])
> + [(set_attr "type" "callv")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_value_pop"
> [(set (match_operand 0)
> - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "UBsBz"))
> + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "U,BsBz"))
> (match_operand 2)))
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> - (match_operand:SI 3 "immediate_operand" "i")))]
> + (match_operand:SI 3 "immediate_operand" "i,i")))]
> "!TARGET_64BIT && SIBLING_CALL_P (insn)"
> "* return ix86_output_call_insn (insn, operands[1]);"
> - [(set_attr "type" "callv")])
> + [(set_attr "type" "callv")
> + (set (attr "enabled")
> + (if_then_else
> + (eq_attr "alternative" "1")
> + (symbol_ref "!ix86_indirect_branch_register")
> + (const_string "*")))])
>
> (define_insn "*sibcall_value_pop_memory"
> [(set (match_operand 0)
> @@ -20460,7 +20504,7 @@ (define_insn "*sibcall_value_pop_memory"
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 3 "immediate_operand" "i")))
> (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> - "!TARGET_64BIT"
> + "!TARGET_64BIT && !ix86_indirect_branch_register"
> "* return ix86_output_call_insn (insn, operands[1]);"
> [(set_attr "type" "callv")])
>
> @@ -20473,7 +20517,8 @@ (define_peephole2
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 4 "immediate_operand")))])]
> - "!TARGET_64BIT && SIBLING_CALL_P (peep2_next_insn (1))
> + "!TARGET_64BIT && !ix86_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)
> @@ -20494,7 +20539,8 @@ (define_peephole2
> (set (reg:SI SP_REG)
> (plus:SI (reg:SI SP_REG)
> (match_operand:SI 4 "immediate_operand")))])]
> - "!TARGET_64BIT && SIBLING_CALL_P (peep2_next_insn (2))
> + "!TARGET_64BIT && !ix86_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)
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-1-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-1-x32.c
> new file mode 100644
> index 00000000000..a727e92adbe
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-1-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-1.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-1.c
> b/gcc/testsuite/gcc.target/i386/pr115673-1.c
> new file mode 100644
> index 00000000000..56884f3d952
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-1.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void);
> +
> +void
> +foo (void)
> +{
> + bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT\\(" { target ia32 } } }
> */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-10-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-10-x32.c
> new file mode 100644
> index 00000000000..3249f2d251b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-10-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-10.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-10.c
> b/gcc/testsuite/gcc.target/i386/pr115673-10.c
> new file mode 100644
> index 00000000000..a0e2ff3760b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-10.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void);
> +
> +int
> +foo (void)
> +{
> + bar ();
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT, " { target ia32 } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-11-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-11-x32.c
> new file mode 100644
> index 00000000000..74f18737b3c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-11-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-11.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-11.c
> b/gcc/testsuite/gcc.target/i386/pr115673-11.c
> new file mode 100644
> index 00000000000..deb0c0df3c7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-11.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> + return bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT, " { target ia32 } } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-12-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-12-x32.c
> new file mode 100644
> index 00000000000..1cf5be6ed95
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-12-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-12.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-12.c
> b/gcc/testsuite/gcc.target/i386/pr115673-12.c
> new file mode 100644
> index 00000000000..333b9c813e5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-12.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> + return bar () + 1;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT, " { target ia32 } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-2-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-2-x32.c
> new file mode 100644
> index 00000000000..40ca0be4d12
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-2-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-2.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-2.c
> b/gcc/testsuite/gcc.target/i386/pr115673-2.c
> new file mode 100644
> index 00000000000..807724e0310
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-2.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void);
> +
> +int
> +foo (void)
> +{
> + bar ();
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT\\(" { target ia32 } } }
> */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-3-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-3-x32.c
> new file mode 100644
> index 00000000000..d80543e4c15
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-3-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-3.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-3.c
> b/gcc/testsuite/gcc.target/i386/pr115673-3.c
> new file mode 100644
> index 00000000000..1cd3fcbdf66
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-3.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> + return bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT\\(" { target ia32 } } }
> */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-4-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-4-x32.c
> new file mode 100644
> index 00000000000..bfb5b8accd6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-4-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-4.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-4.c
> b/gcc/testsuite/gcc.target/i386/pr115673-4.c
> new file mode 100644
> index 00000000000..86d13b73bfc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-4.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> + return bar () + 1;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT\\(" { target ia32 } } }
> */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-5-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-5-x32.c
> new file mode 100644
> index 00000000000..65d52447a1a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-5-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-5.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-5.c
> b/gcc/testsuite/gcc.target/i386/pr115673-5.c
> new file mode 100644
> index 00000000000..7b1f8c17c2d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-5.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void) __attribute__((visibility("hidden")));
> +
> +void
> +foo (void)
> +{
> + bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-6-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-6-x32.c
> new file mode 100644
> index 00000000000..f728b15db77
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-6-x32.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void) __attribute__((visibility("hidden")));
> +
> +int
> +foo (void)
> +{
> + bar ();
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-6.c
> b/gcc/testsuite/gcc.target/i386/pr115673-6.c
> new file mode 100644
> index 00000000000..a4f3b68f3e7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-6.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void) __attribute__((visibility("hidden")));
> +
> +int
> +foo (void)
> +{
> + bar ();
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-7-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-7-x32.c
> new file mode 100644
> index 00000000000..084d8125b71
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-7-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-7.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-7.c
> b/gcc/testsuite/gcc.target/i386/pr115673-7.c
> new file mode 100644
> index 00000000000..fdc0db951bf
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-7.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void) __attribute__((visibility("hidden")));
> +
> +int
> +foo (void)
> +{
> + return bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-8-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-8-x32.c
> new file mode 100644
> index 00000000000..23c0bf5ad80
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-8-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-8.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-8.c
> b/gcc/testsuite/gcc.target/i386/pr115673-8.c
> new file mode 100644
> index 00000000000..03d5f008e0d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-8.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern int bar (void) __attribute__((visibility("hidden")));
> +
> +int
> +foo (void)
> +{
> + return bar () + 1;
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar, " } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-9-x32.c
> b/gcc/testsuite/gcc.target/i386/pr115673-9-x32.c
> new file mode 100644
> index 00000000000..f4370772ec1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-9-x32.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-require-effective-target maybe_x32 } */
> +/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +#include "pr115673-9.c"
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr115673-9.c
> b/gcc/testsuite/gcc.target/i386/pr115673-9.c
> new file mode 100644
> index 00000000000..365f65fb194
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr115673-9.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fno-pic -fno-plt -mindirect-branch-register" } */
> +
> +extern void bar (void);
> +
> +void
> +foo (void)
> +{
> + bar ();
> +}
> +
> +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { !
> ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT, " { target ia32 } } } */
> +/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
> --
> 2.48.1
>