diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cfe5f841922..e0aa3ac69fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-10-01 Richard Sandiford + + 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_): Use a call + rtx instead of a list of clobbers and clobber_highs. + (tlsdesc_small_): Update accordingly. + 2019-10-01 Richard Sandiford * config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 919f2b1fd28..ab27a1263f5 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -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); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 85c87bb626b..7ee31a66b12 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -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 diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 5aff106694f..abd14a2f92c 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -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 }; diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index e483572820c..e7a6930465e 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -6805,7 +6805,12 @@ "TARGET_TLS_DESC" { if (TARGET_SVE) - emit_insn (gen_tlsdesc_small_sve_ (operands[0])); + { + rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode); + rtx_insn *call + = emit_call_insn (gen_tlsdesc_small_sve_ (operands[0], abi)); + RTL_CONST_CALL_P (call) = 1; + } else emit_insn (gen_tlsdesc_small_advsimd_ (operands[0])); DONE; @@ -6827,67 +6832,20 @@ [(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_" [(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%1, [x0, #%L0]\;add\\t0, 0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" + "adrp\\tx0, %A0\;ldr\\t%2, [x0, #%L0]\;add\\t0, 0, %L0\;.tlsdesccall\\t%0\;blr\\t%2" [(set_attr "type" "call") (set_attr "length" "16")])