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".

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.  */
+         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);
@@ -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 thread pointer 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..d53684096c4 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\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..ba9d2b618c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { 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..788796a9a94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1b.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { 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..8c462e904bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1c.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { 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..7989e1c9fd4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93319-1d.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { 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