On Sat, Feb 1, 2025 at 5:52 PM Uros Bizjak <ubiz...@gmail.com> wrote:
>
> On Sat, Feb 1, 2025 at 9:51 AM H.J. Lu <hjl.to...@gmail.com> wrote:
> >
> > If TARGET_INDIRECT_BRANCH_REGISTER is true, indirect call and jump should
> > use register, not memory.  Update Bs, Bw and Bz constraints to disable
> > indirect call over memmory if TARGET_INDIRECT_BRANCH_REGISTER true, change
> > x32 call over GOT slot to call over register and also disable sibcall
> > over memory.
> >
> > gcc/
> >
> >         PR target/118713
> >         * config/i386/constraints.md (Bs): Always disable if
> >         TARGET_INDIRECT_BRANCH_REGISTER is true.
> >         (Bw): Likewise.
> >         * config/i386/i386-expand.cc (ix86_expand_call): Force indirect
> >         call via register for GOT slot call if
> >         TARGET_INDIRECT_BRANCH_REGISTER is true.
> >         * config/i386/i386-protos.h (ix86_nopic_noplt_attribute_p): New.
> >         * config/i386/i386.cc (ix86_nopic_noplt_attribute_p): Make it
> >         global.
> >         * config/i386/i386.md (*call_got_x32): Disable indirect call via
> >         memory for TARGET_INDIRECT_BRANCH_REGISTER.
> >         (*call_value_got_x32): Likewise.
> >         (*sibcall_value_pop_memory): Likewise.
> >         * config/i386/predicates.md (constant_call_address_operand):
> >         Return false if both TARGET_INDIRECT_BRANCH_REGISTER and
> >         ix86_nopic_noplt_attribute_p are true.
>
> LGTM, with some code reshuffling, proposed below. I didn't do a
> thorough review on how T_I_B_R is handled, you are the expert in the
> area of symbol handling.
>
> Thanks,
> Uros.
>
> >
> > 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.
> >
> > Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
> > ---
> >  gcc/config/i386/constraints.md                | 24 +++++++++----------
> >  gcc/config/i386/i386-expand.cc                | 22 +++++++++++------
> >  gcc/config/i386/i386-protos.h                 |  1 +
> >  gcc/config/i386/i386.cc                       |  2 +-
> >  gcc/config/i386/i386.md                       |  6 ++---
> >  gcc/config/i386/predicates.md                 |  4 +++-
> >  .../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          |  7 ++++++
> >  gcc/testsuite/gcc.target/i386/pr118713-5.c    | 12 ++++++++++
> >  .../gcc.target/i386/pr118713-6-x32.c          |  7 ++++++
> >  gcc/testsuite/gcc.target/i386/pr118713-6.c    | 13 ++++++++++
> >  .../gcc.target/i386/pr118713-7-x32.c          |  7 ++++++
> >  gcc/testsuite/gcc.target/i386/pr118713-7.c    | 12 ++++++++++
> >  .../gcc.target/i386/pr118713-8-x32.c          |  7 ++++++
> >  gcc/testsuite/gcc.target/i386/pr118713-8.c    | 12 ++++++++++
> >  .../gcc.target/i386/pr118713-9-x32.c          |  8 +++++++
> >  gcc/testsuite/gcc.target/i386/pr118713-9.c    | 14 +++++++++++
> >  30 files changed, 290 insertions(+), 24 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/constraints.md b/gcc/config/i386/constraints.md
> > index 9dd280568bd..d3d6e9e66f4 100644
> > --- a/gcc/config/i386/constraints.md
> > +++ b/gcc/config/i386/constraints.md
> > @@ -203,21 +203,21 @@ (define_special_memory_constraint "Br"
> >
> >  (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"))))
> > +  (and (match_test "!TARGET_INDIRECT_BRANCH_REGISTER")
> > +       (ior (and (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")))))
>
> While here, the above can use if_then_else RTX (and not RTX for
> consistency), like:
>
>   (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
>        (if_then_else (match_test "TARGET_X32")
>             (and (match_test "Pmode == DImode")
>                     (match_operand 0 "GOT_memory_operand"))
>             (match_operand 0 "sibcall_memory_operand")))

Will fix it.

> >  (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"))))
> > +  (and (match_test "!TARGET_INDIRECT_BRANCH_REGISTER")
> > +       (ior (and (match_test "!TARGET_X32")
> > +                 (match_operand 0 "memory_operand"))
> > +            (and (match_test "TARGET_X32")
> > +                 (match_test "Pmode == DImode")
> > +                 (match_operand 0 "GOT_memory_operand")))))
>
> Also here.

Will fix it.

>
> >  (define_constraint "Bz"
> >    "@internal Constant call address operand."
> > diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
> > index 117f6f6f7eb..7a2df43e7cd 100644
> > --- a/gcc/config/i386/i386-expand.cc
> > +++ b/gcc/config/i386/i386-expand.cc
> > @@ -10225,13 +10225,21 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx 
> > callarg1,
> >      fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 
> > 0)));
> >    /* 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
>
> Please keep "else if" here. construct_plt_address always returns REG,
> which is universally accepted as a call operand.
>
> > +      && MEM_P (fnaddr)
> > +      && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
> > +      && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode))
>
> The purpose of this condition is to bypass the "else if" below. If you
> write it as:
>
> else if (TARGET_X32
>       && MEM_P (fnaddr)
>       && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
>       && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode)
>       && !TARGET_INDIRECT_BRANCH_REGISTER)
>         ;
> else if (sibcall ...
>
> Then bypass won't be active, and "else if (sibcall ...)" will trigger,
> copying the address to the register in the exact same way as your
> newly added code.

Will fix it.

>
> > +       {
> > +         fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
> > +         fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode,
> > +                                                         fnaddr));
> > +       }
> > +    }
> > +  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-protos.h b/gcc/config/i386/i386-protos.h
> > index f122fd8a0a3..bea3fd4b2e2 100644
> > --- a/gcc/config/i386/i386-protos.h
> > +++ b/gcc/config/i386/i386-protos.h
> > @@ -371,6 +371,7 @@ extern int asm_preferred_eh_data_format (int, int);
> >  extern enum attr_cpu ix86_schedule;
> >  #endif
> >
> > +extern bool ix86_nopic_noplt_attribute_p (rtx call_op);
> >  extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
> >  extern const char * ix86_output_indirect_jmp (rtx call_op);
> >  extern const char * ix86_output_function_return (bool long_p);
> > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> > index 11770aa8a50..f89201684a8 100644
> > --- a/gcc/config/i386/i386.cc
> > +++ b/gcc/config/i386/i386.cc
> > @@ -16724,7 +16724,7 @@ ix86_ifunc_ref_local_ok (void)
> >     This is currently used only with 64-bit or 32-bit GOT32X ELF targets
> >     to call the function marked "noplt" indirectly.  */
> >
> > -static bool
> > +bool
> >  ix86_nopic_noplt_attribute_p (rtx call_op)
> >  {
> >    if (flag_pic || ix86_cmodel == CM_LARGE
> > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> > index 52c02b6351a..d6ae3ee378a 100644
> > --- a/gcc/config/i386/i386.md
> > +++ b/gcc/config/i386/i386.md
> > @@ -20133,7 +20133,7 @@ (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);
> > @@ -20338,7 +20338,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);
> > @@ -20460,7 +20460,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/config/i386/predicates.md b/gcc/config/i386/predicates.md
> > index e733a474f9e..9a9101ed374 100644
> > --- a/gcc/config/i386/predicates.md
> > +++ b/gcc/config/i386/predicates.md
> > @@ -670,7 +670,9 @@ (define_predicate "constant_call_address_operand"
> >    (match_code "symbol_ref")
> >  {
> >    if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC
> > -      || flag_force_indirect_call)
> > +      || flag_force_indirect_call
> > +      || (TARGET_INDIRECT_BRANCH_REGISTER
> > +          && ix86_nopic_noplt_attribute_p (op)))
> >      return false;
> >    if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
> >      return false;

This is the patch I am testing.

Thanks.


-- 
H.J.
From 6becc8551c9af8052dfdcc3368c943572fdd6b62 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Fri, 31 Jan 2025 12:29:04 +0800
Subject: [PATCH v4] x86: Handle TARGET_INDIRECT_BRANCH_REGISTER for -fno-plt

If TARGET_INDIRECT_BRANCH_REGISTER is true, indirect call and jump should
use register, not memory.  Update Bs, Bw and Bz constraints to disable
indirect call over memmory if TARGET_INDIRECT_BRANCH_REGISTER true, change
x32 call over GOT slot to call over register and also disable sibcall
over memory.

gcc/

	PR target/118713
	* config/i386/constraints.md (Bs): Always disable if
	TARGET_INDIRECT_BRANCH_REGISTER is true.
	(Bw): Likewise.
	* config/i386/i386-expand.cc (ix86_expand_call): Force indirect
	call via register for GOT slot call if
	TARGET_INDIRECT_BRANCH_REGISTER is true.
	* config/i386/i386-protos.h (ix86_nopic_noplt_attribute_p): New.
	* config/i386/i386.cc (ix86_nopic_noplt_attribute_p): Make it
	global.
	* config/i386/i386.md (*call_got_x32): Disable indirect call via
	memory for TARGET_INDIRECT_BRANCH_REGISTER.
	(*call_value_got_x32): Likewise.
	(*sibcall_value_pop_memory): Likewise.
	* config/i386/predicates.md (constant_call_address_operand):
	Return false if both TARGET_INDIRECT_BRANCH_REGISTER and
	ix86_nopic_noplt_attribute_p are true.

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.

Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
---
 gcc/config/i386/constraints.md                | 22 +++++++++----------
 gcc/config/i386/i386-expand.cc                | 16 ++++++++------
 gcc/config/i386/i386-protos.h                 |  1 +
 gcc/config/i386/i386.cc                       |  2 +-
 gcc/config/i386/i386.md                       |  6 ++---
 gcc/config/i386/predicates.md                 |  4 +++-
 .../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          |  7 ++++++
 gcc/testsuite/gcc.target/i386/pr118713-5.c    | 12 ++++++++++
 .../gcc.target/i386/pr118713-6-x32.c          |  7 ++++++
 gcc/testsuite/gcc.target/i386/pr118713-6.c    | 13 +++++++++++
 .../gcc.target/i386/pr118713-7-x32.c          |  7 ++++++
 gcc/testsuite/gcc.target/i386/pr118713-7.c    | 12 ++++++++++
 .../gcc.target/i386/pr118713-8-x32.c          |  7 ++++++
 gcc/testsuite/gcc.target/i386/pr118713-8.c    | 12 ++++++++++
 .../gcc.target/i386/pr118713-9-x32.c          |  8 +++++++
 gcc/testsuite/gcc.target/i386/pr118713-9.c    | 14 ++++++++++++
 30 files changed, 282 insertions(+), 24 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/constraints.md b/gcc/config/i386/constraints.md
index 9dd280568bd..38877a7e61b 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -203,21 +203,19 @@ (define_special_memory_constraint "Br"
 
 (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"))))
+  (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+       (if_then_else (match_test "TARGET_X32")
+         (and (match_test "Pmode == DImode")
+              (match_operand 0 "GOT_memory_operand"))
+         (match_operand 0 "sibcall_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"))))
+  (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER"))
+       (if_then_else (match_test "TARGET_X32")
+         (and (match_test "Pmode == DImode")
+              (match_operand 0 "GOT_memory_operand"))
+         (match_operand 0 "memory_operand"))))
 
 (define_constraint "Bz"
   "@internal Constant call address operand."
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 117f6f6f7eb..a43b0f0e8f0 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -10225,13 +10225,15 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
     fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
   /* 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)
+      && !TARGET_INDIRECT_BRANCH_REGISTER)
+    ;
+  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-protos.h b/gcc/config/i386/i386-protos.h
index f122fd8a0a3..bea3fd4b2e2 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -371,6 +371,7 @@ extern int asm_preferred_eh_data_format (int, int);
 extern enum attr_cpu ix86_schedule;
 #endif
 
+extern bool ix86_nopic_noplt_attribute_p (rtx call_op);
 extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
 extern const char * ix86_output_indirect_jmp (rtx call_op);
 extern const char * ix86_output_function_return (bool long_p);
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 11770aa8a50..f89201684a8 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -16724,7 +16724,7 @@ ix86_ifunc_ref_local_ok (void)
    This is currently used only with 64-bit or 32-bit GOT32X ELF targets
    to call the function marked "noplt" indirectly.  */
 
-static bool
+bool
 ix86_nopic_noplt_attribute_p (rtx call_op)
 {
   if (flag_pic || ix86_cmodel == CM_LARGE
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 52c02b6351a..d6ae3ee378a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -20133,7 +20133,7 @@ (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);
@@ -20338,7 +20338,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);
@@ -20460,7 +20460,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/config/i386/predicates.md b/gcc/config/i386/predicates.md
index e733a474f9e..9a9101ed374 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -670,7 +670,9 @@ (define_predicate "constant_call_address_operand"
   (match_code "symbol_ref")
 {
   if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC
-      || flag_force_indirect_call)
+      || flag_force_indirect_call
+      || (TARGET_INDIRECT_BRANCH_REGISTER
+          && ix86_nopic_noplt_attribute_p (op)))
     return false;
   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
     return false;
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..4642ace9d6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-5-x32.c
@@ -0,0 +1,7 @@
+/* { 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 "jmp\[ \t\]*bar" } } */
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..0f44ab23c9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-5.c
@@ -0,0 +1,12 @@
+/* { 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 "jmp\[ \t\]*bar" } } */
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..e7a2f35d569
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-6-x32.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -mx32 -fno-pic -fno-plt -mindirect-branch-register" } */
+
+#include "pr118713-6.c"
+
+/* { dg-final { scan-assembler "call\[ \t\]*bar" } } */
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..befe0b07e06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-6.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")));
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*bar" } } */
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..35e9de5c187
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-7-x32.c
@@ -0,0 +1,7 @@
+/* { 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 "jmp\[ \t\]*bar" } } */
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..ba405be4272
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-7.c
@@ -0,0 +1,12 @@
+/* { 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 "jmp\[ \t\]*bar" } } */
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..9aebe6aef64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-8-x32.c
@@ -0,0 +1,7 @@
+/* { 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 "call\[ \t\]*bar" } } */
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..046f107a6f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118713-8.c
@@ -0,0 +1,12 @@
+/* { 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 "call\[ \t\]*bar" } } */
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

Reply via email to