public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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).