-fno-plt forces external call to indirect call via GOT memory. But
-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.
gcc/
PR target/118713
* 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.
gcc/testsuite/
PR target/118713
* gcc.target/i386/pr118713-1-x32.c: New test.
* gcc.target/i386/pr118713-1.c: Likewise.
* gcc.target/i386/pr118713-2-x32.c: Likewise.
* gcc.target/i386/pr118713-2.c: Likewise.
* gcc.target/i386/pr118713-3-x32.c: Likewise.
* gcc.target/i386/pr118713-3.c: Likewise.
* gcc.target/i386/pr118713-4-x32.c: Likewise.
* gcc.target/i386/pr118713-4.c: Likewise.
* gcc.target/i386/pr118713-5-x32.c: Likewise.
* gcc.target/i386/pr118713-5.c: Likewise.
* gcc.target/i386/pr118713-6-x32.c: Likewise.
* gcc.target/i386/pr118713-6.c: Likewise.
* gcc.target/i386/pr118713-7-x32.c: Likewise.
* gcc.target/i386/pr118713-7.c: Likewise.
* gcc.target/i386/pr118713-8-x32.c: Likewise.
* gcc.target/i386/pr118713-8.c: Likewise.
* gcc.target/i386/pr118713-9-x32.c: Likewise.
* gcc.target/i386/pr118713-9.c: Likewise.
* gcc.target/i386/pr118713-10-x32.c: Likewise.
* gcc.target/i386/pr118713-10.c: Likewise.
* gcc.target/i386/pr118713-11-x32.c: Likewise.
* gcc.target/i386/pr118713-11.c: Likewise.
* gcc.target/i386/pr118713-12-x32.c: Likewise.
* gcc.target/i386/pr118713-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 | 98 +++++++++++++------
.../gcc.target/i386/pr118713-1-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-1.c | 14 +++
.../gcc.target/i386/pr118713-10-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-10.c | 15 +++
.../gcc.target/i386/pr118713-11-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-11.c | 14 +++
.../gcc.target/i386/pr118713-12-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-12.c | 14 +++
.../gcc.target/i386/pr118713-2-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-2.c | 15 +++
.../gcc.target/i386/pr118713-3-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-3.c | 14 +++
.../gcc.target/i386/pr118713-4-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-4.c | 14 +++
.../gcc.target/i386/pr118713-5-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-5.c | 13 +++
.../gcc.target/i386/pr118713-6-x32.c | 15 +++
gcc/testsuite/gcc.target/i386/pr118713-6.c | 14 +++
.../gcc.target/i386/pr118713-7-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-7.c | 13 +++
.../gcc.target/i386/pr118713-8-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-8.c | 13 +++
.../gcc.target/i386/pr118713-9-x32.c | 8 ++
gcc/testsuite/gcc.target/i386/pr118713-9.c | 14 +++
26 files changed, 353 insertions(+), 35 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-1-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-10-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-10.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-11-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-11.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-12-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-12.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-2-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-3-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-4-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-4.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-5-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-5.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-6-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-6.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-7-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-7.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-8-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-8.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-9-x32.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr118713-9.c
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 117f6f6f7eb..1d1614d2ccc 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 (TARGET_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
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..0c9721bdc7a 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 "!TARGET_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 && !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 && !TARGET_INDIRECT_BRANCH_REGISTER
&& !TARGET_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 "!TARGET_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 && !TARGET_INDIRECT_BRANCH_REGISTER
+ && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[0]);"
[(set_attr "type" "call")])
@@ -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 "!TARGET_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 "!TARGET_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 && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[0]);"
[(set_attr "type" "call")])
@@ -20325,11 +20346,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 "!TARGET_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 +20364,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 && !TARGET_INDIRECT_BRANCH_REGISTER"
{
rtx fnaddr = gen_const_mem (DImode, XEXP (operands[1], 0));
return ix86_output_call_insn (insn, fnaddr);
@@ -20355,7 +20381,7 @@ (define_insn "*sibcall_value_GOT_32"
(match_operand:SI 2 "GOT32_symbol_operand"))))
(match_operand 3)))]
"!TARGET_MACHO
- && !TARGET_64BIT
+ && !TARGET_64BIT && !TARGET_INDIRECT_BRANCH_REGISTER
&& !TARGET_INDIRECT_BRANCH_REGISTER
&& SIBLING_CALL_P (insn)"
{
@@ -20367,18 +20393,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 "!TARGET_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 && !TARGET_INDIRECT_BRANCH_REGISTER
+ && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[1]);"
[(set_attr "type" "callv")])
@@ -20432,25 +20464,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 "!TARGET_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 "!TARGET_INDIRECT_BRANCH_REGISTER")
+ (const_string "*")))])
(define_insn "*sibcall_value_pop_memory"
[(set (match_operand 0)
@@ -20460,7 +20502,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 && !TARGET_INDIRECT_BRANCH_REGISTER"
"* return ix86_output_call_insn (insn, operands[1]);"
[(set_attr "type" "callv")])
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-1-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-1-x32.c
new file mode 100644
index 00000000000..c27ac93ae87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-1.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-1.c
b/gcc/testsuite/gcc.target/i386/pr118713-1.c
new file mode 100644
index 00000000000..56884f3d952
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-10-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-10-x32.c
new file mode 100644
index 00000000000..30d25ad6d0e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-10.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-10.c
b/gcc/testsuite/gcc.target/i386/pr118713-10.c
new file mode 100644
index 00000000000..a0e2ff3760b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-11-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-11-x32.c
new file mode 100644
index 00000000000..98afe50f42c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-11.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-11.c
b/gcc/testsuite/gcc.target/i386/pr118713-11.c
new file mode 100644
index 00000000000..deb0c0df3c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-12-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-12-x32.c
new file mode 100644
index 00000000000..534ddab2344
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-12.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-12.c
b/gcc/testsuite/gcc.target/i386/pr118713-12.c
new file mode 100644
index 00000000000..333b9c813e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-2-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-2-x32.c
new file mode 100644
index 00000000000..4af932e68ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-2.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-2.c
b/gcc/testsuite/gcc.target/i386/pr118713-2.c
new file mode 100644
index 00000000000..807724e0310
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-3-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-3-x32.c
new file mode 100644
index 00000000000..90a0e66a10c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-3.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-3.c
b/gcc/testsuite/gcc.target/i386/pr118713-3.c
new file mode 100644
index 00000000000..1cd3fcbdf66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-4-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-4-x32.c
new file mode 100644
index 00000000000..7f02f6003ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-4.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-4.c
b/gcc/testsuite/gcc.target/i386/pr118713-4.c
new file mode 100644
index 00000000000..86d13b73bfc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-5-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-5-x32.c
new file mode 100644
index 00000000000..dfaf247ce06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-5.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-5.c
b/gcc/testsuite/gcc.target/i386/pr118713-5.c
new file mode 100644
index 00000000000..7b1f8c17c2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-6-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-6-x32.c
new file mode 100644
index 00000000000..f728b15db77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-6.c
b/gcc/testsuite/gcc.target/i386/pr118713-6.c
new file mode 100644
index 00000000000..a4f3b68f3e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-7-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-7-x32.c
new file mode 100644
index 00000000000..443930cc6f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-7.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-7.c
b/gcc/testsuite/gcc.target/i386/pr118713-7.c
new file mode 100644
index 00000000000..fdc0db951bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-8-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-8-x32.c
new file mode 100644
index 00000000000..5dd873502d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-8.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*\\\$bar, " } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-8.c
b/gcc/testsuite/gcc.target/i386/pr118713-8.c
new file mode 100644
index 00000000000..03d5f008e0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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/pr118713-9-x32.c
b/gcc/testsuite/gcc.target/i386/pr118713-9-x32.c
new file mode 100644
index 00000000000..85819aa3380
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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 "pr118713-9.c"
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\\*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr118713-9.c
b/gcc/testsuite/gcc.target/i386/pr118713-9.c
new file mode 100644
index 00000000000..365f65fb194
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-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