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