x86: Update 'P' operand modifier for -fno-plt

Message ID 20210311222249.432201-1-hjl.tools@gmail.com
State New
Headers show
Series
  • x86: Update 'P' operand modifier for -fno-plt
Related show

Commit Message

Hongyu Wang via Gcc-patches March 11, 2021, 10:22 p.m.
Update 'P' operand modifier for -fno-plt to support inline assembly
statements.  In 64-bit, we can always load function address with
@GOTPCREL.  In 32-bit, we load function address with @GOT only for
non-PIC since PIC register may not be available at call site.

gcc/

	PR target/99504
	* config/i386/i386.c (ix86_print_operand): Update 'P' handling
	for -fno-plt.

gcc/testsuite/

	PR target/99504
	* gcc.target/i386/pr99530-1.c: New test.
	* gcc.target/i386/pr99530-2.c: Likewise.
	* gcc.target/i386/pr99530-3.c: Likewise.
	* gcc.target/i386/pr99530-4.c: Likewise.
	* gcc.target/i386/pr99530-5.c: Likewise.
	* gcc.target/i386/pr99530-6.c: Likewise.
---
 gcc/config/i386/i386.c                    | 33 +++++++++++++++++++++--
 gcc/testsuite/gcc.target/i386/pr99530-1.c | 11 ++++++++
 gcc/testsuite/gcc.target/i386/pr99530-2.c | 11 ++++++++
 gcc/testsuite/gcc.target/i386/pr99530-3.c | 11 ++++++++
 gcc/testsuite/gcc.target/i386/pr99530-4.c | 11 ++++++++
 gcc/testsuite/gcc.target/i386/pr99530-5.c | 11 ++++++++
 gcc/testsuite/gcc.target/i386/pr99530-6.c | 11 ++++++++
 7 files changed, 97 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-6.c

-- 
2.29.2

Comments

Hongyu Wang via Gcc-patches March 12, 2021, 7:21 a.m. | #1
On Thu, Mar 11, 2021 at 11:22 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> Update 'P' operand modifier for -fno-plt to support inline assembly

> statements.  In 64-bit, we can always load function address with

> @GOTPCREL.  In 32-bit, we load function address with @GOT only for

> non-PIC since PIC register may not be available at call site.

>

> gcc/

>

>         PR target/99504

>         * config/i386/i386.c (ix86_print_operand): Update 'P' handling

>         for -fno-plt.

>

> gcc/testsuite/

>

>         PR target/99504

>         * gcc.target/i386/pr99530-1.c: New test.

>         * gcc.target/i386/pr99530-2.c: Likewise.

>         * gcc.target/i386/pr99530-3.c: Likewise.

>         * gcc.target/i386/pr99530-4.c: Likewise.

>         * gcc.target/i386/pr99530-5.c: Likewise.

>         * gcc.target/i386/pr99530-6.c: Likewise.

> ---

>  gcc/config/i386/i386.c                    | 33 +++++++++++++++++++++--

>  gcc/testsuite/gcc.target/i386/pr99530-1.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-2.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-3.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-4.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-5.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-6.c | 11 ++++++++

>  7 files changed, 97 insertions(+), 2 deletions(-)

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-1.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-2.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-3.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-4.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-5.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-6.c

>

> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c

> index 2603333f87b..8733fcecf65 100644

> --- a/gcc/config/i386/i386.c

> +++ b/gcc/config/i386/i386.c

> @@ -12701,7 +12701,8 @@ print_reg (rtx x, int code, FILE *file)

>     y -- print "st(0)" instead of "st" as a register.

>     d -- print duplicated register operand for AVX instruction.

>     D -- print condition for SSE cmp instruction.

> -   P -- if PIC, print an @PLT suffix.

> +   P -- if PIC, print an @PLT suffix.  For -fno-plt, load function

> +       address from GOT.

>     p -- print raw symbol name.

>     X -- don't print any sort of PIC '@' suffix for a symbol.

>     & -- print some in-use local-dynamic symbol name.

> @@ -13445,7 +13446,35 @@ ix86_print_operand (FILE *file, rtx x, int code)

>           x = const0_rtx;

>         }

>

> -      if (code != 'P' && code != 'p')

> +      if (code == 'P')

> +       {

> +         if (current_output_insn == NULL_RTX

> +             && (TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))

> +             && !TARGET_PECOFF

> +             && !TARGET_MACHO

> +             && ix86_cmodel != CM_LARGE

> +             && ix86_cmodel != CM_LARGE_PIC

> +             && GET_CODE (x) == SYMBOL_REF

> +             && SYMBOL_REF_FUNCTION_P (x)

> +             && (!flag_plt

> +                 || (SYMBOL_REF_DECL (x)

> +                     && lookup_attribute ("noplt",

> +                                          DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))

> +             && !SYMBOL_REF_LOCAL_P (x))

> +           {

> +             /* For inline assembly statement, load function address

> +                from GOT with 'P' operand modifier to avoid PLT.

> +                NB: This works only with call or jmp.  */

> +             const char *xasm;

> +             if (TARGET_64BIT)

> +               xasm = "{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";

> +             else

> +               xasm = "{*%p0@GOT|[DWORD PTR %p0@GOT]}";

> +             output_asm_insn (xasm, &x);

> +             return;


This should be handled in output_pic_addr_const.

Uros.

> +           }

> +       }

> +      else if (code != 'p')

>         {

>           if (CONST_INT_P (x))

>             {

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-1.c b/gcc/testsuite/gcc.target/i386/pr99530-1.c

> new file mode 100644

> index 00000000000..080d7cc9399

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-1.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-require-effective-target lp64 } */

> +/* { dg-options "-O2 -fpic -mcmodel=large -fno-plt" } */

> +/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-2.c b/gcc/testsuite/gcc.target/i386/pr99530-2.c

> new file mode 100644

> index 00000000000..9808957d624

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-2.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-require-effective-target lp64 } */

> +/* { dg-options "-O2 -fno-pic -mcmodel=large -fno-plt" } */

> +/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-3.c b/gcc/testsuite/gcc.target/i386/pr99530-3.c

> new file mode 100644

> index 00000000000..22fe81b25f2

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-3.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fno-pic -fno-plt" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-4.c b/gcc/testsuite/gcc.target/i386/pr99530-4.c

> new file mode 100644

> index 00000000000..aba0b5d7892

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-4.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fpic -fno-plt" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-5.c b/gcc/testsuite/gcc.target/i386/pr99530-5.c

> new file mode 100644

> index 00000000000..02c5799d273

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-5.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fno-pic" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */

> +

> +extern void foo (void) __attribute__ ((noplt));

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-6.c b/gcc/testsuite/gcc.target/i386/pr99530-6.c

> new file mode 100644

> index 00000000000..0dfdd3752f7

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-6.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fpic" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */

> +

> +extern void foo (void) __attribute__ ((noplt));

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> --

> 2.29.2

>
Hongyu Wang via Gcc-patches March 12, 2021, 7:27 a.m. | #2
On Thu, Mar 11, 2021 at 11:22 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> Update 'P' operand modifier for -fno-plt to support inline assembly

> statements.  In 64-bit, we can always load function address with

> @GOTPCREL.  In 32-bit, we load function address with @GOT only for

> non-PIC since PIC register may not be available at call site.

>

> gcc/

>

>         PR target/99504

>         * config/i386/i386.c (ix86_print_operand): Update 'P' handling

>         for -fno-plt.

>

> gcc/testsuite/

>

>         PR target/99504

>         * gcc.target/i386/pr99530-1.c: New test.

>         * gcc.target/i386/pr99530-2.c: Likewise.

>         * gcc.target/i386/pr99530-3.c: Likewise.

>         * gcc.target/i386/pr99530-4.c: Likewise.

>         * gcc.target/i386/pr99530-5.c: Likewise.

>         * gcc.target/i386/pr99530-6.c: Likewise.

> ---

>  gcc/config/i386/i386.c                    | 33 +++++++++++++++++++++--

>  gcc/testsuite/gcc.target/i386/pr99530-1.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-2.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-3.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-4.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-5.c | 11 ++++++++

>  gcc/testsuite/gcc.target/i386/pr99530-6.c | 11 ++++++++

>  7 files changed, 97 insertions(+), 2 deletions(-)

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-1.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-2.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-3.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-4.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-5.c

>  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-6.c

>

> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c

> index 2603333f87b..8733fcecf65 100644

> --- a/gcc/config/i386/i386.c

> +++ b/gcc/config/i386/i386.c

> @@ -12701,7 +12701,8 @@ print_reg (rtx x, int code, FILE *file)

>     y -- print "st(0)" instead of "st" as a register.

>     d -- print duplicated register operand for AVX instruction.

>     D -- print condition for SSE cmp instruction.

> -   P -- if PIC, print an @PLT suffix.

> +   P -- if PIC, print an @PLT suffix.  For -fno-plt, load function

> +       address from GOT.

>     p -- print raw symbol name.

>     X -- don't print any sort of PIC '@' suffix for a symbol.

>     & -- print some in-use local-dynamic symbol name.

> @@ -13445,7 +13446,35 @@ ix86_print_operand (FILE *file, rtx x, int code)

>           x = const0_rtx;

>         }

>

> -      if (code != 'P' && code != 'p')

> +      if (code == 'P')

> +       {

> +         if (current_output_insn == NULL_RTX

> +             && (TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))

> +             && !TARGET_PECOFF

> +             && !TARGET_MACHO

> +             && ix86_cmodel != CM_LARGE

> +             && ix86_cmodel != CM_LARGE_PIC

> +             && GET_CODE (x) == SYMBOL_REF

> +             && SYMBOL_REF_FUNCTION_P (x)

> +             && (!flag_plt

> +                 || (SYMBOL_REF_DECL (x)

> +                     && lookup_attribute ("noplt",

> +                                          DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))

> +             && !SYMBOL_REF_LOCAL_P (x))


You can use ix86_force_load_from_GOT_p instead.

Uros.

> +           {

> +             /* For inline assembly statement, load function address

> +                from GOT with 'P' operand modifier to avoid PLT.

> +                NB: This works only with call or jmp.  */

> +             const char *xasm;

> +             if (TARGET_64BIT)

> +               xasm = "{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";

> +             else

> +               xasm = "{*%p0@GOT|[DWORD PTR %p0@GOT]}";

> +             output_asm_insn (xasm, &x);

> +             return;

> +           }

> +       }

> +      else if (code != 'p')

>         {

>           if (CONST_INT_P (x))

>             {

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-1.c b/gcc/testsuite/gcc.target/i386/pr99530-1.c

> new file mode 100644

> index 00000000000..080d7cc9399

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-1.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-require-effective-target lp64 } */

> +/* { dg-options "-O2 -fpic -mcmodel=large -fno-plt" } */

> +/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-2.c b/gcc/testsuite/gcc.target/i386/pr99530-2.c

> new file mode 100644

> index 00000000000..9808957d624

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-2.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-require-effective-target lp64 } */

> +/* { dg-options "-O2 -fno-pic -mcmodel=large -fno-plt" } */

> +/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-3.c b/gcc/testsuite/gcc.target/i386/pr99530-3.c

> new file mode 100644

> index 00000000000..22fe81b25f2

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-3.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fno-pic -fno-plt" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-4.c b/gcc/testsuite/gcc.target/i386/pr99530-4.c

> new file mode 100644

> index 00000000000..aba0b5d7892

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-4.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fpic -fno-plt" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */

> +

> +extern void foo (void);

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-5.c b/gcc/testsuite/gcc.target/i386/pr99530-5.c

> new file mode 100644

> index 00000000000..02c5799d273

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-5.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fno-pic" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */

> +

> +extern void foo (void) __attribute__ ((noplt));

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> diff --git a/gcc/testsuite/gcc.target/i386/pr99530-6.c b/gcc/testsuite/gcc.target/i386/pr99530-6.c

> new file mode 100644

> index 00000000000..0dfdd3752f7

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/i386/pr99530-6.c

> @@ -0,0 +1,11 @@

> +/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */

> +/* { dg-options "-O2 -fpic" } */

> +/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */

> +/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */

> +

> +extern void foo (void) __attribute__ ((noplt));

> +void

> +bar (void)

> +{

> +  asm ("call %P0" : : "X" (foo));

> +}

> --

> 2.29.2

>
Hongyu Wang via Gcc-patches March 12, 2021, 1:18 p.m. | #3
On Thu, Mar 11, 2021 at 11:27 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>

> On Thu, Mar 11, 2021 at 11:22 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > Update 'P' operand modifier for -fno-plt to support inline assembly

> > statements.  In 64-bit, we can always load function address with

> > @GOTPCREL.  In 32-bit, we load function address with @GOT only for

> > non-PIC since PIC register may not be available at call site.

> >

> > gcc/

> >

> >         PR target/99504

> >         * config/i386/i386.c (ix86_print_operand): Update 'P' handling

> >         for -fno-plt.

> >

> > gcc/testsuite/

> >

> >         PR target/99504

> >         * gcc.target/i386/pr99530-1.c: New test.

> >         * gcc.target/i386/pr99530-2.c: Likewise.

> >         * gcc.target/i386/pr99530-3.c: Likewise.

> >         * gcc.target/i386/pr99530-4.c: Likewise.

> >         * gcc.target/i386/pr99530-5.c: Likewise.

> >         * gcc.target/i386/pr99530-6.c: Likewise.

> > ---

> >  gcc/config/i386/i386.c                    | 33 +++++++++++++++++++++--

> >  gcc/testsuite/gcc.target/i386/pr99530-1.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-2.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-3.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-4.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-5.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-6.c | 11 ++++++++

> >  7 files changed, 97 insertions(+), 2 deletions(-)

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-1.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-2.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-3.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-4.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-5.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-6.c

> >

> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c

> > index 2603333f87b..8733fcecf65 100644

> > --- a/gcc/config/i386/i386.c

> > +++ b/gcc/config/i386/i386.c

> > @@ -12701,7 +12701,8 @@ print_reg (rtx x, int code, FILE *file)

> >     y -- print "st(0)" instead of "st" as a register.

> >     d -- print duplicated register operand for AVX instruction.

> >     D -- print condition for SSE cmp instruction.

> > -   P -- if PIC, print an @PLT suffix.

> > +   P -- if PIC, print an @PLT suffix.  For -fno-plt, load function

> > +       address from GOT.

> >     p -- print raw symbol name.

> >     X -- don't print any sort of PIC '@' suffix for a symbol.

> >     & -- print some in-use local-dynamic symbol name.

> > @@ -13445,7 +13446,35 @@ ix86_print_operand (FILE *file, rtx x, int code)

> >           x = const0_rtx;

> >         }

> >

> > -      if (code != 'P' && code != 'p')

> > +      if (code == 'P')

> > +       {

> > +         if (current_output_insn == NULL_RTX

> > +             && (TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))

> > +             && !TARGET_PECOFF

> > +             && !TARGET_MACHO

> > +             && ix86_cmodel != CM_LARGE

> > +             && ix86_cmodel != CM_LARGE_PIC

> > +             && GET_CODE (x) == SYMBOL_REF

> > +             && SYMBOL_REF_FUNCTION_P (x)

> > +             && (!flag_plt

> > +                 || (SYMBOL_REF_DECL (x)

> > +                     && lookup_attribute ("noplt",

> > +                                          DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))

> > +             && !SYMBOL_REF_LOCAL_P (x))

>

> You can use ix86_force_load_from_GOT_p instead.

>


bool
ix86_force_load_from_GOT_p (rtx x)
{
  return ((TARGET_64BIT || HAVE_AS_IX86_GOT32X)
          && !TARGET_PECOFF && !TARGET_MACHO
          && !flag_pic <<<<<<<<<<<<<  This doesn't work with -fPIC/-fPIE.
          && ix86_cmodel != CM_LARGE
          && GET_CODE (x) == SYMBOL_REF
          && SYMBOL_REF_FUNCTION_P (x)
          && (!flag_plt
              || (SYMBOL_REF_DECL (x)
                  && lookup_attribute ("noplt",
                                       DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))
          && !SYMBOL_REF_LOCAL_P (x));
}

-- 
H.J.
Hongyu Wang via Gcc-patches March 12, 2021, 1:20 p.m. | #4
On Thu, Mar 11, 2021 at 11:21 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>

> On Thu, Mar 11, 2021 at 11:22 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > Update 'P' operand modifier for -fno-plt to support inline assembly

> > statements.  In 64-bit, we can always load function address with

> > @GOTPCREL.  In 32-bit, we load function address with @GOT only for

> > non-PIC since PIC register may not be available at call site.

> >

> > gcc/

> >

> >         PR target/99504

> >         * config/i386/i386.c (ix86_print_operand): Update 'P' handling

> >         for -fno-plt.

> >

> > gcc/testsuite/

> >

> >         PR target/99504

> >         * gcc.target/i386/pr99530-1.c: New test.

> >         * gcc.target/i386/pr99530-2.c: Likewise.

> >         * gcc.target/i386/pr99530-3.c: Likewise.

> >         * gcc.target/i386/pr99530-4.c: Likewise.

> >         * gcc.target/i386/pr99530-5.c: Likewise.

> >         * gcc.target/i386/pr99530-6.c: Likewise.

> > ---

> >  gcc/config/i386/i386.c                    | 33 +++++++++++++++++++++--

> >  gcc/testsuite/gcc.target/i386/pr99530-1.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-2.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-3.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-4.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-5.c | 11 ++++++++

> >  gcc/testsuite/gcc.target/i386/pr99530-6.c | 11 ++++++++

> >  7 files changed, 97 insertions(+), 2 deletions(-)

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-1.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-2.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-3.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-4.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-5.c

> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr99530-6.c

> >

> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c

> > index 2603333f87b..8733fcecf65 100644

> > --- a/gcc/config/i386/i386.c

> > +++ b/gcc/config/i386/i386.c

> > @@ -12701,7 +12701,8 @@ print_reg (rtx x, int code, FILE *file)

> >     y -- print "st(0)" instead of "st" as a register.

> >     d -- print duplicated register operand for AVX instruction.

> >     D -- print condition for SSE cmp instruction.

> > -   P -- if PIC, print an @PLT suffix.

> > +   P -- if PIC, print an @PLT suffix.  For -fno-plt, load function

> > +       address from GOT.

> >     p -- print raw symbol name.

> >     X -- don't print any sort of PIC '@' suffix for a symbol.

> >     & -- print some in-use local-dynamic symbol name.

> > @@ -13445,7 +13446,35 @@ ix86_print_operand (FILE *file, rtx x, int code)

> >           x = const0_rtx;

> >         }

> >

> > -      if (code != 'P' && code != 'p')

> > +      if (code == 'P')

> > +       {

> > +         if (current_output_insn == NULL_RTX

> > +             && (TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))

> > +             && !TARGET_PECOFF

> > +             && !TARGET_MACHO

> > +             && ix86_cmodel != CM_LARGE

> > +             && ix86_cmodel != CM_LARGE_PIC

> > +             && GET_CODE (x) == SYMBOL_REF

> > +             && SYMBOL_REF_FUNCTION_P (x)

> > +             && (!flag_plt

> > +                 || (SYMBOL_REF_DECL (x)

> > +                     && lookup_attribute ("noplt",

> > +                                          DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))

> > +             && !SYMBOL_REF_LOCAL_P (x))

> > +           {

> > +             /* For inline assembly statement, load function address

> > +                from GOT with 'P' operand modifier to avoid PLT.

> > +                NB: This works only with call or jmp.  */

> > +             const char *xasm;

> > +             if (TARGET_64BIT)

> > +               xasm = "{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";

> > +             else

> > +               xasm = "{*%p0@GOT|[DWORD PTR %p0@GOT]}";

> > +             output_asm_insn (xasm, &x);

> > +             return;

>

> This should be handled in output_pic_addr_const.

>


call/jmp are special and are handled by ix86_output_call_insn,
not output_pic_addr_const.

H.J.

Patch

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2603333f87b..8733fcecf65 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -12701,7 +12701,8 @@  print_reg (rtx x, int code, FILE *file)
    y -- print "st(0)" instead of "st" as a register.
    d -- print duplicated register operand for AVX instruction.
    D -- print condition for SSE cmp instruction.
-   P -- if PIC, print an @PLT suffix.
+   P -- if PIC, print an @PLT suffix.  For -fno-plt, load function
+	address from GOT.
    p -- print raw symbol name.
    X -- don't print any sort of PIC '@' suffix for a symbol.
    & -- print some in-use local-dynamic symbol name.
@@ -13445,7 +13446,35 @@  ix86_print_operand (FILE *file, rtx x, int code)
 	  x = const0_rtx;
 	}
 
-      if (code != 'P' && code != 'p')
+      if (code == 'P')
+	{
+	  if (current_output_insn == NULL_RTX
+	      && (TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))
+	      && !TARGET_PECOFF
+	      && !TARGET_MACHO
+	      && ix86_cmodel != CM_LARGE
+	      && ix86_cmodel != CM_LARGE_PIC
+	      && GET_CODE (x) == SYMBOL_REF
+	      && SYMBOL_REF_FUNCTION_P (x)
+	      && (!flag_plt
+		  || (SYMBOL_REF_DECL (x)
+		      && lookup_attribute ("noplt",
+					   DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))
+	      && !SYMBOL_REF_LOCAL_P (x))
+	    {
+	      /* For inline assembly statement, load function address
+		 from GOT with 'P' operand modifier to avoid PLT.
+		 NB: This works only with call or jmp.  */
+	      const char *xasm;
+	      if (TARGET_64BIT)
+		xasm = "{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+	      else
+		xasm = "{*%p0@GOT|[DWORD PTR %p0@GOT]}";
+	      output_asm_insn (xasm, &x);
+	      return;
+	    }
+	}
+      else if (code != 'p')
 	{
 	  if (CONST_INT_P (x))
 	    {
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-1.c b/gcc/testsuite/gcc.target/i386/pr99530-1.c
new file mode 100644
index 00000000000..080d7cc9399
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-1.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -fpic -mcmodel=large -fno-plt" } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */
+
+extern void foo (void); 
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+} 
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-2.c b/gcc/testsuite/gcc.target/i386/pr99530-2.c
new file mode 100644
index 00000000000..9808957d624
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-2.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -fno-pic -mcmodel=large -fno-plt" } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" } } */
+
+extern void foo (void); 
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+} 
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-3.c b/gcc/testsuite/gcc.target/i386/pr99530-3.c
new file mode 100644
index 00000000000..22fe81b25f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-3.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */
+
+extern void foo (void); 
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+} 
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-4.c b/gcc/testsuite/gcc.target/i386/pr99530-4.c
new file mode 100644
index 00000000000..aba0b5d7892
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-4.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */
+
+extern void foo (void);
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+} 
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-5.c b/gcc/testsuite/gcc.target/i386/pr99530-5.c
new file mode 100644
index 00000000000..02c5799d273
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-5.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O2 -fno-pic" } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOT" { target { ia32 && got32x_reloc } } } } */
+
+extern void foo (void) __attribute__ ((noplt)); 
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+} 
diff --git a/gcc/testsuite/gcc.target/i386/pr99530-6.c b/gcc/testsuite/gcc.target/i386/pr99530-6.c
new file mode 100644
index 00000000000..0dfdd3752f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99530-6.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O2 -fpic" } */
+/* { dg-final { scan-assembler "call\[ \t\]+\[*\]foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target { ia32 } } } } */
+
+extern void foo (void) __attribute__ ((noplt)); 
+void
+bar (void)
+{
+  asm ("call %P0" : : "X" (foo));
+}