re PR target/67400 (-fno-plt doesn't work with function pointers)

PR target/67400
	* config/i386/i386-protos.h (ix86_force_load_from_GOT_p): New.
	* config/i386/i386.c (ix86_force_load_from_GOT_p): New function.
	(ix86_legitimate_constant_p): Do not allow UNSPEC_GOTPCREL if
	ix86_force_load_from_GOT_p returns true.
	(ix86_legitimate_address_p): Allow UNSPEC_GOTPCREL if
	ix86_force_load_from_GOT_p returns true.
	(ix86_print_operand_address_as): Support UNSPEC_GOTPCREL if
	ix86_force_load_from_GOT_p returns true.
	(ix86_expand_move): Load the external function address via the
	GOT slot if ix86_force_load_from_GOT_p returns true.
	* config/i386/predicates.md (x86_64_immediate_operand): Return
	false for SYMBOL_REFs where ix86_force_load_from_GOT_p returns true.
	(x86_64_zext_immediate_operand): Ditto.

testsuite/ChangeLog:

	PR target/67400
        * gcc.target/i386/pr67400-1.c: New test.
        * gcc.target/i386/pr67400-2.c: Likewise.
        * gcc.target/i386/pr67400-3.c: Likewise.
        * gcc.target/i386/pr67400-4.c: Likewise.
        * gcc.target/i386/pr67400-5.c: Likewise.
        * gcc.target/i386/pr67400-6.c: Likewise.
        * gcc.target/i386/pr67400-7.c: Likewise.

From-SVN: r237720
This commit is contained in:
Uros Bizjak 2016-06-23 00:06:56 +02:00
parent 37c467c0a5
commit e3d62871c3
12 changed files with 189 additions and 9 deletions

View file

@ -1,3 +1,21 @@
2016-06-23 Uros Bizjak <ubizjak@gmail.com>
H.J. Lu <hongjiu.lu@intel.com>
PR target/67400
* config/i386/i386-protos.h (ix86_force_load_from_GOT_p): New.
* config/i386/i386.c (ix86_force_load_from_GOT_p): New function.
(ix86_legitimate_constant_p): Do not allow UNSPEC_GOTPCREL if
ix86_force_load_from_GOT_p returns true.
(ix86_legitimate_address_p): Allow UNSPEC_GOTPCREL if
ix86_force_load_from_GOT_p returns true.
(ix86_print_operand_address_as): Support UNSPEC_GOTPCREL if
ix86_force_load_from_GOT_p returns true.
(ix86_expand_move): Load the external function address via the
GOT slot if ix86_force_load_from_GOT_p returns true.
* config/i386/predicates.md (x86_64_immediate_operand): Return
false for SYMBOL_REFs where ix86_force_load_from_GOT_p returns true.
(x86_64_zext_immediate_operand): Ditto.
2016-06-22 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (ix86_expand_move): Simplify SYMBOL_REF handling.

View file

@ -70,6 +70,7 @@ extern bool ix86_expand_set_or_movmem (rtx, rtx, rtx, rtx, rtx, rtx,
extern bool constant_address_p (rtx);
extern bool legitimate_pic_operand_p (rtx);
extern bool legitimate_pic_address_disp_p (rtx);
extern bool ix86_force_load_from_GOT_p (rtx);
extern void print_reg (rtx, int, FILE*);
extern void ix86_print_operand (FILE *, rtx, int);

View file

@ -15120,6 +15120,19 @@ darwin_local_data_pic (rtx disp)
&& XINT (disp, 1) == UNSPEC_MACHOPIC_OFFSET);
}
/* True if operand X should be loaded from GOT. */
bool
ix86_force_load_from_GOT_p (rtx x)
{
return (TARGET_64BIT && !TARGET_PECOFF && !TARGET_MACHO
&& !flag_plt && !flag_pic
&& ix86_cmodel != CM_LARGE
&& GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x)
&& !SYMBOL_REF_LOCAL_P (x));
}
/* Determine if a given RTX is a valid constant. We already know this
satisfies CONSTANT_P. */
@ -15188,6 +15201,12 @@ ix86_legitimate_constant_p (machine_mode mode, rtx x)
if (MACHO_DYNAMIC_NO_PIC_P)
return machopic_symbol_defined_p (x);
#endif
/* External function address should be loaded
via the GOT slot to avoid PLT. */
if (ix86_force_load_from_GOT_p (x))
return false;
break;
CASE_CONST_SCALAR_INT:
@ -15596,6 +15615,9 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
return false;
case UNSPEC_GOTPCREL:
if (ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0)))
goto is_legitimate_pic;
/* FALLTHRU */
case UNSPEC_PCREL:
gcc_assert (flag_pic);
goto is_legitimate_pic;
@ -18169,6 +18191,12 @@ ix86_print_operand_address_as (FILE *file, rtx addr,
fputs ("ds:", file);
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
}
/* Load the external function address via the GOT slot to avoid PLT. */
else if (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == UNSPEC
&& XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL
&& ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0)))
output_pic_addr_const (file, disp, 0);
else if (flag_pic)
output_pic_addr_const (file, disp, 0);
else
@ -19417,6 +19445,15 @@ ix86_expand_move (machine_mode mode, rtx operands[])
if (model)
op1 = legitimize_tls_address (op1, model, true);
else if (ix86_force_load_from_GOT_p (op1))
{
/* Load the external function address via GOT slot to avoid PLT. */
op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
UNSPEC_GOTPCREL);
op1 = gen_rtx_CONST (Pmode, op1);
op1 = gen_const_mem (Pmode, op1);
set_mem_alias_set (op1, ix86_GOT_alias_set ());
}
else
{
tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX);

View file

@ -160,13 +160,18 @@
return trunc_int_for_mode (val, SImode) == val;
}
case SYMBOL_REF:
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op))
return false;
/* Load the external function address via the GOT slot. */
if (ix86_force_load_from_GOT_p (op))
return false;
/* For certain code models, the symbolic references are known to fit.
in CM_SMALL_PIC model we know it fits if it is local to the shared
library. Don't count TLS SYMBOL_REFs here, since they should fit
only if inside of UNSPEC handled below. */
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op))
return false;
return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
|| (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
@ -207,6 +212,11 @@
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op1))
return false;
/* Load the external function address via the GOT slot. */
if (ix86_force_load_from_GOT_p (op1))
return false;
/* For CM_SMALL assume that latest object is 16MB before
end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are
@ -273,10 +283,15 @@
return !(INTVAL (op) & ~(HOST_WIDE_INT) 0xffffffff);
case SYMBOL_REF:
/* For certain code models, the symbolic references are known to fit. */
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op))
return false;
/* Load the external function address via the GOT slot. */
if (ix86_force_load_from_GOT_p (op))
return false;
/* For certain code models, the symbolic references are known to fit. */
return (ix86_cmodel == CM_SMALL
|| (ix86_cmodel == CM_MEDIUM
&& !SYMBOL_REF_FAR_ADDR_P (op)));
@ -301,6 +316,11 @@
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op1))
return false;
/* Load the external function address via the GOT slot. */
if (ix86_force_load_from_GOT_p (op1))
return false;
/* For small code model we may accept pretty large positive
offsets, since one bit is available for free. Negative
offsets are limited by the size of NULL pointer area

View file

@ -1,3 +1,14 @@
2016-06-23 H.J. Lu <hongjiu.lu@intel.com>
PR target/67400
* gcc.target/i386/pr67400-1.c: New test.
* gcc.target/i386/pr67400-2.c: Likewise.
* gcc.target/i386/pr67400-3.c: Likewise.
* gcc.target/i386/pr67400-4.c: Likewise.
* gcc.target/i386/pr67400-5.c: Likewise.
* gcc.target/i386/pr67400-6.c: Likewise.
* gcc.target/i386/pr67400-7.c: Likewise.
2016-06-22 David Malcolm <dmalcolm@redhat.com>
* c-c++-common/missing-header-1.c: New test case.
@ -355,7 +366,7 @@
2016-06-15 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/torture/float128-nan.c: Include stdint.h to define uint64_t.
* gcc.dg/torture/float128-nan.c: Include stdint.h to define uint64_t.
2016-06-15 Alan Hayward <alan.hayward@arm.com>
@ -394,10 +405,10 @@
2016-06-14 Uros Bizjak <ubizjak@gmail.com>
* gcc.target/i386/float128-3.c: New test.
* gcc.target/i386/quad-sse4.c: Ditto.
* gcc.target/i386/quad-sse.c: Use -msse instead of -msse2.
Update scan strings.
* gcc.target/i386/float128-3.c: New test.
* gcc.target/i386/quad-sse4.c: Ditto.
* gcc.target/i386/quad-sse.c: Use -msse instead of -msse2.
Update scan strings.
2016-06-14 Richard Biener <rguenther@suse.de>

View file

@ -0,0 +1,13 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern void bar (void);
void *
foo (void)
{
return &bar;
}
/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */

View file

@ -0,0 +1,14 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern void bar (void);
extern void *p;
void
foo (void)
{
p = &bar;
}
/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */

View file

@ -0,0 +1,16 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
static void
bar (void)
{
}
void *
foo (void)
{
return &bar;
}
/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */
/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */

View file

@ -0,0 +1,13 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern void bar (void) __attribute__ ((visibility ("hidden")));
void *
foo (void)
{
return &bar;
}
/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */
/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */

View file

@ -0,0 +1,11 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern void foo (void);
extern void bar (int, int, int, int, int, int, void *);
void
x (void)
{
bar (1, 2, 3, 4, 5, 6, foo);
}

View file

@ -0,0 +1,13 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern int bar (void);
int
check (void *p)
{
return p != &bar;
}
/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" } } */
/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */

View file

@ -0,0 +1,13 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
/* { dg-options "-O2 -fno-pic -fno-plt" } */
extern void bar (void);
void *
foo (void)
{
return &bar+1;
}
/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */