Don't allow mask/sse/mmx mov in TLS code sequences.

As change in assembler, refer to [1], this patch disallow mask/sse/mmx
mov in TLS code sequences which require integer MOV instructions.

[1] https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d7e3e627027fcf37d63e284144fe27ff4eba36b5

gcc/ChangeLog:

	PR target/103275
	* config/i386/constraints.md (Bk): New
	define_memory_constraint.
	* config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p):
	Declare.
	* config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New
	function.
	* config/i386/i386.md (*movsi_internal): Don't allow
	mask/sse/mmx move in TLS code sequences.
	(*movdi_internal): Ditto.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/pr103275.c: New test.
This commit is contained in:
liuhongt 2021-11-17 15:48:37 +08:00
parent 2b5b8610e9
commit b5844cb0bc
5 changed files with 123 additions and 4 deletions

View File

@ -186,6 +186,11 @@
(and (match_operand 0 "memory_operand")
(match_test "constant_address_p (XEXP (op, 0))")))
(define_memory_constraint "Bk"
"@internal TLS address that allows insn using non-integer registers."
(and (match_operand 0 "memory_operand")
(not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
(define_special_memory_constraint "Bn"
"@internal Memory operand without REX prefix."
(match_operand 0 "norex_memory_operand"))

View File

@ -243,6 +243,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
#endif
extern rtx ix86_tls_module_base (void);
extern bool ix86_gpr_tls_address_pattern_p (rtx);
extern bool ix86_tls_address_pattern_p (rtx);
extern rtx ix86_rewrite_tls_address (rtx);

View File

@ -11628,6 +11628,36 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
return dest;
}
/* Return true if the TLS address requires insn using integer registers.
It's used to prevent KMOV/VMOV in TLS code sequences which require integer
MOV instructions, refer to PR103275. */
bool
ix86_gpr_tls_address_pattern_p (rtx mem)
{
gcc_assert (MEM_P (mem));
rtx addr = XEXP (mem, 0);
subrtx_var_iterator::array_type array;
FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
{
rtx op = *iter;
if (GET_CODE (op) == UNSPEC)
switch (XINT (op, 1))
{
case UNSPEC_GOTNTPOFF:
return true;
case UNSPEC_TPOFF:
if (!TARGET_64BIT)
return true;
break;
default:
break;
}
}
return false;
}
/* Return true if OP refers to a TLS address. */
bool
ix86_tls_address_pattern_p (rtx op)

View File

@ -2164,9 +2164,9 @@
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand"
"=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
"=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
(match_operand:DI 1 "general_operand"
"riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
"riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*kBk,*k,*k,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{
@ -2385,9 +2385,9 @@
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand"
"=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
"=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
(match_operand:SI 1 "general_operand"
"g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
"g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*kBk,*k ,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{

View File

@ -0,0 +1,83 @@
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -march=tigerlake -fPIC" } */
/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
typedef uint32_t in_addr_t;
struct in_addr { in_addr_t s_addr; };
extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
extern unsigned long strtoul (const char*, char**, int);
extern uint32_t __bswap_32 (in_addr_t);
int
inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
{
static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
in_addr_t val;
char c;
union iaddr
{
uint8_t bytes[4];
uint32_t word;
} res;
uint8_t *pp = res.bytes;
int digit;
int saved_errno = __libc_errno;
__libc_errno = 0;
res.word = 0;
c = *cp;
for (;;)
{
if (c < '0' || c > '9')
goto ret_0;
{
char *endp;
unsigned long ul = strtoul (cp, &endp, 0);
if (ul == 0x7fffffffL && __libc_errno == 34)
goto ret_0;
if (ul > 0xfffffffful)
goto ret_0;
val = ul;
digit = cp != endp;
cp = endp;
}
c = *cp;
if (c == '.')
{
if (pp > res.bytes + 2 || val > 0xff)
goto ret_0;
*pp++ = val;
c = *++cp;
}
else
break;
}
if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
goto ret_0;
if (!digit)
goto ret_0;
if (val > max[pp - res.bytes])
goto ret_0;
if (addr != 0)
addr->s_addr = res.word | __bswap_32 (val);
*endp = cp;
__libc_errno = saved_errno;
return 1;
ret_0:
__libc_errno = saved_errno;
return 0;
}