[AArch64] Use calls for SVE TLSDESC
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 1 Oct 2019 08:55:28 +0000 (08:55 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 1 Oct 2019 08:55:28 +0000 (08:55 +0000)
One (unintended) side effect of the patches to support multiple
ABIs is that we can now represent tlsdesc calls as normal calls
on SVE targets.  This is likely to be handled more efficiently than
clobber_high, and for example fixes the long-standing failure in
gcc.target/aarch64/sve/tls_preserve_1.c.

2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR target/91452
* config/aarch64/aarch64.h (ARM_PCS_TLSDESC): New arm_pcs.
* config/aarch64/aarch64-protos.h (aarch64_tlsdesc_abi_id): Declare.
* config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered):
Handle ARM_PCS_TLSDESC.
(aarch64_tlsdesc_abi_id): New function.
* config/aarch64/aarch64.md (tlsdesc_small_sve_<mode>): Use a call
rtx instead of a list of clobbers and clobber_highs.
(tlsdesc_small_<mode>): Update accordingly.

From-SVN: r276392

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.h
gcc/config/aarch64/aarch64.md

index cfe5f841922a8aa215d55d76375ac5dd6453cc36..e0aa3ac69fe7886fc9d1b8c53c3ad4845bf8e74c 100644 (file)
@@ -1,3 +1,15 @@
+2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR target/91452
+       * config/aarch64/aarch64.h (ARM_PCS_TLSDESC): New arm_pcs.
+       * config/aarch64/aarch64-protos.h (aarch64_tlsdesc_abi_id): Declare.
+       * config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered):
+       Handle ARM_PCS_TLSDESC.
+       (aarch64_tlsdesc_abi_id): New function.
+       * config/aarch64/aarch64.md (tlsdesc_small_sve_<mode>): Use a call
+       rtx instead of a list of clobbers and clobber_highs.
+       (tlsdesc_small_<mode>): Update accordingly.
+
 2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an
index 919f2b1fd283b05b9cc5a46ac7edab2582bf2296..ab27a1263f54981586f2b9d036f143030820208b 100644 (file)
@@ -533,6 +533,7 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT);
 bool aarch64_use_return_insn_p (void);
 const char *aarch64_output_casesi (rtx *);
 
+unsigned int aarch64_tlsdesc_abi_id ();
 enum aarch64_symbol_type aarch64_classify_symbol (rtx, HOST_WIDE_INT);
 enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
 enum reg_class aarch64_regno_regclass (unsigned);
index 85c87bb626b21d1c10b5d76ce5a6e8f9ebdacd14..7ee31a66b12d7354759f06449955e933421f5fe0 100644 (file)
@@ -1896,12 +1896,13 @@ aarch64_hard_regno_call_part_clobbered (unsigned int abi_id,
 {
   if (FP_REGNUM_P (regno))
     {
-      bool simd_p = (abi_id == ARM_PCS_SIMD);
       poly_int64 per_register_size = GET_MODE_SIZE (mode);
       unsigned int nregs = hard_regno_nregs (regno, mode);
       if (nregs > 1)
        per_register_size = exact_div (per_register_size, nregs);
-      return maybe_gt (per_register_size, simd_p ? 16 : 8);
+      if (abi_id == ARM_PCS_SIMD || abi_id == ARM_PCS_TLSDESC)
+       return maybe_gt (per_register_size, 16);
+      return maybe_gt (per_register_size, 8);
     }
   return false;
 }
@@ -13953,6 +13954,26 @@ aarch64_can_inline_p (tree caller, tree callee)
   return true;
 }
 
+/* Return the ID of the TLDESC ABI, initializing the descriptor if hasn't
+   been already.  */
+
+unsigned int
+aarch64_tlsdesc_abi_id ()
+{
+  predefined_function_abi &tlsdesc_abi = function_abis[ARM_PCS_TLSDESC];
+  if (!tlsdesc_abi.initialized_p ())
+    {
+      HARD_REG_SET full_reg_clobbers;
+      CLEAR_HARD_REG_SET (full_reg_clobbers);
+      SET_HARD_REG_BIT (full_reg_clobbers, R0_REGNUM);
+      SET_HARD_REG_BIT (full_reg_clobbers, CC_REGNUM);
+      for (int regno = P0_REGNUM; regno <= P15_REGNUM; ++regno)
+       SET_HARD_REG_BIT (full_reg_clobbers, regno);
+      tlsdesc_abi.initialize (ARM_PCS_TLSDESC, full_reg_clobbers);
+    }
+  return tlsdesc_abi.id ();
+}
+
 /* Return true if SYMBOL_REF X binds locally.  */
 
 static bool
index 5aff106694f4117d6b608a21359f6dff42fc30c6..abd14a2f92c06828adfc6d2e2e81b63a6163d3a3 100644 (file)
@@ -784,6 +784,7 @@ enum arm_pcs
 {
   ARM_PCS_AAPCS64,             /* Base standard AAPCS for 64 bit.  */
   ARM_PCS_SIMD,                        /* For aarch64_vector_pcs functions.  */
+  ARM_PCS_TLSDESC,             /* For targets of tlsdesc calls.  */
   ARM_PCS_UNKNOWN
 };
 
index e483572820ccb3680846247b04319d5922114c4c..e7a6930465e5433c68f3d9c9b4ba2b9f82aaf7ce 100644 (file)
   "TARGET_TLS_DESC"
   {
     if (TARGET_SVE)
-      emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0]));
+      {
+       rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
+       rtx_insn *call
+         = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
+       RTL_CONST_CALL_P (call) = 1;
+      }
     else
       emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
     DONE;
   [(set_attr "type" "call")
    (set_attr "length" "16")])
 
-;; For SVE, model tlsdesc calls as clobbering the lower 128 bits of
-;; all vector registers, and clobber all predicate registers, on
-;; top of the usual R0 and LR.
+;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
+;; describing the extra call-preserved guarantees.  This would work
+;; for non-SVE too, but avoiding a call is probably better if we can.
 (define_insn "tlsdesc_small_sve_<mode>"
   [(set (reg:PTR R0_REGNUM)
-        (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
-                   UNSPEC_TLSDESC))
+       (call (mem:DI (unspec:PTR
+                       [(match_operand 0 "aarch64_valid_symref")]
+                       UNSPEC_TLSDESC))
+             (const_int 0)))
+   (unspec:DI [(match_operand:DI 1 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (clobber (reg:DI LR_REGNUM))
-   (clobber (reg:CC CC_REGNUM))
-   (clobber_high (reg:TI V0_REGNUM))
-   (clobber_high (reg:TI V1_REGNUM))
-   (clobber_high (reg:TI V2_REGNUM))
-   (clobber_high (reg:TI V3_REGNUM))
-   (clobber_high (reg:TI V4_REGNUM))
-   (clobber_high (reg:TI V5_REGNUM))
-   (clobber_high (reg:TI V6_REGNUM))
-   (clobber_high (reg:TI V7_REGNUM))
-   (clobber_high (reg:TI V8_REGNUM))
-   (clobber_high (reg:TI V9_REGNUM))
-   (clobber_high (reg:TI V10_REGNUM))
-   (clobber_high (reg:TI V11_REGNUM))
-   (clobber_high (reg:TI V12_REGNUM))
-   (clobber_high (reg:TI V13_REGNUM))
-   (clobber_high (reg:TI V14_REGNUM))
-   (clobber_high (reg:TI V15_REGNUM))
-   (clobber_high (reg:TI V16_REGNUM))
-   (clobber_high (reg:TI V17_REGNUM))
-   (clobber_high (reg:TI V18_REGNUM))
-   (clobber_high (reg:TI V19_REGNUM))
-   (clobber_high (reg:TI V20_REGNUM))
-   (clobber_high (reg:TI V21_REGNUM))
-   (clobber_high (reg:TI V22_REGNUM))
-   (clobber_high (reg:TI V23_REGNUM))
-   (clobber_high (reg:TI V24_REGNUM))
-   (clobber_high (reg:TI V25_REGNUM))
-   (clobber_high (reg:TI V26_REGNUM))
-   (clobber_high (reg:TI V27_REGNUM))
-   (clobber_high (reg:TI V28_REGNUM))
-   (clobber_high (reg:TI V29_REGNUM))
-   (clobber_high (reg:TI V30_REGNUM))
-   (clobber_high (reg:TI V31_REGNUM))
-   (clobber (reg:VNx2BI P0_REGNUM))
-   (clobber (reg:VNx2BI P1_REGNUM))
-   (clobber (reg:VNx2BI P2_REGNUM))
-   (clobber (reg:VNx2BI P3_REGNUM))
-   (clobber (reg:VNx2BI P4_REGNUM))
-   (clobber (reg:VNx2BI P5_REGNUM))
-   (clobber (reg:VNx2BI P6_REGNUM))
-   (clobber (reg:VNx2BI P7_REGNUM))
-   (clobber (reg:VNx2BI P8_REGNUM))
-   (clobber (reg:VNx2BI P9_REGNUM))
-   (clobber (reg:VNx2BI P10_REGNUM))
-   (clobber (reg:VNx2BI P11_REGNUM))
-   (clobber (reg:VNx2BI P12_REGNUM))
-   (clobber (reg:VNx2BI P13_REGNUM))
-   (clobber (reg:VNx2BI P14_REGNUM))
-   (clobber (reg:VNx2BI P15_REGNUM))
-   (clobber (match_scratch:DI 1 "=r"))
-   (use (reg:DI FP_REGNUM))]
+   (clobber (match_scratch:DI 2 "=r"))]
   "TARGET_TLS_DESC && TARGET_SVE"
-  "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
+  "adrp\\tx0, %A0\;ldr\\t%<w>2, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%2"
   [(set_attr "type" "call")
    (set_attr "length" "16")])