On Sun, Jan 19, 2020 at 12:01 PM Uros Bizjak <ubiz...@gmail.com> wrote:
>
> On Sun, Jan 19, 2020 at 7:07 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> >
> > On Sun, Jan 19, 2020 at 9:48 AM Uros Bizjak <ubiz...@gmail.com> wrote:
> > >
> > > On Sun, Jan 19, 2020 at 6:43 PM Uros Bizjak <ubiz...@gmail.com> wrote:
> > > >
> > > > On Sun, Jan 19, 2020 at 2:58 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> > > > >
> > > > > To add x32 support to -mtls-dialect=gnu2, we need to replace DI with
> > > > > P in GNU2 TLS patterns.  Since thread pointer is in ptr_mode, PLUS in
> > > > > GNU2 TLS address computation must be done in ptr_mode to support
> > > > > -maddress-mode=long.  Also drop the "q" suffix from lea to support
> > > > > both "lea foo@TLSDESC(%rip), %eax" and "foo@TLSDESC(%rip), %rax".
> > > >
> > > > Please use "lea%z0" instead.
> > > >
> > > > > Tested on Linux/x86-64.  OK for master?
> > > > >
> > > > > Thanks.
> > > > >
> > > > > H.J.
> > > > > ---
> > > > > gcc/
> > > > >
> > > > >         PR target/93319
> > > > >         * config/i386/i386.c (legitimize_tls_address): Pass Pmode to
> > > > >         gen_tls_dynamic_gnu2_64.  Compute GNU2 TLS address in 
> > > > > ptr_mode.
> > > > >         * config/i386/i386.md (tls_dynamic_gnu2_64): Renamed to ...
> > > > >         (@tls_dynamic_gnu2_64_<mode>): This.  Replace DI with P.
> > > > >         (*tls_dynamic_gnu2_lea_64): Renamed to ...
> > > > >         (*tls_dynamic_gnu2_lea_64_<mode>): This.  Replace DI with P.
> > > > >         Remove the {q} suffix from lea.
> > > > >         (*tls_dynamic_gnu2_call_64): Renamed to ...
> > > > >         (*tls_dynamic_gnu2_call_64_<mode>): This.  Replace DI with P.
> > > > >         (*tls_dynamic_gnu2_combine_64): Renamed to ...
> > > > >         (*tls_dynamic_gnu2_combine_64_<mode>): This.  Replace DI with 
> > > > > P.
> > > > >         Pass Pmode to gen_tls_dynamic_gnu2_64.
> > > > >
> > > > > gcc/testsuite/
> > > > >
> > > > >         PR target/93319
> > > > >         * gcc.target/i386/pr93319-1a.c: New test.
> > > > >         * gcc.target/i386/pr93319-1b.c: Likewise.
> > > > >         * gcc.target/i386/pr93319-1c.c: Likewise.
> > > > >         * gcc.target/i386/pr93319-1d.c: Likewise.
> > > > > ---
> > > > >  gcc/config/i386/i386.c                     | 31 +++++++++++--
> > > > >  gcc/config/i386/i386.md                    | 54 
> > > > > +++++++++++-----------
> > > > >  gcc/testsuite/gcc.target/i386/pr93319-1a.c | 24 ++++++++++
> > > > >  gcc/testsuite/gcc.target/i386/pr93319-1b.c |  7 +++
> > > > >  gcc/testsuite/gcc.target/i386/pr93319-1c.c |  7 +++
> > > > >  gcc/testsuite/gcc.target/i386/pr93319-1d.c |  7 +++
> > > > >  6 files changed, 99 insertions(+), 31 deletions(-)
> > > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1a.c
> > > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1b.c
> > > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1c.c
> > > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1d.c
> > > > >
> > > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > > > index 2c087a4a3e0..8c437dbe1f3 100644
> > > > > --- a/gcc/config/i386/i386.c
> > > > > +++ b/gcc/config/i386/i386.c
> > > > > @@ -10764,12 +10764,24 @@ legitimize_tls_address (rtx x, enum 
> > > > > tls_model model, bool for_mov)
> > > > >        if (TARGET_GNU2_TLS)
> > > > >         {
> > > > >           if (TARGET_64BIT)
> > > > > -           emit_insn (gen_tls_dynamic_gnu2_64 (dest, x));
> > > > > +           emit_insn (gen_tls_dynamic_gnu2_64 (Pmode, dest, x));
> > > > >           else
> > > > >             emit_insn (gen_tls_dynamic_gnu2_32 (dest, x, pic));
> > > > >
> > > > >           tp = get_thread_pointer (Pmode, true);
> > > > > -         dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
> > > > > +
> > > > > +         /* NB: Since thread pointer is in ptr_mode, make sure that
> > > > > +            PLUS is done in ptr_mode.  */
> > >
> > > Actually, thread_pointer is in Pmode, see the line just above your
> > > change. Also, dest is in Pmode, so why do we need all this subreg
> > > dance?
> >
> > dest set from  gen_tls_dynamic_gnu2_64 is in ptr_mode by
> >
> > call *foo@TLSCALL(%rax)
>
> It looks to me that we have Pmode/ptr_mode mixup in
> legitimize_tls_address & friends for TARGET_GNU2_TLS. I think that we
> need to perform all calculations in ptr_mode, since get_thread_pointer
> in effect always returns ptr_mode (SImode) value, and also the above
> call always returns ptr_mode (SImode) value. In case of
> -maddress-mode=long, the value would be zero-extended to Pmode.
>

The problem is with tls_dynamic_gnu2_64 which generates

call *foo@TLSCALL(%rax)

It always returns a 32-bit index.  I can change get_thread_pointer if
needed.

Here is the updated patch with "lea%z0" and updated comments.

-- 
H.J.
From 6be0be4176337744ba89d7ce0496b7fb3de175bb Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Sat, 18 Jan 2020 10:20:29 -0800
Subject: [PATCH] x32: Add x32 support to -mtls-dialect=gnu2

To add x32 support to -mtls-dialect=gnu2, we need to replace DI with
P in GNU2 TLS patterns.  Since DEST set by tls_dynamic_gnu2_64 is in
ptr_mode, PLUS in GNU2 TLS address computation must be done in ptr_mode
to support -maddress-mode=long.  Also replace the "{q}" suffix on lea
with "%z0" to support both 32-bit and 64-bit destination register.

Tested on Linux/x86-64.

gcc/

	PR target/93319
	* config/i386/i386.c (legitimize_tls_address): Pass Pmode to
	gen_tls_dynamic_gnu2_64.  Compute GNU2 TLS address in ptr_mode.
	* config/i386/i386.md (tls_dynamic_gnu2_64): Renamed to ...
	(@tls_dynamic_gnu2_64_<mode>): This.  Replace DI with P.
	(*tls_dynamic_gnu2_lea_64): Renamed to ...
	(*tls_dynamic_gnu2_lea_64_<mode>): This.  Replace DI with P.
	Remove the {q} suffix from lea.
	(*tls_dynamic_gnu2_call_64): Renamed to ...
	(*tls_dynamic_gnu2_call_64_<mode>): This.  Replace DI with P.
	(*tls_dynamic_gnu2_combine_64): Renamed to ...
	(*tls_dynamic_gnu2_combine_64_<mode>): This.  Replace DI with P.
	Pass Pmode to gen_tls_dynamic_gnu2_64.

gcc/testsuite/

	PR target/93319
	* gcc.target/i386/pr93319-1a.c: New test.
	* gcc.target/i386/pr93319-1b.c: Likewise.
	* gcc.target/i386/pr93319-1c.c: Likewise.
	* gcc.target/i386/pr93319-1d.c: Likewise.
---
 gcc/config/i386/i386.c                     | 31 +++++++++++--
 gcc/config/i386/i386.md                    | 54 +++++++++++-----------
 gcc/testsuite/gcc.target/i386/pr93319-1a.c | 24 ++++++++++
 gcc/testsuite/gcc.target/i386/pr93319-1b.c |  7 +++
 gcc/testsuite/gcc.target/i386/pr93319-1c.c |  7 +++
 gcc/testsuite/gcc.target/i386/pr93319-1d.c |  7 +++
 6 files changed, 99 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1c.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93319-1d.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2c087a4a3e0..9b819a95bc2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10764,12 +10764,24 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
       if (TARGET_GNU2_TLS)
 	{
 	  if (TARGET_64BIT)
-	    emit_insn (gen_tls_dynamic_gnu2_64 (dest, x));
+	    emit_insn (gen_tls_dynamic_gnu2_64 (Pmode, dest, x));
 	  else
 	    emit_insn (gen_tls_dynamic_gnu2_32 (dest, x, pic));
 
 	  tp = get_thread_pointer (Pmode, true);
-	  dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
+
+	  /* NB: Since DEST set by tls_dynamic_gnu2_64 is in ptr_mode,
+	     make sure that PLUS is done in ptr_mode.  */
+	  if (0 && Pmode != ptr_mode)
+	    {
+	      tp = lowpart_subreg (ptr_mode, tp, Pmode);
+	      dest = lowpart_subreg (ptr_mode, dest, Pmode);
+	      dest = gen_rtx_PLUS (ptr_mode, tp, dest);
+	      dest = gen_rtx_ZERO_EXTEND (Pmode, dest);
+	    }
+	  else
+	    dest = gen_rtx_PLUS (Pmode, tp, dest);
+	  dest = force_reg (Pmode, dest);
 
 	  if (GET_MODE (x) != Pmode)
 	    x = gen_rtx_ZERO_EXTEND (Pmode, x);
@@ -10821,7 +10833,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
 	  rtx tmp = ix86_tls_module_base ();
 
 	  if (TARGET_64BIT)
-	    emit_insn (gen_tls_dynamic_gnu2_64 (base, tmp));
+	    emit_insn (gen_tls_dynamic_gnu2_64 (Pmode, base, tmp));
 	  else
 	    emit_insn (gen_tls_dynamic_gnu2_32 (base, tmp, pic));
 
@@ -10864,7 +10876,18 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
 
       if (TARGET_GNU2_TLS)
 	{
-	  dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, dest, tp));
+	  /* NB: Since DEST set by tls_dynamic_gnu2_64 is in ptr_mode,
+	     make sure that PLUS is done in ptr_mode.  */
+	  if (Pmode != ptr_mode)
+	    {
+	      tp = lowpart_subreg (ptr_mode, tp, Pmode);
+	      dest = lowpart_subreg (ptr_mode, dest, Pmode);
+	      dest = gen_rtx_PLUS (ptr_mode, tp, dest);
+	      dest = gen_rtx_ZERO_EXTEND (Pmode, dest);
+	    }
+	  else
+	    dest = gen_rtx_PLUS (Pmode, tp, dest);
+	  dest = force_reg (Pmode, dest);
 
 	  if (GET_MODE (x) != Pmode)
 	    x = gen_rtx_ZERO_EXTEND (Pmode, x);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index c9d2f338fe9..de335cb8f02 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -15185,14 +15185,14 @@ (define_insn_and_split "*tls_dynamic_gnu2_combine_32"
   emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
 })
 
-(define_expand "tls_dynamic_gnu2_64"
+(define_expand "@tls_dynamic_gnu2_64_<mode>"
   [(set (match_dup 2)
-	(unspec:DI [(match_operand 1 "tls_symbolic_operand")]
-		   UNSPEC_TLSDESC))
+	(unspec:P [(match_operand 1 "tls_symbolic_operand")]
+		  UNSPEC_TLSDESC))
    (parallel
-    [(set (match_operand:DI 0 "register_operand")
-	  (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
-		     UNSPEC_TLSDESC))
+    [(set (match_operand:P 0 "register_operand")
+	  (unspec:P [(match_dup 1) (match_dup 2) (reg:P SP_REG)]
+		    UNSPEC_TLSDESC))
      (clobber (reg:CC FLAGS_REG))])]
   "TARGET_64BIT && TARGET_GNU2_TLS"
 {
@@ -15200,23 +15200,23 @@ (define_expand "tls_dynamic_gnu2_64"
   ix86_tls_descriptor_calls_expanded_in_cfun = true;
 })
 
-(define_insn "*tls_dynamic_gnu2_lea_64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(unspec:DI [(match_operand 1 "tls_symbolic_operand")]
-		   UNSPEC_TLSDESC))]
+(define_insn "*tls_dynamic_gnu2_lea_64_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+	(unspec:P [(match_operand 1 "tls_symbolic_operand")]
+		  UNSPEC_TLSDESC))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
-  "lea{q}\t{%E1@TLSDESC(%%rip), %0|%0, %E1@TLSDESC[rip]}"
+  "lea%z0\t{%E1@TLSDESC(%%rip), %0|%0, %E1@TLSDESC[rip]}"
   [(set_attr "type" "lea")
-   (set_attr "mode" "DI")
+   (set_attr "mode" "<MODE>")
    (set_attr "length" "7")
    (set_attr "length_address" "4")])
 
-(define_insn "*tls_dynamic_gnu2_call_64"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(unspec:DI [(match_operand 1 "tls_symbolic_operand")
-		    (match_operand:DI 2 "register_operand" "0")
-		    (reg:DI SP_REG)]
-		   UNSPEC_TLSDESC))
+(define_insn "*tls_dynamic_gnu2_call_64_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=a")
+	(unspec:P [(match_operand 1 "tls_symbolic_operand")
+		   (match_operand:P 2 "register_operand" "0")
+		   (reg:P SP_REG)]
+		  UNSPEC_TLSDESC))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
   "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
@@ -15224,14 +15224,14 @@ (define_insn "*tls_dynamic_gnu2_call_64"
    (set_attr "length" "2")
    (set_attr "length_address" "0")])
 
-(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
-  [(set (match_operand:DI 0 "register_operand" "=&a")
-	(plus:DI
-	 (unspec:DI [(match_operand 2 "tls_modbase_operand")
-		     (match_operand:DI 3)
-		     (reg:DI SP_REG)]
-		    UNSPEC_TLSDESC)
-	 (const:DI (unspec:DI
+(define_insn_and_split "*tls_dynamic_gnu2_combine_64_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=&a")
+	(plus:P
+	 (unspec:P [(match_operand 2 "tls_modbase_operand")
+		     (match_operand:P 3)
+		     (reg:P SP_REG)]
+		   UNSPEC_TLSDESC)
+	 (const:P (unspec:P
 		    [(match_operand 1 "tls_symbolic_operand")]
 		    UNSPEC_DTPOFF))))
    (clobber (reg:CC FLAGS_REG))]
@@ -15241,7 +15241,7 @@ (define_insn_and_split "*tls_dynamic_gnu2_combine_64"
   [(set (match_dup 0) (match_dup 4))]
 {
   operands[4] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0];
-  emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
+  emit_insn (gen_tls_dynamic_gnu2_64 (Pmode, operands[4], operands[1]));
 })
 
 (define_split
diff --git a/gcc/testsuite/gcc.target/i386/pr93319-1a.c b/gcc/testsuite/gcc.target/i386/pr93319-1a.c
new file mode 100644
index 00000000000..8f6b4af3225
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-mx32 -fPIC -mtls-dialect=gnu2" } */
+
+#include <stdio.h>
+
+extern __thread int bar;
+static __thread int foo = 30;
+
+int *
+test1 (void)
+{
+  printf ("foo: %d\n", foo);
+  return &foo;
+}
+
+int *
+test2 (void)
+{
+  printf ("bar: %d\n", bar);
+  return &bar;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr93319-1b.c b/gcc/testsuite/gcc.target/i386/pr93319-1b.c
new file mode 100644
index 00000000000..f28cc557884
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1b.c
@@ -0,0 +1,7 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-mx32 -O2 -fPIC -mtls-dialect=gnu2" } */
+
+#include "pr93319-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr93319-1c.c b/gcc/testsuite/gcc.target/i386/pr93319-1c.c
new file mode 100644
index 00000000000..2ae0d99b2e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1c.c
@@ -0,0 +1,7 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-mx32 -O2 -fPIC -mtls-dialect=gnu2 -maddress-mode=long" } */
+
+#include "pr93319-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr93319-1d.c b/gcc/testsuite/gcc.target/i386/pr93319-1d.c
new file mode 100644
index 00000000000..feb378d2971
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1d.c
@@ -0,0 +1,7 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-mx32 -fPIC -mtls-dialect=gnu2 -maddress-mode=long" } */
+
+#include "pr93319-1a.c"
-- 
2.24.1

Reply via email to