Marcus Shawcroft writes:

> On 21 May 2015 at 17:49, Jiong Wang <jiong.w...@arm.com> wrote:
>
>> 2015-05-14  Jiong Wang  <jiong.w...@arm.com>
>> gcc/
>>   * config/aarch64/aarch64.c (aarch64_print_operand): Support tls_size.
>>   * config/aarch64/aarch64.md (tlsle): Choose proper instruction
>>   sequences.
>>   (tlsle_<mode>): New define_insn.
>>   (tlsle_movsym_<mode>): Ditto.
>>   * config/aarch64/constraints.md (Uta): New constraint.
>>   (Utb): Ditto.
>>   (Utc): Ditto.
>>   (Utd): Ditto.
>>
>> gcc/testsuite/
>>   * gcc.target/aarch64/tlsle.c: New test source.
>>   * gcc.target/aarch64/tlsle12.c: New testcase.
>>   * gcc.target/aarch64/tlsle24.c: New testcase.
>>   * gcc.target/aarch64/tlsle32.c: New testcase.
>>
>
>
>   case SYMBOL_TLSLE:
> -  asm_fprintf (asm_out_file, ":tprel_lo12_nc:");
> +  if (aarch64_tls_size <= 12)
> +    /* Make sure TLS offset fit into 12bit.  */
> +    asm_fprintf (asm_out_file, ":tprel_lo12:");
> +  else
> +    asm_fprintf (asm_out_file, ":tprel_lo12_nc:");
>    break;
>
> Use the existing classify_symbol mechanism we use throughout the
> aarch64 backend.  Specifically rename SYMBOL_TLSLE as SYMBOL_TLSLE24
> and introduce the 3 missing flavours then use the symbol
> classification to control behaviour such as this modifier selection.

Done.

classified TLS symbol into the following sub-types according to the value of 
tls size.

 SYMBOL_TLSLE12
 SYMBOL_TLSLE24
 SYMBOL_TLSLE32
 SYMBOL_TLSLE48

And On AArch64, instruction sequence for TLS LE under -mtls-size=32 will
utilize the relocation modifier "tprel_g0_nc" together with MOVK, it's
only supported in binutils since 2015-03-04 as PR gas/17843. So I
adjusted tlsle32.c to make it robust by detecting whether there is such
binutils support.

OK for trunk?

2015-08-19  Marcus Shawcroft  <marcus.shawcr...@arm.com>
            Jiong Wang  <jiong.w...@arm.com>
gcc/
  * config/aarch64/aarch64.c (initialize_aarch64_tls_size): Set default
  tls size for tiny, small, large memory model.
  (aarch64_load_symref_appropriately): Support new symbol types.
  (aarch64_expand_mov_immediate): Likewise.
  (aarch64_print_operand): Likewise.
  (aarch64_classify_tls_symbol): Likewise.
  * config/aarch64/aarch64-protos.h (aarch64_symbol_context): Likewise.
  (aarch64_symbol_type): Likewise.
  * config/aarch64/aarch64.md (tlsle): Deleted.
  (tlsle12_<mode>): New define_insn.
  (tlsle24_<mode>): Likewise.
  (tlsle32_<mode>): Likewise.
  (tlsle48_<mode>): Likewise.
  * doc/sourcebuild.texi (AArch64-specific attributes): Document
  "aarch64_tlsle32".

gcc/testsuite/
  * lib/target-supports.exp (check_effective_target_aarch64_tlsle32):
  New test directive.
  * gcc.target/aarch64/tlsle_1.x: New test source.
  * gcc.target/aarch64/tlsle12.c: New testcase.
  * gcc.target/aarch64/tlsle24.c: New testcase.
  * gcc.target/aarch64/tlsle32.c: New testcase.
-- 
Regards,
Jiong

From bd5c221101a9cf241c1f4d117c643e3a5c7e344d Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiong.w...@arm.com>
Date: Wed, 19 Aug 2015 14:15:01 +0100
Subject: [PATCH 3/3] 3

---
 gcc/config/aarch64/aarch64-protos.h        |  6 +++
 gcc/config/aarch64/aarch64.c               | 66 ++++++++++++++++++++++++++----
 gcc/config/aarch64/aarch64.md              | 56 +++++++++++++++++--------
 gcc/testsuite/gcc.target/aarch64/tlsle12.c |  8 ++++
 gcc/testsuite/gcc.target/aarch64/tlsle24.c |  9 ++++
 gcc/testsuite/gcc.target/aarch64/tlsle32.c | 10 +++++
 gcc/testsuite/gcc.target/aarch64/tlsle_1.x | 14 +++++++
 gcc/testsuite/lib/target-supports.exp      | 17 ++++++++
 8 files changed, 161 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/tlsle12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/tlsle24.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/tlsle32.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/tlsle_1.x

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index daa45bf..09d83e3 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -74,7 +74,10 @@ enum aarch64_symbol_context
    SYMBOL_SMALL_TLSGD
    SYMBOL_SMALL_TLSDESC
    SYMBOL_SMALL_GOTTPREL
+   SYMBOL_TLSLE12
    SYMBOL_TLSLE24
+   SYMBOL_TLSLE32
+   SYMBOL_TLSLE48
    Each of these represents a thread-local symbol, and corresponds to the
    thread local storage relocation operator for the symbol being referred to.
 
@@ -111,7 +114,10 @@ enum aarch64_symbol_type
   SYMBOL_SMALL_GOTTPREL,
   SYMBOL_TINY_ABSOLUTE,
   SYMBOL_TINY_GOT,
+  SYMBOL_TLSLE12,
   SYMBOL_TLSLE24,
+  SYMBOL_TLSLE32,
+  SYMBOL_TLSLE48,
   SYMBOL_FORCE_TO_MEM
 };
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 87f8d96..9a1e53b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1115,14 +1115,43 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 	return;
       }
 
+    case SYMBOL_TLSLE12:
     case SYMBOL_TLSLE24:
+    case SYMBOL_TLSLE32:
+    case SYMBOL_TLSLE48:
       {
+	machine_mode mode = GET_MODE (dest);
 	rtx tp = aarch64_load_tp (NULL);
 
-	if (GET_MODE (dest) != Pmode)
-	  tp = gen_lowpart (GET_MODE (dest), tp);
+	if (mode != Pmode)
+	  tp = gen_lowpart (mode, tp);
+
+	switch (type)
+	  {
+	  case SYMBOL_TLSLE12:
+	    emit_insn ((mode == DImode ? gen_tlsle12_di : gen_tlsle12_si)
+			(dest, tp, imm));
+	    break;
+	  case SYMBOL_TLSLE24:
+	    emit_insn ((mode == DImode ? gen_tlsle24_di : gen_tlsle24_si)
+			(dest, tp, imm));
+	  break;
+	  case SYMBOL_TLSLE32:
+	    emit_insn ((mode == DImode ? gen_tlsle32_di : gen_tlsle32_si)
+			(dest, imm));
+	    emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3)
+			(dest, dest, tp));
+	  break;
+	  case SYMBOL_TLSLE48:
+	    emit_insn ((mode == DImode ? gen_tlsle48_di : gen_tlsle48_si)
+			(dest, imm));
+	    emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3)
+			(dest, dest, tp));
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
 
-	emit_insn (gen_tlsle (dest, tp, imm));
 	set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
 	return;
       }
@@ -1677,7 +1706,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 
 	case SYMBOL_SMALL_ABSOLUTE:
 	case SYMBOL_TINY_ABSOLUTE:
+	case SYMBOL_TLSLE12:
 	case SYMBOL_TLSLE24:
+	case SYMBOL_TLSLE32:
+	case SYMBOL_TLSLE48:
 	  aarch64_load_symref_appropriately (dest, imm, sty);
 	  return;
 
@@ -4593,6 +4625,10 @@ aarch64_print_operand (FILE *f, rtx x, char code)
 	  asm_fprintf (asm_out_file, ":gottprel_lo12:");
 	  break;
 
+	case SYMBOL_TLSLE12:
+	  asm_fprintf (asm_out_file, ":tprel_lo12:");
+	  break;
+
 	case SYMBOL_TLSLE24:
 	  asm_fprintf (asm_out_file, ":tprel_lo12_nc:");
 	  break;
@@ -7514,20 +7550,27 @@ initialize_aarch64_tls_size (struct gcc_options *opts)
   switch (opts->x_aarch64_cmodel_var)
     {
     case AARCH64_CMODEL_TINY:
-      /* The maximum TLS size allowed under tiny is 1M.  */
-      if (aarch64_tls_size > 20)
-	aarch64_tls_size = 20;
+      /* Both the default and maximum TLS size allowed under tiny is 1M which
+	 needs two instructions to address, so we clamp the size to 24.  */
+      if (aarch64_tls_size == 0 || aarch64_tls_size > 24)
+	aarch64_tls_size = 24;
       break;
     case AARCH64_CMODEL_SMALL:
       /* The maximum TLS size allowed under small is 4G.  */
       if (aarch64_tls_size > 32)
 	aarch64_tls_size = 32;
+      /* Default tls size be 16M.  */
+      else if (aarch64_tls_size == 0)
+	aarch64_tls_size = 24;
       break;
     case AARCH64_CMODEL_LARGE:
       /* The maximum TLS size allowed under large is 16E.
 	 FIXME: 16E should be 64bit, we only support 48bit offset now.  */
       if (aarch64_tls_size > 48)
 	aarch64_tls_size = 48;
+      /* Default tls size be 16M.  */
+      else if (aarch64_tls_size == 0)
+	aarch64_tls_size = 24;
       break;
     default:
       gcc_unreachable ();
@@ -8717,7 +8760,16 @@ aarch64_classify_tls_symbol (rtx x)
       return SYMBOL_SMALL_GOTTPREL;
 
     case TLS_MODEL_LOCAL_EXEC:
-      return SYMBOL_TLSLE24;
+      if (aarch64_tls_size == 12)
+	return SYMBOL_TLSLE12;
+      else if (aarch64_tls_size == 24)
+	return SYMBOL_TLSLE24;
+      else if (aarch64_tls_size == 32)
+	return SYMBOL_TLSLE32;
+      else if (aarch64_tls_size == 48)
+	return SYMBOL_TLSLE48;
+      else
+	gcc_unreachable ();
 
     case TLS_MODEL_EMULATED:
     case TLS_MODEL_NONE:
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 35255e9..89fff15 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -117,7 +117,10 @@
     UNSPEC_ST4_LANE
     UNSPEC_TLS
     UNSPEC_TLSDESC
-    UNSPEC_TLSLE
+    UNSPEC_TLSLE12
+    UNSPEC_TLSLE24
+    UNSPEC_TLSLE32
+    UNSPEC_TLSLE48
     UNSPEC_USHL_2S
     UNSPEC_VSTRUCTDUMMY
     UNSPEC_SP_SET
@@ -4512,31 +4515,48 @@
    (set_attr "length" "8")]
 )
 
-(define_expand "tlsle"
-  [(set (match_operand 0 "register_operand" "=r")
-        (unspec [(match_operand 1 "register_operand" "r")
-                   (match_operand 2 "aarch64_tls_le_symref" "S")]
-                   UNSPEC_TLSLE))]
+(define_insn "tlsle12_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+	(unspec:P [(match_operand:P 1 "register_operand" "r")
+		   (match_operand 2 "aarch64_tls_le_symref" "S")]
+		   UNSPEC_TLSLE12))]
   ""
-{
-  machine_mode mode = GET_MODE (operands[0]);
-  emit_insn ((mode == DImode
-	      ? gen_tlsle_di
-	      : gen_tlsle_si) (operands[0], operands[1], operands[2]));
-  DONE;
-})
+  "add\\t%<w>0, %<w>1, #%L2";
+  [(set_attr "type" "alu_sreg")
+   (set_attr "length" "4")]
+)
 
-(define_insn "tlsle_<mode>"
+(define_insn "tlsle24_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
-        (unspec:P [(match_operand:P 1 "register_operand" "r")
-                   (match_operand 2 "aarch64_tls_le_symref" "S")]
-		   UNSPEC_TLSLE))]
+	(unspec:P [(match_operand:P 1 "register_operand" "r")
+		   (match_operand 2 "aarch64_tls_le_symref" "S")]
+		   UNSPEC_TLSLE24))]
   ""
   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
-  [(set_attr "type" "alu_sreg")
+  [(set_attr "type" "multiple")
    (set_attr "length" "8")]
 )
 
+(define_insn "tlsle32_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+	(unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
+		   UNSPEC_TLSLE32))]
+  ""
+  "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
+  [(set_attr "type" "multiple")
+   (set_attr "length" "8")]
+)
+
+(define_insn "tlsle48_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+	(unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
+		   UNSPEC_TLSLE48))]
+  ""
+  "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
+  [(set_attr "type" "multiple")
+   (set_attr "length" "12")]
+)
+
 (define_insn "tlsdesc_small_<mode>"
   [(set (reg:PTR R0_REGNUM)
         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle12.c b/gcc/testsuite/gcc.target/aarch64/tlsle12.c
new file mode 100644
index 0000000..846aa98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsle12.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=12 --save-temps" } */
+
+#include "tlsle_1.x"
+
+/* { dg-final { scan-assembler-times "#:tprel_lo12" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle24.c b/gcc/testsuite/gcc.target/aarch64/tlsle24.c
new file mode 100644
index 0000000..e8b14ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsle24.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=24 --save-temps" } */
+
+#include "tlsle_1.x"
+
+/* { dg-final { scan-assembler-times "#:tprel_lo12_nc" 2 } } */
+/* { dg-final { scan-assembler-times "#:tprel_hi12" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle32.c b/gcc/testsuite/gcc.target/aarch64/tlsle32.c
new file mode 100644
index 0000000..edc06ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsle32.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target aarch64_tlsle32 } */
+/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=32 --save-temps" } */
+
+#include "tlsle_1.x"
+
+/* { dg-final { scan-assembler-times "#:tprel_g1" 2 } } */
+/* { dg-final { scan-assembler-times "#:tprel_g0_nc" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle_1.x b/gcc/testsuite/gcc.target/aarch64/tlsle_1.x
new file mode 100644
index 0000000..d92281b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tlsle_1.x
@@ -0,0 +1,14 @@
+void abort (void);
+
+__thread int t0 = 0x10;
+__thread int t1 = 0x10;
+
+int
+main (int argc, char **argv)
+{
+  if (t0 != t1)
+    abort ();
+
+  return  0;
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 1988301..70576b3 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -957,6 +957,23 @@ proc check_effective_target_aarch64_small_fpic { } {
     }
 }
 
+# On AArch64, instruction sequence for TLS LE under -mtls-size=32 will utilize
+# the relocation modifier "tprel_g0_nc" together with MOVK, it's only supported
+# in binutils since 2015-03-04 as PR gas/17843.
+#
+# This test directive make sure binutils support all features needed by TLS LE
+# under -mtls-size=32 on AArch64.
+
+proc check_effective_target_aarch64_tlsle32 { } {
+    if { [istarget aarch64*-*-*] } {
+	return [check_no_compiler_messages aarch64_tlsle32 object {
+	    void foo (void) { asm ("movk x1,#:tprel_g0_nc:t1"); }
+	}]
+    } else {
+	return 0
+    }
+}
+
 # Return 1 if -shared is supported, as in no warnings or errors
 # emitted, 0 otherwise.
 
-- 
1.9.1

Reply via email to