x32: Add x32 support to -mtls-dialect=gnu2
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 20 Jan 2020 13:02:14 +0000 (05:02 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 20 Jan 2020 13:14:16 +0000 (05:14 -0800)
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/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr93319-1a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr93319-1b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr93319-1c.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr93319-1d.c [new file with mode: 0644]

index ce26404..5ae2773 100644 (file)
@@ -1,3 +1,19 @@
+2020-01-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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.
+
 2020-01-20  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * config/aarch64/aarch64.h (SLOW_BYTE_ACCESS): Set to 1.
index 2c087a4..0b8a4b9 100644 (file)
@@ -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 (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);
index c9d2f33..de335cb 100644 (file)
   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"
 {
   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]]}"
    (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))]
   [(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
index 220485b..d8bf313 100644 (file)
@@ -1,3 +1,11 @@
+2020-01-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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.
+
 2020-01-20  Richard Biener  <rguenther@suse.de>
 
        PR debug/92763
diff --git a/gcc/testsuite/gcc.target/i386/pr93319-1a.c b/gcc/testsuite/gcc.target/i386/pr93319-1a.c
new file mode 100644 (file)
index 0000000..8f6b4af
--- /dev/null
@@ -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 (file)
index 0000000..f28cc55
--- /dev/null
@@ -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 (file)
index 0000000..2ae0d99
--- /dev/null
@@ -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 (file)
index 0000000..feb378d
--- /dev/null
@@ -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"