Cranelift: Avoid calling ensure_struct_return_pointer_is_returned and cloning sigs for every call (#5113)
* Cranelift: pass iterators to `ABIMachineSpec::compute_arg_locs` Instead of slices. This gives us more flexibility to pass custom sequences without needing to allocate a `Vec` to hold them and pass in as a slice. * Cranelift: Avoid cloning `ir::Signature`s in `SigData::from_func_sig` This avoids two heap allocations per signature that are unnecessary 99% of the time. * fix typo * Simplify condition in `missing_struct_return`
This commit is contained in:
@@ -586,14 +586,15 @@ impl SigData {
|
|||||||
sig: &ir::Signature,
|
sig: &ir::Signature,
|
||||||
flags: &settings::Flags,
|
flags: &settings::Flags,
|
||||||
) -> CodegenResult<SigData> {
|
) -> CodegenResult<SigData> {
|
||||||
let sig = ensure_struct_return_ptr_is_returned(sig);
|
let sret = missing_struct_return(sig);
|
||||||
|
let returns = sret.as_ref().into_iter().chain(&sig.returns);
|
||||||
|
|
||||||
// Compute args and retvals from signature. Handle retvals first,
|
// Compute args and retvals from signature. Handle retvals first,
|
||||||
// because we may need to add a return-area arg to the args.
|
// because we may need to add a return-area arg to the args.
|
||||||
let (rets, sized_stack_ret_space, _) = M::compute_arg_locs(
|
let (rets, sized_stack_ret_space, _) = M::compute_arg_locs(
|
||||||
sig.call_conv,
|
sig.call_conv,
|
||||||
flags,
|
flags,
|
||||||
&sig.returns,
|
returns,
|
||||||
ArgsOrRets::Rets,
|
ArgsOrRets::Rets,
|
||||||
/* extra ret-area ptr = */ false,
|
/* extra ret-area ptr = */ false,
|
||||||
)?;
|
)?;
|
||||||
@@ -1175,19 +1176,21 @@ fn gen_store_stack_multi<M: ABIMachineSpec>(
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn ensure_struct_return_ptr_is_returned(sig: &ir::Signature) -> ir::Signature {
|
/// If the signature needs to be legalized, then return the struct-return
|
||||||
let params_structret = sig
|
/// parameter that should be prepended to its returns. Otherwise, return `None`.
|
||||||
.params
|
fn missing_struct_return(sig: &ir::Signature) -> Option<ir::AbiParam> {
|
||||||
.iter()
|
let struct_ret_index = sig.special_param_index(ArgumentPurpose::StructReturn)?;
|
||||||
.find(|p| p.purpose == ArgumentPurpose::StructReturn);
|
if !sig.uses_special_return(ArgumentPurpose::StructReturn) {
|
||||||
let rets_have_structret = sig.returns.len() > 0
|
return Some(sig.params[struct_ret_index]);
|
||||||
&& sig
|
}
|
||||||
.returns
|
|
||||||
.iter()
|
None
|
||||||
.any(|arg| arg.purpose == ArgumentPurpose::StructReturn);
|
}
|
||||||
|
|
||||||
|
fn ensure_struct_return_ptr_is_returned(sig: &ir::Signature) -> ir::Signature {
|
||||||
let mut sig = sig.clone();
|
let mut sig = sig.clone();
|
||||||
if params_structret.is_some() && !rets_have_structret {
|
if let Some(sret) = missing_struct_return(&sig) {
|
||||||
sig.returns.insert(0, params_structret.unwrap().clone());
|
sig.returns.insert(0, sret);
|
||||||
}
|
}
|
||||||
sig
|
sig
|
||||||
}
|
}
|
||||||
@@ -1198,6 +1201,10 @@ pub(crate) fn ensure_struct_return_ptr_is_returned(sig: &ir::Signature) -> ir::S
|
|||||||
impl<M: ABIMachineSpec> Callee<M> {
|
impl<M: ABIMachineSpec> Callee<M> {
|
||||||
/// Access the (possibly legalized) signature.
|
/// Access the (possibly legalized) signature.
|
||||||
pub fn signature(&self) -> &ir::Signature {
|
pub fn signature(&self) -> &ir::Signature {
|
||||||
|
debug_assert!(
|
||||||
|
missing_struct_return(&self.ir_sig).is_none(),
|
||||||
|
"`Callee::ir_sig` is always legalized"
|
||||||
|
);
|
||||||
&self.ir_sig
|
&self.ir_sig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user