For x86 targets, when -fno-plt is used, external functions are called
via GOT slot, in 64-bit mode:

        [bnd] call/jmp *foo@GOTPCREL(%rip)

and in 32-bit mode:

        [bnd] call/jmp *foo@GOT[(%reg)]

With -mindirect-branch=, they are converted to, in 64-bit mode:

        pushq          foo@GOTPCREL(%rip)
        [bnd] jmp      __x86_indirect_thunk[_bnd]

and in 32-bit mode:

        pushl          foo@GOT[(%reg)]
        [bnd] jmp      __x86_indirect_thunk[_bnd]

which were incompatible with CFI.  In 64-bit mode, since R11 is a scratch
register, we generate:

        movq           foo@GOTPCREL(%rip), %r11
        [bnd] call/jmp __x86_indirect_thunk_[bnd_]r11

instead.  We do it in ix86_output_indirect_branch so that we can use
the newly proposed R_X86_64_THUNK_GOTPCRELX relocation:

https://groups.google.com/forum/#!topic/x86-64-abi/eED5lzn3_Mg

        movq           foo@OTPCREL_THUNK(%rip), %r11
        [bnd] call/jmp __x86_indirect_thunk_[bnd_]r11

to load GOT slot into R11.  If foo is defined locally, linker can can
convert

        movq           foo@GOTPCREL_THUNK(%rip), %reg
        call/jmp       __x86_indirect_thunk_reg

to

        call/jmp       foo
        nop            0L(%rax)

In 32-bit mode, since all caller-saved registers, EAX, EDX and ECX, may
used to function parameters, there is no scratch register available.  For
-fno-plt -fno-pic -mindirect-branch=, we expand external function call
to:

        movl           foo@GOT, %reg
        [bnd] call/jmp *%reg

so that it can be converted to

        movl           foo@GOT, %reg
        [bnd] call/jmp __x86_indirect_thunk_[bnd_]reg

in ix86_output_indirect_branch.  Since this is performed during RTL
expansion, other instructions may be inserted between movl and call/jmp.
Linker optimization isn't always possible.

Tested on i686 and x86-64.  OK for trunk?


H.J.
---
gcc/

        PR target/83970
        * config/i386/constraints.md (Bs): Allow GOT_memory_operand
        for TARGET_LP64 with indirect branch conversion.
        (Bw): Likewise.
        * config/i386/i386.c (ix86_expand_call): Handle -fno-plt with
        -mindirect-branch=.
        (ix86_nopic_noplt_attribute_p): Likewise.
        (ix86_output_indirect_branch): In 64-bit mode, convert function
        call via GOT with R11 as a scratch register using
        __x86_indirect_thunk_r11.
        (ix86_output_call_insn): In 64-bit mode, set xasm to NULL when
        calling ix86_output_indirect_branch with function call via GOT.
        * config/i386/i386.md (*call_got_thunk): New call pattern for
        TARGET_LP64 with indirect branch conversion.
        (*call_value_got_thunk): Likewise.

gcc/testsuite/

        PR target/83970
        * gcc.target/i386/indirect-thunk-5.c: Updated.
        * gcc.target/i386/indirect-thunk-6.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-5.c: Likewise.
        * gcc.target/i386/indirect-thunk-extern-6.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-13.c: New test.
        * gcc.target/i386/indirect-thunk-14.c: Likewise.
        * gcc.target/i386/indirect-thunk-bnd-5.c: Likewise.
        * gcc.target/i386/indirect-thunk-bnd-6.c: Likewise.
        * gcc.target/i386/indirect-thunk-extern-11.c: Likewise.
        * gcc.target/i386/indirect-thunk-extern-12.c: Likewise.
        * gcc.target/i386/indirect-thunk-inline-8.c: Likewise.
        * gcc.target/i386/indirect-thunk-inline-9.c: Likewise.
---
 gcc/config/i386/constraints.md                     | 14 +++-
 gcc/config/i386/i386.c                             | 90 +++++++++++++++++++---
 gcc/config/i386/i386.md                            | 36 +++++++++
 gcc/testsuite/gcc.target/i386/indirect-thunk-13.c  | 19 +++++
 gcc/testsuite/gcc.target/i386/indirect-thunk-14.c  | 20 +++++
 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c   |  6 +-
 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c   | 12 +--
 .../gcc.target/i386/indirect-thunk-bnd-3.c         |  2 +-
 .../gcc.target/i386/indirect-thunk-bnd-4.c         |  2 +-
 .../gcc.target/i386/indirect-thunk-bnd-5.c         | 21 +++++
 .../gcc.target/i386/indirect-thunk-bnd-6.c         | 22 ++++++
 .../gcc.target/i386/indirect-thunk-extern-11.c     | 18 +++++
 .../gcc.target/i386/indirect-thunk-extern-12.c     | 19 +++++
 .../gcc.target/i386/indirect-thunk-extern-5.c      |  6 +-
 .../gcc.target/i386/indirect-thunk-extern-6.c      |  8 +-
 .../gcc.target/i386/indirect-thunk-inline-5.c      |  3 +-
 .../gcc.target/i386/indirect-thunk-inline-6.c      |  3 +-
 .../gcc.target/i386/indirect-thunk-inline-8.c      | 18 +++++
 .../gcc.target/i386/indirect-thunk-inline-9.c      | 19 +++++
 19 files changed, 300 insertions(+), 38 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-13.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-14.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-11.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-12.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-8.c
 create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-9.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index d026968c4c9..34d255aea59 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -228,7 +228,12 @@
   (ior (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
            (not (match_test "TARGET_X32"))
            (match_operand 0 "sibcall_memory_operand"))
-       (and (match_test "TARGET_X32 && Pmode == DImode")
+       (and (ior (and (match_test "TARGET_LP64")
+                     (match_test "cfun->machine->func_type
+                                  == TYPE_NORMAL")
+                     (match_test "cfun->machine->indirect_branch_type
+                                  != indirect_branch_keep"))
+                (match_test "TARGET_X32 && Pmode == DImode"))
            (match_operand 0 "GOT_memory_operand"))))
 
 (define_constraint "Bw"
@@ -236,7 +241,12 @@
   (ior (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
            (not (match_test "TARGET_X32"))
            (match_operand 0 "memory_operand"))
-       (and (match_test "TARGET_X32 && Pmode == DImode")
+       (and (ior (and (match_test "TARGET_LP64")
+                     (match_test "cfun->machine->func_type
+                                  == TYPE_NORMAL")
+                     (match_test "cfun->machine->indirect_branch_type
+                                  != indirect_branch_keep"))
+                (match_test "TARGET_X32 && Pmode == DImode"))
            (match_operand 0 "GOT_memory_operand"))))
 
 (define_constraint "Bz"
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9041485bd61..a8a50f7687f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -28526,7 +28526,14 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
                                    pic_offset_table_rtx);
                }
            }
-         else if (!TARGET_PECOFF && !TARGET_MACHO)
+         /* In 64-bit mode, -mindirect-branch= is treated as -fno-pic
+            and ix86_output_indirect_branch will convert call via PLT
+            to indirect branch via GOT slot.  */
+         else if (!TARGET_PECOFF
+                  && !TARGET_MACHO
+                  && (!TARGET_64BIT
+                      || (cfun->machine->indirect_branch_type
+                          == indirect_branch_keep)))
            {
              if (TARGET_64BIT)
                {
@@ -28553,6 +28560,30 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
              fnaddr = gen_rtx_MEM (QImode, fnaddr);
            }
        }
+      else if (!TARGET_64BIT
+              && HAVE_AS_IX86_GOT32X
+              && !TARGET_PECOFF
+              && !TARGET_MACHO
+              && (cfun->machine->indirect_branch_type
+                  != indirect_branch_keep)
+              && !flag_pic
+              && GET_CODE (addr) == SYMBOL_REF
+              && SYMBOL_REF_FUNCTION_P (addr)
+              && !SYMBOL_REF_LOCAL_P (addr)
+              && (!flag_plt
+                  || (SYMBOL_REF_DECL (addr) != NULL_TREE
+                      && lookup_attribute ("noplt",
+                                           DECL_ATTRIBUTES (SYMBOL_REF_DECL 
(addr))))))
+       {
+         /* In 32-bit mode, with -fno-pic -mindirect-branch=, we load
+            function's GOT slot into a register and call the external
+            function via the register.  */
+         fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+                                  UNSPEC_GOT);
+         fnaddr = gen_rtx_CONST (Pmode, fnaddr);
+         fnaddr = gen_const_mem (Pmode, fnaddr);
+         fnaddr = gen_rtx_MEM (QImode, fnaddr);
+       }
     }
 
   /* Skip setting up RAX register for -mskip-rax-setup when there are no
@@ -28699,7 +28730,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
 static bool
 ix86_nopic_noplt_attribute_p (rtx call_op)
 {
-  if (flag_pic || ix86_cmodel == CM_LARGE
+  if (ix86_cmodel == CM_LARGE
       || !(TARGET_64BIT || HAVE_AS_IX86_GOT32X)
       || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
       || SYMBOL_REF_LOCAL_P (call_op))
@@ -28707,10 +28738,16 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
 
   tree symbol_decl = SYMBOL_REF_DECL (call_op);
 
+  /* In 64-bit mode, -mindirect-branch= is treated as -fno-pic and
+     ix86_output_indirect_branch will convert call via PLT to indirect
+     branch via GOT slot.  */
   if (!flag_plt
       || (symbol_decl != NULL_TREE
           && lookup_attribute ("noplt", DECL_ATTRIBUTES (symbol_decl))))
-    return true;
+    return (!flag_pic
+           || (TARGET_64BIT
+               && (cfun->machine->indirect_branch_type
+                   != indirect_branch_keep)));
 
   return false;
 }
@@ -28968,6 +29005,43 @@ static void
 ix86_output_indirect_branch (rtx call_op, const char *xasm,
                             bool sibcall_p)
 {
+  /* In 64-bit mode, convert function call via GOT:
+
+       [bnd] call/jmp *foo@GOTPCREL(%rip)
+
+     to
+
+       movq           foo@GOTPCREL(%rip), %r11
+       [bnd] call/jmp __x86_indirect_thunk_[bnd_]r11
+
+     with R11 as a scratch register.  */
+  if (TARGET_64BIT)
+    {
+      if (MEM_P (call_op)
+         && GET_CODE (XEXP (call_op, 0)) == CONST
+         && GET_CODE (XEXP (XEXP (call_op, 0), 0)) == UNSPEC
+         && XINT (XEXP (XEXP (call_op, 0), 0), 1) == UNSPEC_GOTPCREL)
+       {
+         rtx op = XVECEXP (XEXP (XEXP (call_op, 0), 0), 0, 0);
+         if (GET_CODE (op) != SYMBOL_REF)
+           gcc_unreachable ();
+         xasm = NULL;
+         call_op = op;
+       }
+
+      if (xasm == NULL)
+       {
+         rtx xops[2];
+         xops[0] = gen_rtx_REG (word_mode, R11_REG);
+         xops[1] = call_op;
+         char movq_buf[80];
+         snprintf (movq_buf, sizeof (movq_buf), "movq\t%s",
+                   "{%p1@GOTPCREL(%%rip), %0|%0, [QWORD PTR 
%p1@GOTPCREL[rip]]}");
+         output_asm_insn (movq_buf, xops);
+         call_op = xops[0];
+       }
+    }
+
   if (REG_P (call_op))
     ix86_output_indirect_branch_via_reg (call_op, sibcall_p);
   else
@@ -29126,7 +29200,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
     = (!TARGET_SEH
        && cfun->machine->indirect_branch_type != indirect_branch_keep);
   bool seh_nop_p = false;
-  const char *xasm;
+  const char *xasm = NULL;
 
   if (SIBLING_CALL_P (insn))
     {
@@ -29137,9 +29211,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
              direct_p = false;
              if (TARGET_64BIT)
                {
-                 if (output_indirect_p)
-                   xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR 
%p0@GOTPCREL[rip]]}";
-                 else
+                 if (!output_indirect_p)
                    xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR 
%p0@GOTPCREL[rip]]}";
                }
              else
@@ -29209,9 +29281,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
          direct_p = false;
          if (TARGET_64BIT)
            {
-             if (output_indirect_p)
-               xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
-             else
+             if (!output_indirect_p)
                xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR 
%p0@GOTPCREL[rip]]}";
            }
          else
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 85e4b07cd0f..cb39a98aeb1 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12575,6 +12575,23 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_thunk"
+  [(call (mem:QI (match_operand:DI 0 "GOT_memory_operand" "Bg"))
+        (match_operand 1))]
+  "TARGET_LP64
+   && cfun->machine->func_type == TYPE_NORMAL
+   && cfun->machine->indirect_branch_type != indirect_branch_keep"
+{
+  rtx fnaddr = gen_const_mem (DImode, XEXP (operands[0], 0));
+  return ix86_output_call_insn (insn, fnaddr);
+}
+  [(set (attr "type")
+     (if_then_else (match_test "(cfun->machine->indirect_branch_type
+                                != indirect_branch_keep)")
+       (const_string "multi")
+       (const_string "call")))])
+
 ;; This covers both call and sibcall since only GOT slot is allowed.
 (define_insn "*call_got_x32"
   [(call (mem:QI (zero_extend:DI
@@ -12778,6 +12795,25 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_thunk"
+  [(set (match_operand 0)
+       (call (mem:QI
+               (match_operand:DI 1 "GOT_memory_operand" "Bg"))
+             (match_operand 2)))]
+  "TARGET_LP64
+   && cfun->machine->func_type == TYPE_NORMAL
+   && cfun->machine->indirect_branch_type != indirect_branch_keep"
+{
+  rtx fnaddr = gen_const_mem (DImode, XEXP (operands[1], 0));
+  return ix86_output_call_insn (insn, fnaddr);
+}
+  [(set (attr "type")
+     (if_then_else (match_test "(cfun->machine->indirect_branch_type
+                                != indirect_branch_keep)")
+       (const_string "multi")
+       (const_string "callv")))])
+
 ;; This covers both call and sibcall since only GOT slot is allowed.
 (define_insn "*call_value_got_x32"
   [(set (match_operand 0)
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-13.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-13.c
new file mode 100644
index 00000000000..ed9c43f23ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-13.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_e" { target 
ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_r" { target { 
! ia32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-14.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-14.c
new file mode 100644
index 00000000000..2bd547486b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-14.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_e" { target 
ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_r" { target { 
! ia32 } } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
index fb26c005e80..95cbf62194d 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
@@ -9,10 +9,8 @@ foo (void)
   bar ();
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 
} } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { 
target { ! x32 } } } } */
+/* { dg-final { scan-assembler "mov(l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)" } } */
 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler {\tpause} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
index 8bc45ff68ce..7e8d9a48905 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
@@ -10,13 +10,9 @@ foo (void)
   return 0;
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 
} } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 { target x32 } } } 
*/
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 { target x32 } } } 
*/
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { 
target { ! x32 } } } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } 
} } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } 
} } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)" } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
 /* { dg-final { scan-assembler {\tpause} } } */
 /* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
index 42312f65588..b573040adc7 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
@@ -11,7 +11,7 @@ foo (void)
 }
 
 /* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_rax" { 
target lp64 } } } */
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_r" { 
target lp64 } } } */
 /* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_eax" 
{ target ia32 } } } */
 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
index 8850f2ffca4..db68eb5a157 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
@@ -12,7 +12,7 @@ foo (void)
 }
 
 /* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
-/* { dg-final { scan-assembler "bnd call\[ 
\t\]*__x86_indirect_thunk_bnd_(r|e)ax" } } */
+/* { dg-final { scan-assembler "bnd call\[ 
\t\]*__x86_indirect_thunk_bnd_(r|e)" } } */
 /* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 1 } } */
 /* { dg-final { scan-assembler "bnd ret" } } */
 /* { dg-final { scan-assembler {\tpause} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-5.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-5.c
new file mode 100644
index 00000000000..d0674ee4058
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+void
+foo (void)
+{
+  bar (buf);
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_e" { 
target ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target lp64 } } } 
*/
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_r" { 
target lp64 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-6.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-6.c
new file mode 100644
index 00000000000..7d7ba2388e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+int
+foo (void)
+{
+  bar (buf);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_e" { 
target ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target lp64 } } } 
*/
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_r" { 
target lp64 } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-11.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-11.c
new file mode 100644
index 00000000000..ce8b21959af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_e" { target 
ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_r" { target { 
! ia32 } } } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-12.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-12.c
new file mode 100644
index 00000000000..8d13e2017ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-12.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_e" { target 
ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_r" { target { 
! ia32 } } } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
index 53282390977..fd818fe15f2 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
@@ -9,10 +9,8 @@ foo (void)
   bar ();
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 
} } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { 
target { ! x32 } } } } */
+/* { dg-final { scan-assembler "mov(l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)" } } */
 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
 /* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
index 8ae43482d0c..b9a053d2fea 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
@@ -10,8 +10,8 @@ foo (void)
   return 0;
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 
} } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { 
target { ! x32 } } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
index 21cbfd39582..cb6e7fdb986 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
@@ -9,8 +9,7 @@ foo (void)
   bar ();
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
+/* { dg-final { scan-assembler "mov(l|q)\[ \t\]*bar@GOT" } } */
 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
 /* { dg-final { scan-assembler {\tpause} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
index d1300f18dc7..b61c855ffeb 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
@@ -10,8 +10,7 @@ foo (void)
   return 0;
 }
 
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } 
*/
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } 
} } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
 /* { dg-final { scan-assembler-times {\tpause} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-8.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-8.c
new file mode 100644
index 00000000000..5bc7eb7f359
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-8.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-9.c 
b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-9.c
new file mode 100644
index 00000000000..4e724fe7e3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-9.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep 
-fno-pic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "movq\[ \t\]*bar@GOTPCREL" { target { ! ia32 } 
} } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
-- 
2.14.3

Reply via email to