From: Richard Sandiford Date: Tue, 1 Oct 2019 08:53:54 +0000 (+0000) Subject: [AArch64] Make call insns record the callee's arm_pcs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=08cc4d925f640c3cd0336bae4dc6004244a5c80a;p=gcc.git [AArch64] Make call insns record the callee's arm_pcs At the moment we rely on SYMBOL_REF_DECL to get the ABI of the callee of a call insn, falling back to the default ABI if the decl isn't available. I think it'd be cleaner to attach the ABI directly to the call instruction instead, which would also have the very minor benefit of handling indirect calls more efficiently. 2019-10-01 Richard Sandiford gcc/ * config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an extra callee_abi argument. * config/aarch64/aarch64.c (aarch64_expand_call): Likewise. Insert a CALLEE_ABI unspec into the call pattern as the second element in the PARALLEL. (aarch64_simd_call_p): Delete. (aarch64_insn_callee_abi): Get the arm_pcs of the callee from the new CALLEE_ABI element of the PARALLEL. (aarch64_init_cumulative_args): Get the arm_pcs of the callee from the function type, if given. (aarch64_function_arg_advance): Handle ARM_PCS_SIMD. (aarch64_function_arg): Likewise. Return the arm_pcs of the callee when passed the function_arg_info end marker. (aarch64_output_mi_thunk): Pass the arm_pcs of the callee as the final argument of gen_sibcall. * config/aarch64/aarch64.md (UNSPEC_CALLEE_ABI): New unspec. (call): Make operand 2 a const_int_operand and pass it to expand_call. Wrap it in an UNSPEC_CALLEE_ABI unspec for the dummy define_expand pattern. (call_value): Likewise operand 3. (sibcall): Likewise operand 2. Place the unspec before rather than after the return. (sibcall_value): Likewise operand 3. (*call_insn, *call_value_insn): Include an UNSPEC_CALLEE_ABI. (tlsgd_small_, *tlsgd_small_): Likewise. (*sibcall_insn, *sibcall_value_insn): Likewise. Remove empty constraint strings. (untyped_call): Pass const0_rtx as the callee ABI to gen_call. gcc/testsuite/ * gcc.target/aarch64/torture/simd-abi-10.c: New test. * gcc.target/aarch64/torture/simd-abi-11.c: Likewise. From-SVN: r276391 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa44ccd6390..cfe5f841922 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2019-10-01 Richard Sandiford + + * config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an + extra callee_abi argument. + * config/aarch64/aarch64.c (aarch64_expand_call): Likewise. + Insert a CALLEE_ABI unspec into the call pattern as the second + element in the PARALLEL. + (aarch64_simd_call_p): Delete. + (aarch64_insn_callee_abi): Get the arm_pcs of the callee from + the new CALLEE_ABI element of the PARALLEL. + (aarch64_init_cumulative_args): Get the arm_pcs of the callee + from the function type, if given. + (aarch64_function_arg_advance): Handle ARM_PCS_SIMD. + (aarch64_function_arg): Likewise. Return the arm_pcs of the callee + when passed the function_arg_info end marker. + (aarch64_output_mi_thunk): Pass the arm_pcs of the callee as the + final argument of gen_sibcall. + * config/aarch64/aarch64.md (UNSPEC_CALLEE_ABI): New unspec. + (call): Make operand 2 a const_int_operand and pass it to expand_call. + Wrap it in an UNSPEC_CALLEE_ABI unspec for the dummy define_expand + pattern. + (call_value): Likewise operand 3. + (sibcall): Likewise operand 2. Place the unspec before rather than + after the return. + (sibcall_value): Likewise operand 3. + (*call_insn, *call_value_insn): Include an UNSPEC_CALLEE_ABI. + (tlsgd_small_, *tlsgd_small_): Likewise. + (*sibcall_insn, *sibcall_value_insn): Likewise. Remove empty + constraint strings. + (untyped_call): Pass const0_rtx as the callee ABI to gen_call. + 2019-10-01 Richard Sandiford * regs.h (HARD_REGNO_CALLER_SAVE_MODE): Update call to diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index c9a342304b6..919f2b1fd28 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -468,7 +468,7 @@ bool aarch64_const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, bool aarch64_constant_address_p (rtx); bool aarch64_emit_approx_div (rtx, rtx, rtx); bool aarch64_emit_approx_sqrt (rtx, rtx, bool); -void aarch64_expand_call (rtx, rtx, bool); +void aarch64_expand_call (rtx, rtx, rtx, bool); bool aarch64_expand_cpymem (rtx *); bool aarch64_float_const_zero_rtx_p (rtx); bool aarch64_float_const_rtx_p (rtx); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index ec180c8bd4f..85c87bb626b 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1872,37 +1872,17 @@ aarch64_reg_save_mode (tree fndecl, unsigned regno) : (aarch64_simd_decl_p (fndecl) ? E_TFmode : E_DFmode); } -/* Return true if the instruction is a call to a SIMD function, false - if it is not a SIMD function or if we do not know anything about - the function. */ - -static bool -aarch64_simd_call_p (const rtx_insn *insn) -{ - rtx symbol; - rtx call; - tree fndecl; - - gcc_assert (CALL_P (insn)); - call = get_call_rtx_from (insn); - symbol = XEXP (XEXP (call, 0), 0); - if (GET_CODE (symbol) != SYMBOL_REF) - return false; - fndecl = SYMBOL_REF_DECL (symbol); - if (!fndecl) - return false; - - return aarch64_simd_decl_p (fndecl); -} - /* Implement TARGET_INSN_CALLEE_ABI. */ const predefined_function_abi & aarch64_insn_callee_abi (const rtx_insn *insn) { - if (aarch64_simd_call_p (insn)) - return aarch64_simd_abi (); - return default_function_abi; + rtx pat = PATTERN (insn); + gcc_assert (GET_CODE (pat) == PARALLEL); + rtx unspec = XVECEXP (pat, 0, 1); + gcc_assert (GET_CODE (unspec) == UNSPEC + && XINT (unspec, 1) == UNSPEC_CALLEE_ABI); + return function_abis[INTVAL (XVECEXP (unspec, 0, 0))]; } /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. The callee only saves @@ -4847,10 +4827,11 @@ static rtx aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) { CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); - gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64); + gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64 + || pcum->pcs_variant == ARM_PCS_SIMD); if (arg.end_marker_p ()) - return NULL_RTX; + return gen_int_mode (pcum->pcs_variant, DImode); aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named); return pcum->aapcs_reg; @@ -4858,16 +4839,19 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) void aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, - const_tree fntype ATTRIBUTE_UNUSED, - rtx libname ATTRIBUTE_UNUSED, - const_tree fndecl ATTRIBUTE_UNUSED, - unsigned n_named ATTRIBUTE_UNUSED) + const_tree fntype, + rtx libname ATTRIBUTE_UNUSED, + const_tree fndecl ATTRIBUTE_UNUSED, + unsigned n_named ATTRIBUTE_UNUSED) { pcum->aapcs_ncrn = 0; pcum->aapcs_nvrn = 0; pcum->aapcs_nextncrn = 0; pcum->aapcs_nextnvrn = 0; - pcum->pcs_variant = ARM_PCS_AAPCS64; + if (fntype) + pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id (); + else + pcum->pcs_variant = ARM_PCS_AAPCS64; pcum->aapcs_reg = NULL_RTX; pcum->aapcs_arg_processed = false; pcum->aapcs_stack_words = 0; @@ -4892,7 +4876,8 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v, const function_arg_info &arg) { CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); - if (pcum->pcs_variant == ARM_PCS_AAPCS64) + if (pcum->pcs_variant == ARM_PCS_AAPCS64 + || pcum->pcs_variant == ARM_PCS_SIMD) { aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named); gcc_assert ((pcum->aapcs_reg != NULL_RTX) @@ -6921,7 +6906,8 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, } funexp = XEXP (DECL_RTL (function), 0); funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); - insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX)); + rtx callee_abi = gen_int_mode (fndecl_abi (function).id (), DImode); + insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi)); SIBLING_CALL_P (insn) = 1; insn = get_insns (); @@ -7999,11 +7985,12 @@ aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) RESULT is the register in which the result is returned. It's NULL for "call" and "sibcall". MEM is the location of the function call. + CALLEE_ABI is a const_int that gives the arm_pcs of the callee. SIBCALL indicates whether this function call is normal call or sibling call. It will generate different pattern accordingly. */ void -aarch64_expand_call (rtx result, rtx mem, bool sibcall) +aarch64_expand_call (rtx result, rtx mem, rtx callee_abi, bool sibcall) { rtx call, callee, tmp; rtvec vec; @@ -8033,7 +8020,11 @@ aarch64_expand_call (rtx result, rtx mem, bool sibcall) else tmp = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM)); - vec = gen_rtvec (2, call, tmp); + gcc_assert (CONST_INT_P (callee_abi)); + callee_abi = gen_rtx_UNSPEC (DImode, gen_rtvec (1, callee_abi), + UNSPEC_CALLEE_ABI); + + vec = gen_rtvec (3, call, callee_abi, tmp); call = gen_rtx_PARALLEL (VOIDmode, vec); aarch64_emit_call_insn (call); diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index fcba5ace867..e483572820c 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -130,6 +130,7 @@ UNSPEC_AUTIB1716 UNSPEC_AUTIASP UNSPEC_AUTIBSP + UNSPEC_CALLEE_ABI UNSPEC_CASESI UNSPEC_CRC32B UNSPEC_CRC32CB @@ -913,14 +914,15 @@ ;; ------------------------------------------------------------------- (define_expand "call" - [(parallel [(call (match_operand 0 "memory_operand") - (match_operand 1 "general_operand")) - (use (match_operand 2 "" "")) - (clobber (reg:DI LR_REGNUM))])] + [(parallel + [(call (match_operand 0 "memory_operand") + (match_operand 1 "general_operand")) + (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI) + (clobber (reg:DI LR_REGNUM))])] "" " { - aarch64_expand_call (NULL_RTX, operands[0], false); + aarch64_expand_call (NULL_RTX, operands[0], operands[2], false); DONE; }" ) @@ -928,6 +930,7 @@ (define_insn "*call_insn" [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf")) (match_operand 1 "" "")) + (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI) (clobber (reg:DI LR_REGNUM))] "" "@ @@ -937,15 +940,16 @@ ) (define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "memory_operand") - (match_operand 2 "general_operand"))) - (use (match_operand 3 "" "")) - (clobber (reg:DI LR_REGNUM))])] + [(parallel + [(set (match_operand 0 "") + (call (match_operand 1 "memory_operand") + (match_operand 2 "general_operand"))) + (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI) + (clobber (reg:DI LR_REGNUM))])] "" " { - aarch64_expand_call (operands[0], operands[1], false); + aarch64_expand_call (operands[0], operands[1], operands[3], false); DONE; }" ) @@ -954,6 +958,7 @@ [(set (match_operand 0 "" "") (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf")) (match_operand 2 "" ""))) + (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI) (clobber (reg:DI LR_REGNUM))] "" "@ @@ -963,33 +968,36 @@ ) (define_expand "sibcall" - [(parallel [(call (match_operand 0 "memory_operand") - (match_operand 1 "general_operand")) - (return) - (use (match_operand 2 "" ""))])] + [(parallel + [(call (match_operand 0 "memory_operand") + (match_operand 1 "general_operand")) + (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI) + (return)])] "" { - aarch64_expand_call (NULL_RTX, operands[0], true); + aarch64_expand_call (NULL_RTX, operands[0], operands[2], true); DONE; } ) (define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "memory_operand") - (match_operand 2 "general_operand"))) - (return) - (use (match_operand 3 "" ""))])] + [(parallel + [(set (match_operand 0 "") + (call (match_operand 1 "memory_operand") + (match_operand 2 "general_operand"))) + (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI) + (return)])] "" { - aarch64_expand_call (operands[0], operands[1], true); + aarch64_expand_call (operands[0], operands[1], operands[3], true); DONE; } ) (define_insn "*sibcall_insn" [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf")) - (match_operand 1 "" "")) + (match_operand 1 "")) + (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI) (return)] "SIBLING_CALL_P (insn)" "@ @@ -999,10 +1007,11 @@ ) (define_insn "*sibcall_value_insn" - [(set (match_operand 0 "" "") + [(set (match_operand 0 "") (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf")) - (match_operand 2 "" ""))) + (match_operand 2 ""))) + (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI) (return)] "SIBLING_CALL_P (insn)" "@ @@ -1022,7 +1031,9 @@ { int i; - emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); + /* Untyped calls always use the default ABI. It's only possible to use + ABI variants if we know the type of the target function. */ + emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -6682,6 +6693,7 @@ (define_expand "tlsgd_small_" [(parallel [(set (match_operand 0 "register_operand") (call (mem:DI (match_dup 2)) (const_int 1))) + (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI) (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS) (clobber (reg:DI LR_REGNUM))])] "" @@ -6692,6 +6704,7 @@ (define_insn "*tlsgd_small_" [(set (match_operand 0 "register_operand" "") (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1))) + (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI) (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS) (clobber (reg:DI LR_REGNUM)) ] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cc31ac8cd5f..2bf37cbbebd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-10-01 Richard Sandiford + + * gcc.target/aarch64/torture/simd-abi-10.c: New test. + * gcc.target/aarch64/torture/simd-abi-11.c: Likewise. + 2019-09-30 Yuliang Wang * gcc.dg/vect/vect-sdiv-pow2-1.c: New test. diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c new file mode 100644 index 00000000000..3d6893ee020 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +int __attribute__((aarch64_vector_pcs)) (*callee) (void); + +int __attribute__ ((aarch64_vector_pcs)) +caller (int *x) +{ + return callee () + 1; +} + +/* { dg-final { scan-assembler-not {\tstp\tq} } } */ +/* { dg-final { scan-assembler-not {\tldp\tq} } } */ +/* { dg-final { scan-assembler-not {\tstr\tq} } } */ +/* { dg-final { scan-assembler-not {\tldr\tq} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c new file mode 100644 index 00000000000..de99bd70199 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ + +int (*callee) (void); + +int __attribute__ ((aarch64_vector_pcs)) +caller (int *x) +{ + return callee () + 1; +} + +/* { dg-final { scan-assembler {\sstp\tq8, q9} } } */ +/* { dg-final { scan-assembler {\sstp\tq10, q11} } } */ +/* { dg-final { scan-assembler {\sstp\tq12, q13} } } */ +/* { dg-final { scan-assembler {\sstp\tq14, q15} } } */ +/* { dg-final { scan-assembler {\sstp\tq16, q17} } } */ +/* { dg-final { scan-assembler {\sstp\tq18, q19} } } */ +/* { dg-final { scan-assembler {\sstp\tq20, q21} } } */ +/* { dg-final { scan-assembler {\sstp\tq22, q23} } } */ +/* { dg-final { scan-assembler {\sldp\tq8, q9} } } */ +/* { dg-final { scan-assembler {\sldp\tq10, q11} } } */ +/* { dg-final { scan-assembler {\sldp\tq12, q13} } } */ +/* { dg-final { scan-assembler {\sldp\tq14, q15} } } */ +/* { dg-final { scan-assembler {\sldp\tq16, q17} } } */ +/* { dg-final { scan-assembler {\sldp\tq18, q19} } } */ +/* { dg-final { scan-assembler {\sldp\tq20, q21} } } */ +/* { dg-final { scan-assembler {\sldp\tq22, q23} } } */