* [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. @ 2021-11-18 7:18 liuhongt 2021-11-18 8:19 ` Uros Bizjak 0 siblings, 1 reply; 6+ messages in thread From: liuhongt @ 2021-11-18 7:18 UTC (permalink / raw) To: gcc-patches 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 Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. Ok for trunk and GCC11 upstream branch? gcc/ChangeLog: PR target/103275 * config/i386/i386-protos.h (ix86_notls_memory): Declare. * config/i386/i386.c (ix86_notls_memory): 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. --- gcc/config/i386/constraints.md | 5 + gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 34 ++++++ gcc/config/i386/i386.md | 18 +-- gcc/testsuite/gcc.target/i386/pr103275.c | 148 +++++++++++++++++++++++ 5 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 87cceac4cfb..489c76164a1 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -186,6 +186,11 @@ (define_special_memory_constraint "Bc" (and (match_operand 0 "memory_operand") (match_test "constant_address_p (XEXP (op, 0))"))) +(define_special_memory_constraint "Bk" + "@internal notls memory operand." + (and (match_operand 0 "memory_operand") + (match_test "ix86_notls_memory (op)"))) + (define_special_memory_constraint "Bn" "@internal Memory operand without REX prefix." (match_operand 0 "norex_memory_operand")) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 7e05510c679..1fb09be8b7e 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -243,6 +243,7 @@ extern unsigned int ix86_get_callcvt (const_tree); #endif extern rtx ix86_tls_module_base (void); +extern bool ix86_notls_memory (rtx); extern bool ix86_tls_address_pattern_p (rtx); extern rtx ix86_rewrite_tls_address (rtx); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index c246c8736f5..f1b7f57b0ca 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11628,6 +11628,40 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) return dest; } +/* Return true if it's not tls memory, + NB: it's different from ix86_tls_address_pattern_p since it also matchs + gottpoff/gotntpoff. + It's used to prevent KMOV/VMOV in TLS code sequences which require integer + MOV instructions, refer to PR103275. */ +bool +ix86_notls_memory (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 false; + case UNSPEC_TPOFF: + if (!TARGET_64BIT) + return false; + break; + default: + break; + } + /* Should iter.skip_subrtxes (); + if there's no inner UNSPEC in addr???. */ + } + + return true; +} + /* Return true if OP refers to a TLS address. */ bool ix86_tls_address_pattern_p (rtx op) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7b2de60706d..9feba81974b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2164,9 +2164,9 @@ (define_split (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,*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,*k,*Bk,*k,*k,CBC"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && ix86_hardreg_mov_ok (operands[0], operands[1])" { @@ -2228,7 +2228,7 @@ (define_insn "*movdi_internal" [(set (attr "isa") (cond [(eq_attr "alternative" "0,1,17,18") (const_string "nox64") - (eq_attr "alternative" "2,3,4,5,10,11,23,25") + (eq_attr "alternative" "2,3,4,5,10,11,23,26") (const_string "x64") (eq_attr "alternative" "19,20") (const_string "x64_sse2") @@ -2249,9 +2249,9 @@ (define_insn "*movdi_internal" (const_string "ssemov") (eq_attr "alternative" "21,22") (const_string "ssecvt") - (eq_attr "alternative" "23,24,25,26") + (eq_attr "alternative" "23,24,25,26,27") (const_string "mskmov") - (eq_attr "alternative" "27") + (eq_attr "alternative" "28") (const_string "msklog") (and (match_operand 0 "register_operand") (match_operand 1 "pic_32bit_operand")) @@ -2385,9 +2385,9 @@ (define_peephole2 (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 ,*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,*k, *Bk,*k ,CBC"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && ix86_hardreg_mov_ok (operands[0], operands[1])" { @@ -2452,9 +2452,9 @@ (define_insn "*movsi_internal" (const_string "sselog1") (eq_attr "alternative" "9,10,11,12,13") (const_string "ssemov") - (eq_attr "alternative" "14,15,16") + (eq_attr "alternative" "14,15,16,17") (const_string "mskmov") - (eq_attr "alternative" "17") + (eq_attr "alternative" "18") (const_string "msklog") (and (match_operand 0 "register_operand") (match_operand 1 "pic_32bit_operand")) diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c new file mode 100644 index 00000000000..288e680ffb2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103275.c @@ -0,0 +1,148 @@ +/* { 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"))); + +enum +{ + _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)), +}; + + +extern inline const uint16_t ** __attribute__ ((const)) +__ctype_b_loc (void) +{ + return (&__libc_tsd_CTYPE_B); +} + +extern unsigned long strtoul (const char*, char**, int); +extern uint32_t __bswap_32 (in_addr_t); +static 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 (!({ int __c = (c); __c >= '0' && __c <= '9'; })) + goto ret_0; + { + char *endp; + unsigned long ul = strtoul (cp, &endp, 0); + if (ul == + (0x7fffffffL * 2UL + 1UL) + && __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 (c != '\0' && (!(((c) & ~0x7f) == 0) || !((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISspace))) + goto ret_0; + + if (!digit) + goto ret_0; + + + + if (val > max[pp - res.bytes]) + goto ret_0; + + if (addr != + ((void *)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; +} + +int +__inet_aton_exact (const char *cp, struct in_addr *addr) +{ + struct in_addr val; + const char *endp; + + if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) + { + *addr = val; + return 1; + } + else + return 0; +} + + + +int +__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) +{ + const char *endp; + return inet_aton_end (cp, addr, &endp); +} +extern __typeof (__inet_aton_ignore_trailing) inet_aton __attribute__ ((weak, alias ("__inet_aton_ignore_trailing"))) __attribute__ ((__copy__ (__inet_aton_ignore_trailing))); + + + +in_addr_t +__inet_addr (const char *cp) +{ + struct in_addr val; + const char *endp; + if (inet_aton_end (cp, &val, &endp)) + return val.s_addr; + return ((in_addr_t) 0xffffffff); +} +extern __typeof (__inet_addr) inet_addr __attribute__ ((weak, alias ("__inet_addr"))) __attribute__ ((__copy__ (__inet_addr))); -- 2.18.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. 2021-11-18 7:18 [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences liuhongt @ 2021-11-18 8:19 ` Uros Bizjak 2021-11-19 1:14 ` liuhongt 0 siblings, 1 reply; 6+ messages in thread From: Uros Bizjak @ 2021-11-18 8:19 UTC (permalink / raw) To: liuhongt; +Cc: gcc-patches, H. J. Lu, Hongtao Liu On Thu, Nov 18, 2021 at 8:18 AM liuhongt <hongtao.liu@intel.com> wrote: > > 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 > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > Ok for trunk and GCC11 upstream branch? > > gcc/ChangeLog: > > PR target/103275 > * config/i386/i386-protos.h (ix86_notls_memory): Declare. > * config/i386/i386.c (ix86_notls_memory): 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. > --- > gcc/config/i386/constraints.md | 5 + > gcc/config/i386/i386-protos.h | 1 + > gcc/config/i386/i386.c | 34 ++++++ > gcc/config/i386/i386.md | 18 +-- > gcc/testsuite/gcc.target/i386/pr103275.c | 148 +++++++++++++++++++++++ > 5 files changed, 197 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md > index 87cceac4cfb..489c76164a1 100644 > --- a/gcc/config/i386/constraints.md > +++ b/gcc/config/i386/constraints.md > @@ -186,6 +186,11 @@ (define_special_memory_constraint "Bc" > (and (match_operand 0 "memory_operand") > (match_test "constant_address_p (XEXP (op, 0))"))) > > +(define_special_memory_constraint "Bk" > + "@internal notls memory operand." > + (and (match_operand 0 "memory_operand") > + (match_test "ix86_notls_memory (op)"))) Why is the above declared as a special memory constraint? Also the predicate comment is missing and the description should say something like: @internal TLS address that allows insn using non-integer registers > (define_special_memory_constraint "Bn" > "@internal Memory operand without REX prefix." > (match_operand 0 "norex_memory_operand")) > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > index 7e05510c679..1fb09be8b7e 100644 > --- a/gcc/config/i386/i386-protos.h > +++ b/gcc/config/i386/i386-protos.h > @@ -243,6 +243,7 @@ extern unsigned int ix86_get_callcvt (const_tree); > #endif > > extern rtx ix86_tls_module_base (void); > +extern bool ix86_notls_memory (rtx); > extern bool ix86_tls_address_pattern_p (rtx); > extern rtx ix86_rewrite_tls_address (rtx); > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index c246c8736f5..f1b7f57b0ca 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -11628,6 +11628,40 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) > return dest; > } > > +/* Return true if it's not tls memory, > + NB: it's different from ix86_tls_address_pattern_p since it also matchs > + gottpoff/gotntpoff. > + It's used to prevent KMOV/VMOV in TLS code sequences which require integer > + MOV instructions, refer to PR103275. */ > +bool > +ix86_notls_memory (rtx mem) I think it is better to avoid negative logic. So, something like Return true if the TLS address requires insn using integer registers. bool ix86_gpr_tls_address_pattern_p (and use not in the predicate) > +{ > + 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 false; > + case UNSPEC_TPOFF: > + if (!TARGET_64BIT) > + return false; > + break; > + default: > + break; > + } > + /* Should iter.skip_subrtxes (); > + if there's no inner UNSPEC in addr???. */ You should figure the above before submitting the patch. > + } > + > + return true; > +} > + > /* Return true if OP refers to a TLS address. */ > bool > ix86_tls_address_pattern_p (rtx op) > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > index 7b2de60706d..9feba81974b 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -2164,9 +2164,9 @@ (define_split > > (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,*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,*k,*Bk,*k,*k,CBC"))] > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > && ix86_hardreg_mov_ok (operands[0], operands[1])" > { > @@ -2228,7 +2228,7 @@ (define_insn "*movdi_internal" > [(set (attr "isa") > (cond [(eq_attr "alternative" "0,1,17,18") > (const_string "nox64") > - (eq_attr "alternative" "2,3,4,5,10,11,23,25") > + (eq_attr "alternative" "2,3,4,5,10,11,23,26") > (const_string "x64") > (eq_attr "alternative" "19,20") > (const_string "x64_sse2") > @@ -2249,9 +2249,9 @@ (define_insn "*movdi_internal" > (const_string "ssemov") > (eq_attr "alternative" "21,22") > (const_string "ssecvt") > - (eq_attr "alternative" "23,24,25,26") > + (eq_attr "alternative" "23,24,25,26,27") > (const_string "mskmov") > - (eq_attr "alternative" "27") > + (eq_attr "alternative" "28") > (const_string "msklog") > (and (match_operand 0 "register_operand") > (match_operand 1 "pic_32bit_operand")) > @@ -2385,9 +2385,9 @@ (define_peephole2 > > (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 ,*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,*k, *Bk,*k ,CBC"))] > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > && ix86_hardreg_mov_ok (operands[0], operands[1])" > { > @@ -2452,9 +2452,9 @@ (define_insn "*movsi_internal" > (const_string "sselog1") > (eq_attr "alternative" "9,10,11,12,13") > (const_string "ssemov") > - (eq_attr "alternative" "14,15,16") > + (eq_attr "alternative" "14,15,16,17") > (const_string "mskmov") > - (eq_attr "alternative" "17") > + (eq_attr "alternative" "18") > (const_string "msklog") > (and (match_operand 0 "register_operand") > (match_operand 1 "pic_32bit_operand")) > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c > new file mode 100644 > index 00000000000..288e680ffb2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c > @@ -0,0 +1,148 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -march=tigerlake -fPIC" } */ > +/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */ Can you please minimize the testcase? Uros. > + > +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"))); > + > +enum > +{ > + _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)), > +}; > + > + > +extern inline const uint16_t ** __attribute__ ((const)) > +__ctype_b_loc (void) > +{ > + return (&__libc_tsd_CTYPE_B); > +} > + > +extern unsigned long strtoul (const char*, char**, int); > +extern uint32_t __bswap_32 (in_addr_t); > +static 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 (!({ int __c = (c); __c >= '0' && __c <= '9'; })) > + goto ret_0; > + { > + char *endp; > + unsigned long ul = strtoul (cp, &endp, 0); > + if (ul == > + (0x7fffffffL * 2UL + 1UL) > + && __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 (c != '\0' && (!(((c) & ~0x7f) == 0) || !((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISspace))) > + goto ret_0; > + > + if (!digit) > + goto ret_0; > + > + > + > + if (val > max[pp - res.bytes]) > + goto ret_0; > + > + if (addr != > + ((void *)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; > +} > + > +int > +__inet_aton_exact (const char *cp, struct in_addr *addr) > +{ > + struct in_addr val; > + const char *endp; > + > + if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) > + { > + *addr = val; > + return 1; > + } > + else > + return 0; > +} > + > + > + > +int > +__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) > +{ > + const char *endp; > + return inet_aton_end (cp, addr, &endp); > +} > +extern __typeof (__inet_aton_ignore_trailing) inet_aton __attribute__ ((weak, alias ("__inet_aton_ignore_trailing"))) __attribute__ ((__copy__ (__inet_aton_ignore_trailing))); > + > + > + > +in_addr_t > +__inet_addr (const char *cp) > +{ > + struct in_addr val; > + const char *endp; > + if (inet_aton_end (cp, &val, &endp)) > + return val.s_addr; > + return ((in_addr_t) 0xffffffff); > +} > +extern __typeof (__inet_addr) inet_addr __attribute__ ((weak, alias ("__inet_addr"))) __attribute__ ((__copy__ (__inet_addr))); > -- > 2.18.1 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. 2021-11-18 8:19 ` Uros Bizjak @ 2021-11-19 1:14 ` liuhongt 2021-11-19 7:50 ` Uros Bizjak 0 siblings, 1 reply; 6+ messages in thread From: liuhongt @ 2021-11-19 1:14 UTC (permalink / raw) To: gcc-patches >Why is the above declared as a special memory constraint? Also the Change to define_memory_constraint since it's ok for reload can make them match by converting the operand to the form ‘(mem (reg X))’.where X is a base register (from the register class specified by BASE_REG_CLASS >predicate comment is missing and the description should say something >like: > >@internal TLS address that allows insn using non-integer registers Changed. >I think it is better to avoid negative logic. So, something like > >Return true if the TLS address requires insn using integer registers. > >bool >ix86_gpr_tls_address_pattern_p > >(and use not in the predicate) Changed. >> +{ >> + 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 false; >> + case UNSPEC_TPOFF: >> + if (!TARGET_64BIT) >> + return false; >> + break; >> + default: >> + break; >> + } >> + /* Should iter.skip_subrtxes (); >> + if there's no inner UNSPEC in addr???. */ >You should figure the above before submitting the patch. ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so remove comments. >Can you please minimize the testcase? Done; 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/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. --- gcc/config/i386/constraints.md | 5 ++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 32 +++++++++ gcc/config/i386/i386.md | 18 ++--- gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index eaa582d2055..15c5950ee6f 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc" (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")) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 7782cf1163f..941e91636d8 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -240,6 +240,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); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 42c47d2b12b..68079e4230e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11468,6 +11468,38 @@ 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. + NB: it's different from ix86_tls_address_pattern_p since it also matchs + gottpoff/gotntpoff. + 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) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 97325e38676..82b85b26059 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2085,9 +2085,9 @@ (define_split (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,*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,*k,*Bk,*k,*k,CBC"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && ix86_hardreg_mov_ok (operands[0], operands[1])" { @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal" [(set (attr "isa") (cond [(eq_attr "alternative" "0,1,17,18") (const_string "nox64") - (eq_attr "alternative" "2,3,4,5,10,11,23,25") + (eq_attr "alternative" "2,3,4,5,10,11,23,26") (const_string "x64") (eq_attr "alternative" "19,20") (const_string "x64_sse2") @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal" (const_string "ssemov") (eq_attr "alternative" "21,22") (const_string "ssecvt") - (eq_attr "alternative" "23,24,25,26") + (eq_attr "alternative" "23,24,25,26,27") (const_string "mskmov") - (eq_attr "alternative" "27") + (eq_attr "alternative" "28") (const_string "msklog") (and (match_operand 0 "register_operand") (match_operand 1 "pic_32bit_operand")) @@ -2306,9 +2306,9 @@ (define_peephole2 (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 ,*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,*k, *Bk,*k ,CBC"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && ix86_hardreg_mov_ok (operands[0], operands[1])" { @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal" (const_string "sselog1") (eq_attr "alternative" "9,10,11,12,13") (const_string "ssemov") - (eq_attr "alternative" "14,15,16") + (eq_attr "alternative" "14,15,16,17") (const_string "mskmov") - (eq_attr "alternative" "17") + (eq_attr "alternative" "18") (const_string "msklog") (and (match_operand 0 "register_operand") (match_operand 1 "pic_32bit_operand")) diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c new file mode 100644 index 00000000000..c93413f3cde --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103275.c @@ -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; +} -- 2.18.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. 2021-11-19 1:14 ` liuhongt @ 2021-11-19 7:50 ` Uros Bizjak 2021-11-19 7:53 ` Uros Bizjak 0 siblings, 1 reply; 6+ messages in thread From: Uros Bizjak @ 2021-11-19 7:50 UTC (permalink / raw) To: liuhongt; +Cc: gcc-patches On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote: > > >Why is the above declared as a special memory constraint? Also the > Change to define_memory_constraint since it's ok for > reload can make them match by converting the operand to the form > ‘(mem (reg X))’.where X is a base register (from the register class specified > by BASE_REG_CLASS > > >predicate comment is missing and the description should say something > >like: > > > >@internal TLS address that allows insn using non-integer registers > Changed. > > >I think it is better to avoid negative logic. So, something like > > > >Return true if the TLS address requires insn using integer registers. > > > >bool > >ix86_gpr_tls_address_pattern_p > > > >(and use not in the predicate) > > Changed. > > >> +{ > >> + 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 false; > >> + case UNSPEC_TPOFF: > >> + if (!TARGET_64BIT) > >> + return false; > >> + break; > >> + default: > >> + break; > >> + } > >> + /* Should iter.skip_subrtxes (); > >> + if there's no inner UNSPEC in addr???. */ > > >You should figure the above before submitting the patch. > ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so > remove comments. > > >Can you please minimize the testcase? > Done; > > 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/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. OK, with a small comment adjustment below. Thanks, Uros. > --- > gcc/config/i386/constraints.md | 5 ++ > gcc/config/i386/i386-protos.h | 1 + > gcc/config/i386/i386.c | 32 +++++++++ > gcc/config/i386/i386.md | 18 ++--- > gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++ > 5 files changed, 130 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md > index eaa582d2055..15c5950ee6f 100644 > --- a/gcc/config/i386/constraints.md > +++ b/gcc/config/i386/constraints.md > @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc" > (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")) > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > index 7782cf1163f..941e91636d8 100644 > --- a/gcc/config/i386/i386-protos.h > +++ b/gcc/config/i386/i386-protos.h > @@ -240,6 +240,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); > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 42c47d2b12b..68079e4230e 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -11468,6 +11468,38 @@ 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. > + NB: it's different from ix86_tls_address_pattern_p since it also matchs > + gottpoff/gotntpoff. The above NB comment is not needed, the fact is obvious from the code. > + 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) > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > index 97325e38676..82b85b26059 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -2085,9 +2085,9 @@ (define_split > > (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,*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,*k,*Bk,*k,*k,CBC"))] > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > && ix86_hardreg_mov_ok (operands[0], operands[1])" > { > @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal" > [(set (attr "isa") > (cond [(eq_attr "alternative" "0,1,17,18") > (const_string "nox64") > - (eq_attr "alternative" "2,3,4,5,10,11,23,25") > + (eq_attr "alternative" "2,3,4,5,10,11,23,26") > (const_string "x64") > (eq_attr "alternative" "19,20") > (const_string "x64_sse2") > @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal" > (const_string "ssemov") > (eq_attr "alternative" "21,22") > (const_string "ssecvt") > - (eq_attr "alternative" "23,24,25,26") > + (eq_attr "alternative" "23,24,25,26,27") > (const_string "mskmov") > - (eq_attr "alternative" "27") > + (eq_attr "alternative" "28") > (const_string "msklog") > (and (match_operand 0 "register_operand") > (match_operand 1 "pic_32bit_operand")) > @@ -2306,9 +2306,9 @@ (define_peephole2 > > (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 ,*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,*k, *Bk,*k ,CBC"))] > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > && ix86_hardreg_mov_ok (operands[0], operands[1])" > { > @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal" > (const_string "sselog1") > (eq_attr "alternative" "9,10,11,12,13") > (const_string "ssemov") > - (eq_attr "alternative" "14,15,16") > + (eq_attr "alternative" "14,15,16,17") > (const_string "mskmov") > - (eq_attr "alternative" "17") > + (eq_attr "alternative" "18") > (const_string "msklog") > (and (match_operand 0 "register_operand") > (match_operand 1 "pic_32bit_operand")) > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c > new file mode 100644 > index 00000000000..c93413f3cde > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c > @@ -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; > +} > -- > 2.18.1 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. 2021-11-19 7:50 ` Uros Bizjak @ 2021-11-19 7:53 ` Uros Bizjak 2021-11-22 3:19 ` Hongtao Liu 0 siblings, 1 reply; 6+ messages in thread From: Uros Bizjak @ 2021-11-19 7:53 UTC (permalink / raw) To: liuhongt; +Cc: gcc-patches On Fri, Nov 19, 2021 at 8:50 AM Uros Bizjak <ubizjak@gmail.com> wrote: > > On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote: > > > > >Why is the above declared as a special memory constraint? Also the > > Change to define_memory_constraint since it's ok for > > reload can make them match by converting the operand to the form > > ‘(mem (reg X))’.where X is a base register (from the register class specified > > by BASE_REG_CLASS > > > > >predicate comment is missing and the description should say something > > >like: > > > > > >@internal TLS address that allows insn using non-integer registers > > Changed. > > > > >I think it is better to avoid negative logic. So, something like > > > > > >Return true if the TLS address requires insn using integer registers. > > > > > >bool > > >ix86_gpr_tls_address_pattern_p > > > > > >(and use not in the predicate) > > > > Changed. > > > > >> +{ > > >> + 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 false; > > >> + case UNSPEC_TPOFF: > > >> + if (!TARGET_64BIT) > > >> + return false; > > >> + break; > > >> + default: > > >> + break; > > >> + } > > >> + /* Should iter.skip_subrtxes (); > > >> + if there's no inner UNSPEC in addr???. */ > > > > >You should figure the above before submitting the patch. > > ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so > > remove comments. > > > > >Can you please minimize the testcase? > > Done; > > > > 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/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. > > OK, with a small comment adjustment below. Ops, sorry, I was too fast. You can simplify the patch to change the constraint from *km to *kBk Then no renumbering is needed. Uros. > > Thanks, > Uros. > > > --- > > gcc/config/i386/constraints.md | 5 ++ > > gcc/config/i386/i386-protos.h | 1 + > > gcc/config/i386/i386.c | 32 +++++++++ > > gcc/config/i386/i386.md | 18 ++--- > > gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++ > > 5 files changed, 130 insertions(+), 9 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c > > > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md > > index eaa582d2055..15c5950ee6f 100644 > > --- a/gcc/config/i386/constraints.md > > +++ b/gcc/config/i386/constraints.md > > @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc" > > (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")) > > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > > index 7782cf1163f..941e91636d8 100644 > > --- a/gcc/config/i386/i386-protos.h > > +++ b/gcc/config/i386/i386-protos.h > > @@ -240,6 +240,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); > > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > > index 42c47d2b12b..68079e4230e 100644 > > --- a/gcc/config/i386/i386.c > > +++ b/gcc/config/i386/i386.c > > @@ -11468,6 +11468,38 @@ 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. > > + NB: it's different from ix86_tls_address_pattern_p since it also matchs > > + gottpoff/gotntpoff. > > The above NB comment is not needed, the fact is obvious from the code. > > > + 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) > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > > index 97325e38676..82b85b26059 100644 > > --- a/gcc/config/i386/i386.md > > +++ b/gcc/config/i386/i386.md > > @@ -2085,9 +2085,9 @@ (define_split > > > > (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,*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,*k,*Bk,*k,*k,CBC"))] > > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > > && ix86_hardreg_mov_ok (operands[0], operands[1])" > > { > > @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal" > > [(set (attr "isa") > > (cond [(eq_attr "alternative" "0,1,17,18") > > (const_string "nox64") > > - (eq_attr "alternative" "2,3,4,5,10,11,23,25") > > + (eq_attr "alternative" "2,3,4,5,10,11,23,26") > > (const_string "x64") > > (eq_attr "alternative" "19,20") > > (const_string "x64_sse2") > > @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal" > > (const_string "ssemov") > > (eq_attr "alternative" "21,22") > > (const_string "ssecvt") > > - (eq_attr "alternative" "23,24,25,26") > > + (eq_attr "alternative" "23,24,25,26,27") > > (const_string "mskmov") > > - (eq_attr "alternative" "27") > > + (eq_attr "alternative" "28") > > (const_string "msklog") > > (and (match_operand 0 "register_operand") > > (match_operand 1 "pic_32bit_operand")) > > @@ -2306,9 +2306,9 @@ (define_peephole2 > > > > (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 ,*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,*k, *Bk,*k ,CBC"))] > > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > > && ix86_hardreg_mov_ok (operands[0], operands[1])" > > { > > @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal" > > (const_string "sselog1") > > (eq_attr "alternative" "9,10,11,12,13") > > (const_string "ssemov") > > - (eq_attr "alternative" "14,15,16") > > + (eq_attr "alternative" "14,15,16,17") > > (const_string "mskmov") > > - (eq_attr "alternative" "17") > > + (eq_attr "alternative" "18") > > (const_string "msklog") > > (and (match_operand 0 "register_operand") > > (match_operand 1 "pic_32bit_operand")) > > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c > > new file mode 100644 > > index 00000000000..c93413f3cde > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c > > @@ -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; > > +} > > -- > > 2.18.1 > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences. 2021-11-19 7:53 ` Uros Bizjak @ 2021-11-22 3:19 ` Hongtao Liu 0 siblings, 0 replies; 6+ messages in thread From: Hongtao Liu @ 2021-11-22 3:19 UTC (permalink / raw) To: Uros Bizjak; +Cc: liuhongt, gcc-patches [-- Attachment #1: Type: text/plain, Size: 12824 bytes --] On Fri, Nov 19, 2021 at 3:53 PM Uros Bizjak via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > On Fri, Nov 19, 2021 at 8:50 AM Uros Bizjak <ubizjak@gmail.com> wrote: > > > > On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote: > > > > > > >Why is the above declared as a special memory constraint? Also the > > > Change to define_memory_constraint since it's ok for > > > reload can make them match by converting the operand to the form > > > ‘(mem (reg X))’.where X is a base register (from the register class specified > > > by BASE_REG_CLASS > > > > > > >predicate comment is missing and the description should say something > > > >like: > > > > > > > >@internal TLS address that allows insn using non-integer registers > > > Changed. > > > > > > >I think it is better to avoid negative logic. So, something like > > > > > > > >Return true if the TLS address requires insn using integer registers. > > > > > > > >bool > > > >ix86_gpr_tls_address_pattern_p > > > > > > > >(and use not in the predicate) > > > > > > Changed. > > > > > > >> +{ > > > >> + 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 false; > > > >> + case UNSPEC_TPOFF: > > > >> + if (!TARGET_64BIT) > > > >> + return false; > > > >> + break; > > > >> + default: > > > >> + break; > > > >> + } > > > >> + /* Should iter.skip_subrtxes (); > > > >> + if there's no inner UNSPEC in addr???. */ > > > > > > >You should figure the above before submitting the patch. > > > ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so > > > remove comments. > > > > > > >Can you please minimize the testcase? > > > Done; > > > > > > 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/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. > > > > OK, with a small comment adjustment below. > > Ops, sorry, I was too fast. You can simplify the patch to change the > constraint from > > *km to *kBk > > Then no renumbering is needed. Yes, changed, thanks for the review. this is the final patch i'm checking in. > > Uros. > > > > > Thanks, > > Uros. > > > > > --- > > > gcc/config/i386/constraints.md | 5 ++ > > > gcc/config/i386/i386-protos.h | 1 + > > > gcc/config/i386/i386.c | 32 +++++++++ > > > gcc/config/i386/i386.md | 18 ++--- > > > gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++ > > > 5 files changed, 130 insertions(+), 9 deletions(-) > > > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c > > > > > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md > > > index eaa582d2055..15c5950ee6f 100644 > > > --- a/gcc/config/i386/constraints.md > > > +++ b/gcc/config/i386/constraints.md > > > @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc" > > > (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")) > > > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > > > index 7782cf1163f..941e91636d8 100644 > > > --- a/gcc/config/i386/i386-protos.h > > > +++ b/gcc/config/i386/i386-protos.h > > > @@ -240,6 +240,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); > > > > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > > > index 42c47d2b12b..68079e4230e 100644 > > > --- a/gcc/config/i386/i386.c > > > +++ b/gcc/config/i386/i386.c > > > @@ -11468,6 +11468,38 @@ 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. > > > + NB: it's different from ix86_tls_address_pattern_p since it also matchs > > > + gottpoff/gotntpoff. > > > > The above NB comment is not needed, the fact is obvious from the code. > > > > > + 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) > > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > > > index 97325e38676..82b85b26059 100644 > > > --- a/gcc/config/i386/i386.md > > > +++ b/gcc/config/i386/i386.md > > > @@ -2085,9 +2085,9 @@ (define_split > > > > > > (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,*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,*k,*Bk,*k,*k,CBC"))] > > > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > > > && ix86_hardreg_mov_ok (operands[0], operands[1])" > > > { > > > @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal" > > > [(set (attr "isa") > > > (cond [(eq_attr "alternative" "0,1,17,18") > > > (const_string "nox64") > > > - (eq_attr "alternative" "2,3,4,5,10,11,23,25") > > > + (eq_attr "alternative" "2,3,4,5,10,11,23,26") > > > (const_string "x64") > > > (eq_attr "alternative" "19,20") > > > (const_string "x64_sse2") > > > @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal" > > > (const_string "ssemov") > > > (eq_attr "alternative" "21,22") > > > (const_string "ssecvt") > > > - (eq_attr "alternative" "23,24,25,26") > > > + (eq_attr "alternative" "23,24,25,26,27") > > > (const_string "mskmov") > > > - (eq_attr "alternative" "27") > > > + (eq_attr "alternative" "28") > > > (const_string "msklog") > > > (and (match_operand 0 "register_operand") > > > (match_operand 1 "pic_32bit_operand")) > > > @@ -2306,9 +2306,9 @@ (define_peephole2 > > > > > > (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 ,*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,*k, *Bk,*k ,CBC"))] > > > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > > > && ix86_hardreg_mov_ok (operands[0], operands[1])" > > > { > > > @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal" > > > (const_string "sselog1") > > > (eq_attr "alternative" "9,10,11,12,13") > > > (const_string "ssemov") > > > - (eq_attr "alternative" "14,15,16") > > > + (eq_attr "alternative" "14,15,16,17") > > > (const_string "mskmov") > > > - (eq_attr "alternative" "17") > > > + (eq_attr "alternative" "18") > > > (const_string "msklog") > > > (and (match_operand 0 "register_operand") > > > (match_operand 1 "pic_32bit_operand")) > > > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c > > > new file mode 100644 > > > index 00000000000..c93413f3cde > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c > > > @@ -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; > > > +} > > > -- > > > 2.18.1 > > > -- BR, Hongtao [-- Attachment #2: 0001-Don-t-allow-mask-sse-mmx-mov-in-TLS-code-sequences.patch --] [-- Type: application/octet-stream, Size: 6954 bytes --] From 800ad44384286aca170b20f9f10aaf7076aeacbc Mon Sep 17 00:00:00 2001 From: liuhongt <hongtao.liu@intel.com> Date: Wed, 17 Nov 2021 15:48:37 +0800 Subject: [PATCH] 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. --- gcc/config/i386/constraints.md | 5 ++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 30 +++++++++ gcc/config/i386/i386.md | 8 +-- gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index eaa582d2055..15c5950ee6f 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc" (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")) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 7782cf1163f..941e91636d8 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -240,6 +240,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); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 42c47d2b12b..1448f3609c3 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11468,6 +11468,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) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 97325e38676..54c32cb3228 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2085,9 +2085,9 @@ (define_split (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])" { @@ -2306,9 +2306,9 @@ (define_peephole2 (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])" { diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c new file mode 100644 index 00000000000..c93413f3cde --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103275.c @@ -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; +} -- 2.18.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-11-22 3:19 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-11-18 7:18 [PATCH] Don't allow mask/sse/mmx mov in TLS code sequences liuhongt 2021-11-18 8:19 ` Uros Bizjak 2021-11-19 1:14 ` liuhongt 2021-11-19 7:50 ` Uros Bizjak 2021-11-19 7:53 ` Uros Bizjak 2021-11-22 3:19 ` Hongtao Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).