diff mbox

Re: [AArch64][TLSGD][2/2] Implement TLS GD traditional for tiny code model

Message ID 563B6E62.20900@foss.arm.com
State New
Headers show

Commit Message

Jiong Wang Nov. 5, 2015, 2:57 p.m. UTC
Marcus Shawcroft writes:

> +#ifdef HAVE_AS_TINY_TLSGD_RELOCS
> +  return SYMBOL_TINY_TLSGD;
> +#else
> +  return SYMBOL_SMALL_TLSGD;
> +#endif
>
> Rather than introduce blocks of conditional compilation it is better
> to gate different behaviours with a test on a constant expression. In
> this case add something like this:
>
> #if define(HAVE_AS_TINY_TLSGD_RELOCS)
> #define USE_TINY_TLSGD 1
> #else
> #define USE_TINY_TLSGD 0
> #endif
>
> up near the definition of TARGET_HAVE_TLS then write the above
> fragment without using the preprocessor:
>
> return USE_TINY_TLSGD ? SYMBOL_TINY_TLSGD : SYMBOL_SMALL_TLSGD;

Done.

> - aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
> + if (type == SYMBOL_SMALL_TLSGD)
> +  aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
> + else
> +  aarch64_emit_call_insn (gen_tlsgd_tiny (result, imm, resolver));
>   insns = get_insns ();
>   end_sequence ();
>
> Add a separate case statment for SYMBOL_TINY_TLSGD rather than reusing
> the case statement for SYMBOL_SMALL_TLSGD and then needing to add
> another test against symbol type within the body of the case
> statement.

Done.

>
> +(define_insn "tlsgd_tiny"
> +  [(set (match_operand 0 "register_operand" "")
> + (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
> +   (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
> UNSPEC_GOTTINYTLS)
> +   (clobber (reg:DI LR_REGNUM))
> +  ]
> +  ""
> +  "adr\tx0, %A1;bl\t%2;nop";
> +  [(set_attr "type" "multiple")
> +   (set_attr "length" "12")])
>
> I don't think the explicit clobber LR_REGNUM is required since your
> change last September:
> https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02654.html

We don't need this explict clobber LR_REGNUM only if operand 0 happen
be allocated to LR_REGNUM as after my above patch LR_REGNUM is allocable.

However we still need the explict clobber here.  Because for all other
cases LR_REGNUM not allocated, gcc data flow analysis can't deduct LR_REGNUM
will still be clobbered implicitly by the call instruction.

Without this "clobber" tag, a direct impact is df_regs_ever_live is calculated
incorrectly for x30, then for the following simple testcase:

__thread int t0 = 0x10;
__thread int t1 = 0x10;

int
main (int argc, char **argv)
{
   if (t0 != t1)
     return 1;
   return  0;
}


if you compile with

  "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad t.c -mcmodel=tiny -fomit-frame-pointer",
wrong code will be generated:

  main:
         str     x19, [sp, -16]!  <--- x30 is not saved.
         adr     x0, :tlsgd:t0
         bl __tls_get_addr
         nop

Patch updated. tls regression OK

OK for trunk?

2015-11-05  Jiong Wang  <jiong.wang@arm.com>

gcc/
   * configure.ac: Add check for binutils global dynamic tiny code model
   relocation support.
   * configure: Regenerate.
   * config.in: Regenerate.
   * config/aarch64/aarch64.md (tlsgd_tiny): New define_insn.
   * config/aarch64/aarch64-protos.h (aarch64_symbol_type): New
   enumeration SYMBOL_TINY_TLSGD.
   (aarch64_symbol_context): New comment on SYMBOL_TINY_TLSGD.
   * config/aarch64/aarch64.c (aarch64_classify_tls_symbol): Support
   SYMBOL_TINY_TLSGD.
   (aarch64_print_operand): Likewise.
   (aarch64_expand_mov_immediate): Likewise.
   (aarch64_load_symref_appropriately): Likewise.

gcc/testsuite/
   * lib/target-supports.exp (check_effective_target_aarch64_tlsgdtiny):
   New effective check.
   * gcc.target/aarch64/tlsgd_small_1.c: New testcase.
   * gcc.target/aarch64/tlsgd_small_ilp32_1.c: Likewise.
   * gcc.target/aarch64/tlsgd_tiny_1.c: Likewise.
   * gcc.target/aarch64/tlsgd_tiny_ilp32_1.c: Likewise.

Comments

Jiong Wang Nov. 13, 2015, 3:21 p.m. UTC | #1
On 05/11/15 14:57, Jiong Wang wrote:
> Marcus Shawcroft writes:
>
>> +#ifdef HAVE_AS_TINY_TLSGD_RELOCS
>> +  return SYMBOL_TINY_TLSGD;
>> +#else
>> +  return SYMBOL_SMALL_TLSGD;
>> +#endif
>>
>> Rather than introduce blocks of conditional compilation it is better
>> to gate different behaviours with a test on a constant expression. In
>> this case add something like this:
>>
>> #if define(HAVE_AS_TINY_TLSGD_RELOCS)
>> #define USE_TINY_TLSGD 1
>> #else
>> #define USE_TINY_TLSGD 0
>> #endif
>>
>> up near the definition of TARGET_HAVE_TLS then write the above
>> fragment without using the preprocessor:
>>
>> return USE_TINY_TLSGD ? SYMBOL_TINY_TLSGD : SYMBOL_SMALL_TLSGD;
>
> Done.
>
>> - aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
>> + if (type == SYMBOL_SMALL_TLSGD)
>> +  aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
>> + else
>> +  aarch64_emit_call_insn (gen_tlsgd_tiny (result, imm, resolver));
>>   insns = get_insns ();
>>   end_sequence ();
>>
>> Add a separate case statment for SYMBOL_TINY_TLSGD rather than reusing
>> the case statement for SYMBOL_SMALL_TLSGD and then needing to add
>> another test against symbol type within the body of the case
>> statement.
>
> Done.
>
>>
>> +(define_insn "tlsgd_tiny"
>> +  [(set (match_operand 0 "register_operand" "")
>> + (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
>> +   (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
>> UNSPEC_GOTTINYTLS)
>> +   (clobber (reg:DI LR_REGNUM))
>> +  ]
>> +  ""
>> +  "adr\tx0, %A1;bl\t%2;nop";
>> +  [(set_attr "type" "multiple")
>> +   (set_attr "length" "12")])
>>
>> I don't think the explicit clobber LR_REGNUM is required since your
>> change last September:
>> https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02654.html
>
> We don't need this explict clobber LR_REGNUM only if operand 0 happen
> be allocated to LR_REGNUM as after my above patch LR_REGNUM is allocable.
>
> However we still need the explict clobber here.  Because for all other
> cases LR_REGNUM not allocated, gcc data flow analysis can't deduct 
> LR_REGNUM
> will still be clobbered implicitly by the call instruction.
>
> Without this "clobber" tag, a direct impact is df_regs_ever_live is 
> calculated
> incorrectly for x30, then for the following simple testcase:
>
> __thread int t0 = 0x10;
> __thread int t1 = 0x10;
>
> int
> main (int argc, char **argv)
> {
>   if (t0 != t1)
>     return 1;
>   return  0;
> }
>
>
> if you compile with
>
>  "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad t.c 
> -mcmodel=tiny -fomit-frame-pointer",
> wrong code will be generated:
>
>  main:
>         str     x19, [sp, -16]!  <--- x30 is not saved.
>         adr     x0, :tlsgd:t0
>         bl __tls_get_addr
>         nop
>
> Patch updated. tls regression OK
>
> OK for trunk?
>
> 2015-11-05  Jiong Wang  <jiong.wang@arm.com>
>
> gcc/
>   * configure.ac: Add check for binutils global dynamic tiny code model
>   relocation support.
>   * configure: Regenerate.
>   * config.in: Regenerate.
>   * config/aarch64/aarch64.md (tlsgd_tiny): New define_insn.
>   * config/aarch64/aarch64-protos.h (aarch64_symbol_type): New
>   enumeration SYMBOL_TINY_TLSGD.
>   (aarch64_symbol_context): New comment on SYMBOL_TINY_TLSGD.
>   * config/aarch64/aarch64.c (aarch64_classify_tls_symbol): Support
>   SYMBOL_TINY_TLSGD.
>   (aarch64_print_operand): Likewise.
>   (aarch64_expand_mov_immediate): Likewise.
>   (aarch64_load_symref_appropriately): Likewise.
>
> gcc/testsuite/
>   * lib/target-supports.exp (check_effective_target_aarch64_tlsgdtiny):
>   New effective check.
>   * gcc.target/aarch64/tlsgd_small_1.c: New testcase.
>   * gcc.target/aarch64/tlsgd_small_ilp32_1.c: Likewise.
>   * gcc.target/aarch64/tlsgd_tiny_1.c: Likewise.
>   * gcc.target/aarch64/tlsgd_tiny_ilp32_1.c: Likewise.
Ping ~
Jiong Wang Dec. 3, 2015, 10:42 a.m. UTC | #2
On 13/11/15 15:21, Jiong Wang wrote:
>
> On 05/11/15 14:57, Jiong Wang wrote:
>> Marcus Shawcroft writes:
>>
>>> +#ifdef HAVE_AS_TINY_TLSGD_RELOCS
>>> +  return SYMBOL_TINY_TLSGD;
>>> +#else
>>> +  return SYMBOL_SMALL_TLSGD;
>>> +#endif
>>>
>>> Rather than introduce blocks of conditional compilation it is better
>>> to gate different behaviours with a test on a constant expression. In
>>> this case add something like this:
>>>
>>> #if define(HAVE_AS_TINY_TLSGD_RELOCS)
>>> #define USE_TINY_TLSGD 1
>>> #else
>>> #define USE_TINY_TLSGD 0
>>> #endif
>>>
>>> up near the definition of TARGET_HAVE_TLS then write the above
>>> fragment without using the preprocessor:
>>>
>>> return USE_TINY_TLSGD ? SYMBOL_TINY_TLSGD : SYMBOL_SMALL_TLSGD;
>>
>> Done.
>>
>>> - aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
>>> + if (type == SYMBOL_SMALL_TLSGD)
>>> +  aarch64_emit_call_insn (gen_tlsgd_small (result, imm, resolver));
>>> + else
>>> +  aarch64_emit_call_insn (gen_tlsgd_tiny (result, imm, resolver));
>>>   insns = get_insns ();
>>>   end_sequence ();
>>>
>>> Add a separate case statment for SYMBOL_TINY_TLSGD rather than reusing
>>> the case statement for SYMBOL_SMALL_TLSGD and then needing to add
>>> another test against symbol type within the body of the case
>>> statement.
>>
>> Done.
>>
>>>
>>> +(define_insn "tlsgd_tiny"
>>> +  [(set (match_operand 0 "register_operand" "")
>>> + (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
>>> +   (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
>>> UNSPEC_GOTTINYTLS)
>>> +   (clobber (reg:DI LR_REGNUM))
>>> +  ]
>>> +  ""
>>> +  "adr\tx0, %A1;bl\t%2;nop";
>>> +  [(set_attr "type" "multiple")
>>> +   (set_attr "length" "12")])
>>>
>>> I don't think the explicit clobber LR_REGNUM is required since your
>>> change last September:
>>> https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02654.html
>>
>> We don't need this explict clobber LR_REGNUM only if operand 0 happen
>> be allocated to LR_REGNUM as after my above patch LR_REGNUM is 
>> allocable.
>>
>> However we still need the explict clobber here.  Because for all other
>> cases LR_REGNUM not allocated, gcc data flow analysis can't deduct 
>> LR_REGNUM
>> will still be clobbered implicitly by the call instruction.
>>
>> Without this "clobber" tag, a direct impact is df_regs_ever_live is 
>> calculated
>> incorrectly for x30, then for the following simple testcase:
>>
>> __thread int t0 = 0x10;
>> __thread int t1 = 0x10;
>>
>> int
>> main (int argc, char **argv)
>> {
>>   if (t0 != t1)
>>     return 1;
>>   return  0;
>> }
>>
>>
>> if you compile with
>>
>>  "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad t.c 
>> -mcmodel=tiny -fomit-frame-pointer",
>> wrong code will be generated:
>>
>>  main:
>>         str     x19, [sp, -16]!  <--- x30 is not saved.
>>         adr     x0, :tlsgd:t0
>>         bl __tls_get_addr
>>         nop
>>
>> Patch updated. tls regression OK
>>
>> OK for trunk?
>>
>> 2015-11-05  Jiong Wang  <jiong.wang@arm.com>
>>
>> gcc/
>>   * configure.ac: Add check for binutils global dynamic tiny code model
>>   relocation support.
>>   * configure: Regenerate.
>>   * config.in: Regenerate.
>>   * config/aarch64/aarch64.md (tlsgd_tiny): New define_insn.
>>   * config/aarch64/aarch64-protos.h (aarch64_symbol_type): New
>>   enumeration SYMBOL_TINY_TLSGD.
>>   (aarch64_symbol_context): New comment on SYMBOL_TINY_TLSGD.
>>   * config/aarch64/aarch64.c (aarch64_classify_tls_symbol): Support
>>   SYMBOL_TINY_TLSGD.
>>   (aarch64_print_operand): Likewise.
>>   (aarch64_expand_mov_immediate): Likewise.
>>   (aarch64_load_symref_appropriately): Likewise.
>>
>> gcc/testsuite/
>>   * lib/target-supports.exp (check_effective_target_aarch64_tlsgdtiny):
>>   New effective check.
>>   * gcc.target/aarch64/tlsgd_small_1.c: New testcase.
>>   * gcc.target/aarch64/tlsgd_small_ilp32_1.c: Likewise.
>>   * gcc.target/aarch64/tlsgd_tiny_1.c: Likewise.
>>   * gcc.target/aarch64/tlsgd_tiny_ilp32_1.c: Likewise.
> Ping ~

Ping^2
diff mbox

Patch

diff --git a/gcc/config.in b/gcc/config.in
index 093478c..617278f 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -618,6 +618,13 @@ 
 #endif
 
 
+/* Define if your assembler supports relocs needed by global dynamic for tiny
+   code model. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_TINY_TLSGD_RELOCS
+#endif
+
+
 /* Define if your assembler and linker support thread-local storage. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_TLS
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index baaf1bd..9128baa 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -62,6 +62,7 @@ 
    SYMBOL_SMALL_TLSGD
    SYMBOL_SMALL_TLSDESC
    SYMBOL_SMALL_TLSIE
+   SYMBOL_TINY_TLSGD
    SYMBOL_TINY_TLSIE
    SYMBOL_TLSLE12
    SYMBOL_TLSLE24
@@ -103,6 +104,7 @@  enum aarch64_symbol_type
   SYMBOL_SMALL_TLSIE,
   SYMBOL_TINY_ABSOLUTE,
   SYMBOL_TINY_GOT,
+  SYMBOL_TINY_TLSGD,
   SYMBOL_TINY_TLSIE,
   SYMBOL_TLSLE12,
   SYMBOL_TLSLE24,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7e61b16..8c24740 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1042,6 +1042,22 @@  aarch64_load_symref_appropriately (rtx dest, rtx imm,
 	return;
       }
 
+    case SYMBOL_TINY_TLSGD:
+      {
+	rtx_insn *insns;
+	rtx result = gen_rtx_REG (Pmode, R0_REGNUM);
+	rtx resolver = aarch64_tls_get_addr ();
+
+	start_sequence ();
+	aarch64_emit_call_insn (gen_tlsgd_tiny (result, imm, resolver));
+	insns = get_insns ();
+	end_sequence ();
+
+	RTL_CONST_CALL_P (insns) = 1;
+	emit_libcall_block (insns, dest, result, imm);
+	return;
+      }
+
     case SYMBOL_SMALL_TLSGD:
       {
 	rtx_insn *insns;
@@ -1573,6 +1589,7 @@  aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	case SYMBOL_SMALL_GOT_28K:
 	case SYMBOL_SMALL_GOT_4G:
 	case SYMBOL_TINY_GOT:
+	case SYMBOL_TINY_TLSGD:
 	case SYMBOL_TINY_TLSIE:
 	  if (offset != const0_rtx)
 	    {
@@ -4426,6 +4443,7 @@  aarch64_print_operand (FILE *f, rtx x, char code)
 	  break;
 
 	case SYMBOL_SMALL_TLSGD:
+	case SYMBOL_TINY_TLSGD:
 	  asm_fprintf (asm_out_file, ":tlsgd:");
 	  break;
 
@@ -8695,6 +8713,23 @@  aarch64_classify_tls_symbol (rtx x)
   switch (tls_kind)
     {
     case TLS_MODEL_GLOBAL_DYNAMIC:
+      if (TARGET_TLS_DESC)
+      return SYMBOL_SMALL_TLSDESC;
+
+      /* Traditional model.  */
+      switch (aarch64_cmodel)
+      {
+#ifdef HAVE_AS_TINY_TLSGD_RELOCS
+#define USE_TINY_TLSGD 1
+#else
+#define USE_TINY_TLSGD 0
+#endif
+      case AARCH64_CMODEL_TINY:
+      case AARCH64_CMODEL_TINY_PIC:
+	  return USE_TINY_TLSGD ? SYMBOL_TINY_TLSGD : SYMBOL_SMALL_TLSGD;
+      default:
+	  return SYMBOL_SMALL_TLSGD;
+      }
     case TLS_MODEL_LOCAL_DYNAMIC:
       return TARGET_TLS_DESC ? SYMBOL_SMALL_TLSDESC : SYMBOL_SMALL_TLSGD;
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index a80213d..b87730d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4688,6 +4688,17 @@ 
   [(set_attr "type" "call")
    (set_attr "length" "16")])
 
+(define_insn "tlsgd_tiny"
+  [(set (match_operand 0 "register_operand" "")
+  (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
+   (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] UNSPEC_GOTTINYTLS)
+   (clobber (reg:DI LR_REGNUM))
+  ]
+  ""
+  "adr\tx0, %A1;bl\t%2;nop";
+  [(set_attr "type" "multiple")
+   (set_attr "length" "12")])
+
 (define_insn "tlsie_small_<mode>"
   [(set (match_operand:PTR 0 "register_operand" "=r")
         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
diff --git a/gcc/configure b/gcc/configure
index f6ae9906..6b7772a 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24388,6 +24388,41 @@  if test $gcc_cv_as_aarch64_picreloc = yes; then
 $as_echo "#define HAVE_AS_SMALL_PIC_RELOCS 1" >>confdefs.h
 
 fi
+    # Check if we have binutils support for relocations types needed by TLSGD
+    # for tiny code model.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for global dynamic for tiny relocs" >&5
+$as_echo_n "checking assembler for global dynamic for tiny relocs... " >&6; }
+if test "${gcc_cv_as_aarch64_gdtinyreloc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_aarch64_gdtinyreloc=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '
+    .text
+    adr x0, :tlsgd:globalsym
+    ' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+    gcc_cv_as_aarch64_gdtinyreloc=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_aarch64_gdtinyreloc" >&5
+$as_echo "$gcc_cv_as_aarch64_gdtinyreloc" >&6; }
+if test $gcc_cv_as_aarch64_gdtinyreloc = yes; then
+
+$as_echo "#define HAVE_AS_TINY_TLSGD_RELOCS 1" >>confdefs.h
+
+fi
     # Enable default workaround for AArch64 Cortex-A53 erratum 835769.
     # Check whether --enable-fix-cortex-a53-835769 was given.
 if test "${enable_fix_cortex_a53_835769+set}" = set; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 88fb9bf..7ba497c 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3637,6 +3637,14 @@  case "$target" in
 	ldr     x0, [[x2, #:gotpage_lo15:globalsym]]
     ],,[AC_DEFINE(HAVE_AS_SMALL_PIC_RELOCS, 1,
 	[Define if your assembler supports relocs needed by -fpic.])])
+    # Check if we have binutils support for relocations types needed by TLSGD
+    # for tiny code model.
+    gcc_GAS_CHECK_FEATURE([global dynamic for tiny relocs], gcc_cv_as_aarch64_gdtinyreloc,,,
+    [
+    .text
+    adr x0, :tlsgd:globalsym
+    ],,[AC_DEFINE(HAVE_AS_TINY_TLSGD_RELOCS, 1,
+    [Define if your assembler supports relocs needed by global dynamic for tiny code model.])])
     # Enable default workaround for AArch64 Cortex-A53 erratum 835769.
     AC_ARG_ENABLE(fix-cortex-a53-835769,
     [
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsgd_small_1.c b/gcc/testsuite/gcc.target/aarch64/tlsgd_small_1.c
new file mode 100644
index 0000000..6fba678
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsgd_small_1.c
@@ -0,0 +1,9 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad --save-temps" } */
+/* { dg-skip-if "TLS GD for small" { aarch64*-*-* }  { "-mcmodel=tiny" "-mcmodel=large" } { "" } } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, :tlsgd:" 2 } } */
+/* { dg-final { scan-assembler-times "bl\t__tls_get_addr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsgd_small_ilp32_1.c b/gcc/testsuite/gcc.target/aarch64/tlsgd_small_ilp32_1.c
new file mode 100644
index 0000000..1b189a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsgd_small_ilp32_1.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad -mabi=ilp32 --save-temps" } */
+/* { dg-skip-if "TLS GD for small" { aarch64*-*-* }  { "-mcmodel=tiny" "-mcmodel=large" } { "" } } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, :tlsgd:" 2 } } */
+/* { dg-final { scan-assembler-times "bl\t__tls_get_addr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_1.c b/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_1.c
new file mode 100644
index 0000000..1a1053d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_1.c
@@ -0,0 +1,10 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target aarch64_tlsgdtiny } */
+/* { dg-options "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad -mcmodel=tiny --save-temps" } */
+/* { dg-skip-if "TLS GD for tiny" { aarch64*-*-* }  { "-mcmodel=small" "-mcmodel=large" } { "" } } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "adr\tx\[0-9\]+, :tlsgd:" 2 } } */
+/* { dg-final { scan-assembler-times "bl\t__tls_get_addr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_ilp32_1.c b/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_ilp32_1.c
new file mode 100644
index 0000000..df00c60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsgd_tiny_ilp32_1.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target aarch64_tlsgdtiny } */
+/* { dg-options "-O2 -ftls-model=global-dynamic -fpic -mtls-dialect=trad -mcmodel=tiny -mabi=ilp32 --save-temps" } */
+/* { dg-skip-if "TLS GD for tiny" { aarch64*-*-* }  { "-mcmodel=small" "-mcmodel=large" } { "" } } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "adr\tx\[0-9\]+, :tlsgd:" 2 } } */
+/* { dg-final { scan-assembler-times "bl\t__tls_get_addr" 2 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 9057a27..1c6f2f7 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1023,6 +1023,19 @@  proc check_effective_target_aarch64_tlsle32 { } {
     }
 }
 
+# On AArch64, instruction sequence for TLS GD on tiny code model will utilize
+# the relocation modifier ":tlsgd:" together with ADR, it's only supported
+# in binutils higher than 2.25.
+
+proc check_effective_target_aarch64_tlsgdtiny { } {
+    if { [istarget aarch64*-*-*] } {
+    return [check_no_compiler_messages aarch64_tlsgdtiny object {
+        void foo (void) { asm ("adr x1,:tlsgd:t1"); }
+	 }]
+    } else {
+    return 0
+    }
+}
 # Return 1 if -shared is supported, as in no warnings or errors
 # emitted, 0 otherwise.