[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  <richard.sandiford@arm.com>

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_<mode>, *tlsgd_small_<mode>): 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
This commit is contained in:
Richard Sandiford 2019-10-01 08:53:54 +00:00 committed by Richard Sandiford
parent 810f316dd6
commit 08cc4d925f
7 changed files with 144 additions and 64 deletions

View File

@ -1,3 +1,34 @@
2019-10-01 Richard Sandiford <richard.sandiford@arm.com>
* 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_<mode>, *tlsgd_small_<mode>): 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 <richard.sandiford@arm.com>
* regs.h (HARD_REGNO_CALLER_SAVE_MODE): Update call to

View File

@ -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);

View File

@ -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);

View File

@ -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_<mode>"
[(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_<mode>"
[(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))
]

View File

@ -1,3 +1,8 @@
2019-10-01 Richard Sandiford <richard.sandiford@arm.com>
* gcc.target/aarch64/torture/simd-abi-10.c: New test.
* gcc.target/aarch64/torture/simd-abi-11.c: Likewise.
2019-09-30 Yuliang Wang <yuliang.wang@arm.com>
* gcc.dg/vect/vect-sdiv-pow2-1.c: New test.

View File

@ -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} } } */

View File

@ -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} } } */