2014-05-23 Yvan Roux <yvan.roux@linaro.org>
authoryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Jun 2014 11:43:21 +0000 (11:43 +0000)
committeryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Jun 2014 11:43:21 +0000 (11:43 +0000)
       Backport from trunk r209645.
       2014-04-22  Andrew Pinski  <apinski@cavium.com>

       * config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
       Handle TLS for ILP32.
       * config/aarch64/aarch64.md (tlsie_small): Rename to ...
       (tlsie_small_<mode>): this and handle PTR.
       (tlsie_small_sidi): New pattern.
       (tlsle_small): Change to an expand to handle ILP32.
       (tlsle_small_<mode>): New pattern.
       (tlsdesc_small): Rename to ...
       (tlsdesc_small_<mode>): this and handle PTR.

git-svn-id: svn://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@211517 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog.linaro
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md

index b1596d1..bc09e72 100644 (file)
@@ -1,5 +1,20 @@
 2014-05-23  Yvan Roux  <yvan.roux@linaro.org>
 
+       Backport from trunk r209645.
+       2014-04-22  Andrew Pinski  <apinski@cavium.com>
+
+       * config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
+       Handle TLS for ILP32.
+       * config/aarch64/aarch64.md (tlsie_small): Rename to ...
+       (tlsie_small_<mode>): this and handle PTR.
+       (tlsie_small_sidi): New pattern.
+       (tlsle_small): Change to an expand to handle ILP32.
+       (tlsle_small_<mode>): New pattern.
+       (tlsdesc_small): Rename to ...
+       (tlsdesc_small_<mode>): this and handle PTR.
+
+2014-05-23  Yvan Roux  <yvan.roux@linaro.org>
+
        Backport from trunk r209643.
        2014-04-22  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
index 60b20a0..dacd7ee 100644 (file)
@@ -636,22 +636,58 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 
     case SYMBOL_SMALL_TLSDESC:
       {
-       rtx x0 = gen_rtx_REG (Pmode, R0_REGNUM);
+       enum machine_mode mode = GET_MODE (dest);
+       rtx x0 = gen_rtx_REG (mode, R0_REGNUM);
        rtx tp;
 
-       emit_insn (gen_tlsdesc_small (imm));
+       gcc_assert (mode == Pmode || mode == ptr_mode);
+
+       /* In ILP32, the got entry is always of SImode size.  Unlike
+          small GOT, the dest is fixed at reg 0.  */
+       if (TARGET_ILP32)
+         emit_insn (gen_tlsdesc_small_si (imm));
+       else
+         emit_insn (gen_tlsdesc_small_di (imm));
        tp = aarch64_load_tp (NULL);
-       emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, x0)));
+
+       if (mode != Pmode)
+         tp = gen_lowpart (mode, tp);
+
+       emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp, x0)));
        set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
        return;
       }
 
     case SYMBOL_SMALL_GOTTPREL:
       {
-       rtx tmp_reg = gen_reg_rtx (Pmode);
+       /* In ILP32, the mode of dest can be either SImode or DImode,
+          while the got entry is always of SImode size.  The mode of
+          dest depends on how dest is used: if dest is assigned to a
+          pointer (e.g. in the memory), it has SImode; it may have
+          DImode if dest is dereferenced to access the memeory.
+          This is why we have to handle three different tlsie_small
+          patterns here (two patterns for ILP32).  */
+       enum machine_mode mode = GET_MODE (dest);
+       rtx tmp_reg = gen_reg_rtx (mode);
        rtx tp = aarch64_load_tp (NULL);
-       emit_insn (gen_tlsie_small (tmp_reg, imm));
-       emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, tmp_reg)));
+
+       if (mode == ptr_mode)
+         {
+           if (mode == DImode)
+             emit_insn (gen_tlsie_small_di (tmp_reg, imm));
+           else
+             {
+               emit_insn (gen_tlsie_small_si (tmp_reg, imm));
+               tp = gen_lowpart (mode, tp);
+             }
+         }
+       else
+         {
+           gcc_assert (mode == Pmode);
+           emit_insn (gen_tlsie_small_sidi (tmp_reg, imm));
+         }
+
+       emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp, tmp_reg)));
        set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
        return;
       }
index 56ba2ad..9871864 100644 (file)
   [(set_attr "type" "call")
    (set_attr "length" "16")])
 
-(define_insn "tlsie_small"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (unspec:DI [(match_operand:DI 1 "aarch64_tls_ie_symref" "S")]
+(define_insn "tlsie_small_<mode>"
+  [(set (match_operand:PTR 0 "register_operand" "=r")
+        (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
                   UNSPEC_GOTSMALLTLS))]
   ""
-  "adrp\\t%0, %A1\;ldr\\t%0, [%0, #%L1]"
+  "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
   [(set_attr "type" "load1")
    (set_attr "length" "8")]
 )
 
-(define_insn "tlsle_small"
+(define_insn "tlsie_small_sidi"
   [(set (match_operand:DI 0 "register_operand" "=r")
-        (unspec:DI [(match_operand:DI 1 "register_operand" "r")
-                   (match_operand:DI 2 "aarch64_tls_le_symref" "S")]
+       (zero_extend:DI
+          (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
+                     UNSPEC_GOTSMALLTLS)))]
+  ""
+  "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
+  [(set_attr "type" "load1")
+   (set_attr "length" "8")]
+)
+
+(define_expand "tlsle_small"
+  [(set (match_operand 0 "register_operand" "=r")
+        (unspec [(match_operand 1 "register_operand" "r")
+                   (match_operand 2 "aarch64_tls_le_symref" "S")]
+                   UNSPEC_GOTSMALLTLS))]
+  ""
+{
+  enum machine_mode mode = GET_MODE (operands[0]);
+  emit_insn ((mode == DImode
+             ? gen_tlsle_small_di
+             : gen_tlsle_small_si) (operands[0],
+                                    operands[1],
+                                    operands[2]));
+  DONE;
+})
+
+(define_insn "tlsle_small_<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_GOTSMALLTLS))]
   ""
-  "add\\t%0, %1, #%G2\;add\\t%0, %0, #%L2"
+  "add\\t%<w>0, %<w>1, #%G2\;add\\t%<w>0, %<w>0, #%L2"
   [(set_attr "type" "alu_reg")
    (set_attr "length" "8")]
 )
 
-(define_insn "tlsdesc_small"
-  [(set (reg:DI R0_REGNUM)
-        (unspec:DI [(match_operand:DI 0 "aarch64_valid_symref" "S")]
+(define_insn "tlsdesc_small_<mode>"
+  [(set (reg:PTR R0_REGNUM)
+        (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
                   UNSPEC_TLSDESC))
    (clobber (reg:DI LR_REGNUM))
    (clobber (match_scratch:DI 1 "=r"))]
   "TARGET_TLS_DESC"
-  "adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\tx0, x0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
+  "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
   [(set_attr "type" "call")
    (set_attr "length" "16")])