[AArch64] Use calls for SVE TLSDESC
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
This commit is contained in:
parent
08cc4d925f
commit
bb6ce448fc
|
@ -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>
|
2019-10-01 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
* config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an
|
* config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an
|
||||||
|
|
|
@ -533,6 +533,7 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT);
|
||||||
bool aarch64_use_return_insn_p (void);
|
bool aarch64_use_return_insn_p (void);
|
||||||
const char *aarch64_output_casesi (rtx *);
|
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_symbol (rtx, HOST_WIDE_INT);
|
||||||
enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
|
enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
|
||||||
enum reg_class aarch64_regno_regclass (unsigned);
|
enum reg_class aarch64_regno_regclass (unsigned);
|
||||||
|
|
|
@ -1896,12 +1896,13 @@ aarch64_hard_regno_call_part_clobbered (unsigned int abi_id,
|
||||||
{
|
{
|
||||||
if (FP_REGNUM_P (regno))
|
if (FP_REGNUM_P (regno))
|
||||||
{
|
{
|
||||||
bool simd_p = (abi_id == ARM_PCS_SIMD);
|
|
||||||
poly_int64 per_register_size = GET_MODE_SIZE (mode);
|
poly_int64 per_register_size = GET_MODE_SIZE (mode);
|
||||||
unsigned int nregs = hard_regno_nregs (regno, mode);
|
unsigned int nregs = hard_regno_nregs (regno, mode);
|
||||||
if (nregs > 1)
|
if (nregs > 1)
|
||||||
per_register_size = exact_div (per_register_size, nregs);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -13953,6 +13954,26 @@ aarch64_can_inline_p (tree caller, tree callee)
|
||||||
return true;
|
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. */
|
/* Return true if SYMBOL_REF X binds locally. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
|
@ -784,6 +784,7 @@ enum arm_pcs
|
||||||
{
|
{
|
||||||
ARM_PCS_AAPCS64, /* Base standard AAPCS for 64 bit. */
|
ARM_PCS_AAPCS64, /* Base standard AAPCS for 64 bit. */
|
||||||
ARM_PCS_SIMD, /* For aarch64_vector_pcs functions. */
|
ARM_PCS_SIMD, /* For aarch64_vector_pcs functions. */
|
||||||
|
ARM_PCS_TLSDESC, /* For targets of tlsdesc calls. */
|
||||||
ARM_PCS_UNKNOWN
|
ARM_PCS_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6805,7 +6805,12 @@
|
||||||
"TARGET_TLS_DESC"
|
"TARGET_TLS_DESC"
|
||||||
{
|
{
|
||||||
if (TARGET_SVE)
|
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
|
else
|
||||||
emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
|
emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
|
||||||
DONE;
|
DONE;
|
||||||
|
@ -6827,67 +6832,20 @@
|
||||||
[(set_attr "type" "call")
|
[(set_attr "type" "call")
|
||||||
(set_attr "length" "16")])
|
(set_attr "length" "16")])
|
||||||
|
|
||||||
;; For SVE, model tlsdesc calls as clobbering the lower 128 bits of
|
;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
|
||||||
;; all vector registers, and clobber all predicate registers, on
|
;; describing the extra call-preserved guarantees. This would work
|
||||||
;; top of the usual R0 and LR.
|
;; for non-SVE too, but avoiding a call is probably better if we can.
|
||||||
(define_insn "tlsdesc_small_sve_<mode>"
|
(define_insn "tlsdesc_small_sve_<mode>"
|
||||||
[(set (reg:PTR R0_REGNUM)
|
[(set (reg:PTR R0_REGNUM)
|
||||||
(unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
|
(call (mem:DI (unspec:PTR
|
||||||
UNSPEC_TLSDESC))
|
[(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:DI LR_REGNUM))
|
||||||
(clobber (reg:CC CC_REGNUM))
|
(clobber (match_scratch:DI 2 "=r"))]
|
||||||
(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))]
|
|
||||||
"TARGET_TLS_DESC && TARGET_SVE"
|
"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 "type" "call")
|
||||||
(set_attr "length" "16")])
|
(set_attr "length" "16")])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue