Remove sig data arg and ret fields to reduce size (#5319)

* Remove sig data arg and ret fields to reduce size

* Update cranelift/codegen/src/machinst/abi.rs

Co-authored-by: Jamey Sharp <jamey@minilop.net>

* Update cranelift/codegen/src/machinst/abi.rs

Co-authored-by: Jamey Sharp <jamey@minilop.net>

* Fix offsets

* Add comment

Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
Timothy Chen
2022-11-30 07:19:41 -08:00
committed by GitHub
parent 2bb1fb08fa
commit 67fc5389b0
3 changed files with 66 additions and 59 deletions

View File

@@ -126,7 +126,7 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
fn defs_init(&mut self, abi: &Sig) -> CallRetList {
// Allocate writable registers for all retval regs, except for StructRet args.
let mut defs = smallvec![];
for i in 0..self.lower_ctx.sigs()[*abi].num_rets() {
for i in 0..self.lower_ctx.sigs().num_rets(*abi) {
if let &ABIArg::Slots {
ref slots, purpose, ..
} = &self.lower_ctx.sigs().get_ret(*abi, i)
@@ -169,7 +169,7 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
// Return the index of the first actual return value, excluding
// any StructReturn that might have been added to Sig.
let sig = &self.lower_ctx.dfg().signatures[sig_ref];
self.lower_ctx.sigs()[*abi].num_rets() - sig.returns.len()
self.lower_ctx.sigs().num_rets(*abi) - sig.returns.len()
}
fn abi_lane_order(&mut self, abi: &Sig) -> LaneOrder {

View File

@@ -608,26 +608,42 @@ pub trait ABIMachineSpec {
pub struct Sig(u32);
cranelift_entity::entity_impl!(Sig);
impl Sig {
fn prev(self) -> Option<Sig> {
self.0.checked_sub(1).map(Sig)
}
}
/// ABI information shared between body (callee) and caller.
#[derive(Clone, Debug)]
pub struct SigData {
/// Argument location starting offset (regs or stack slots). Stack offsets are relative to
/// Currently both return values and arguments are stored in a continuous space vector
/// in `SigSet::abi_args`.
///
/// ```plain
/// +----------------------------------------------+
/// | return values |
/// | ... |
/// rets_end --> +----------------------------------------------+
/// | arguments |
/// | ... |
/// args_end --> +----------------------------------------------+
///
/// ```
///
/// Note we only store two offsets as rets_end == args_start, and rets_start == prev.args_end.
///
/// Argument location ending offset (regs or stack slots). Stack offsets are relative to
/// SP on entry to function.
///
/// This is a index into the `SigSet::abi_args`.
args_start: u32,
args_end: u32,
/// Amount of arguments in the stack.
args_length: u16,
/// Return-value location starting offset. Stack offsets are relative to the return-area
/// Return-value location ending offset. Stack offsets are relative to the return-area
/// pointer.
///
/// This is a index into the `SigSet::abi_args`.
rets_start: u32,
/// Amount of Return value locations in the stack.
rets_length: u16,
rets_end: u32,
/// Space on stack used to store arguments.
sized_stack_arg_space: i64,
@@ -643,27 +659,11 @@ pub struct SigData {
}
impl SigData {
/// Get the number of arguments expected.
pub fn num_args(&self) -> usize {
let num = if self.stack_ret_arg.is_some() {
self.args_length - 1
} else {
self.args_length
};
usize::from(num)
}
/// Get total stack space required for arguments.
pub fn sized_stack_arg_space(&self) -> i64 {
self.sized_stack_arg_space
}
/// Get the number of return values expected.
pub fn num_rets(&self) -> usize {
usize::from(self.rets_length)
}
/// Get total stack space required for return values.
pub fn sized_stack_ret_space(&self) -> i64 {
self.sized_stack_ret_space
@@ -806,7 +806,10 @@ impl SigSet {
// Compute args and retvals from signature. Handle retvals first,
// because we may need to add a return-area arg to the args.
let rets_start = u32::try_from(self.abi_args.len()).unwrap();
// NOTE: We rely on the order of the args (rets -> args) inserted to compute the offsets in
// `SigSet::args()` and `SigSet::rets()`. Therefore, we cannot change the two
// compute_arg_locs order.
let (sized_stack_ret_space, _) = M::compute_arg_locs(
sig.call_conv,
flags,
@@ -818,7 +821,6 @@ impl SigSet {
let rets_end = u32::try_from(self.abi_args.len()).unwrap();
let need_stack_return_area = sized_stack_ret_space > 0;
let args_start = u32::try_from(self.abi_args.len()).unwrap();
let (sized_stack_arg_space, stack_ret_arg) = M::compute_arg_locs(
sig.call_conv,
flags,
@@ -829,17 +831,12 @@ impl SigSet {
)?;
let args_end = u32::try_from(self.abi_args.len()).unwrap();
let args_length = u16::try_from(args_end - args_start).unwrap();
let rets_length = u16::try_from(rets_end - rets_start).unwrap();
trace!(
"ABISig: sig {:?} => args start = {} args len = {} rets start = {} rets len = {}
"ABISig: sig {:?} => args end = {} rets end = {}
arg stack = {} ret stack = {} stack_ret_arg = {:?}",
sig,
args_start,
args_length,
rets_start,
rets_length,
args_end,
rets_end,
sized_stack_arg_space,
sized_stack_ret_space,
need_stack_return_area,
@@ -847,10 +844,8 @@ impl SigSet {
let stack_ret_arg = stack_ret_arg.map(|s| u16::try_from(s).unwrap());
Ok(SigData {
args_start,
args_length,
rets_start,
rets_length,
args_end,
rets_end,
sized_stack_arg_space,
sized_stack_ret_space,
stack_ret_arg,
@@ -861,8 +856,9 @@ impl SigSet {
/// Get this signature's ABI arguments.
pub fn args(&self, sig: Sig) -> &[ABIArg] {
let sig_data = &self.sigs[sig];
let start = usize::try_from(sig_data.args_start).unwrap();
let end = usize::try_from(sig_data.args_start + u32::from(sig_data.args_length)).unwrap();
// Please see comments in `SigSet::from_func_sig` of how we store the offsets.
let start = usize::try_from(sig_data.rets_end).unwrap();
let end = usize::try_from(sig_data.args_end).unwrap();
&self.abi_args[start..end]
}
@@ -885,8 +881,9 @@ impl SigSet {
/// Get this signature's ABI returns.
pub fn rets(&self, sig: Sig) -> &[ABIArg] {
let sig_data = &self.sigs[sig];
let start = usize::try_from(sig_data.rets_start).unwrap();
let end = usize::try_from(sig_data.rets_start + u32::from(sig_data.rets_length)).unwrap();
// Please see comments in `SigSet::from_func_sig` of how we store the offsets.
let start = usize::try_from(sig.prev().map_or(0, |prev| self.sigs[prev].args_end)).unwrap();
let end = usize::try_from(sig_data.rets_end).unwrap();
&self.abi_args[start..end]
}
@@ -927,6 +924,21 @@ impl SigSet {
clobbers
}
/// Get the number of arguments expected.
pub fn num_args(&self, sig: Sig) -> usize {
let len = self.args(sig).len();
if self.sigs[sig].stack_ret_arg.is_some() {
len - 1
} else {
len
}
}
/// Get the number of return values expected.
pub fn num_rets(&self, sig: Sig) -> usize {
self.rets(sig).len()
}
}
// NB: we do _not_ implement `IndexMut` because these signatures are
@@ -2097,12 +2109,7 @@ fn adjust_stack_and_nominal_sp<M: ABIMachineSpec>(ctx: &mut Lower<M::I>, off: i3
impl<M: ABIMachineSpec> Caller<M> {
/// Get the number of arguments expected.
pub fn num_args(&self, sigs: &SigSet) -> usize {
let len = sigs.args(self.sig).len();
if sigs[self.sig].stack_ret_arg.is_some() {
len - 1
} else {
len
}
sigs.num_args(self.sig)
}
/// Emit code to pre-adjust the stack, prior to argument copies and call.
@@ -2402,6 +2409,6 @@ mod tests {
fn sig_data_size() {
// The size of `SigData` is performance sensitive, so make sure
// we don't regress it unintentionally.
assert_eq!(std::mem::size_of::<SigData>(), 40);
assert_eq!(std::mem::size_of::<SigData>(), 32);
}
}

View File

@@ -432,7 +432,7 @@ macro_rules! isle_lower_prelude_methods {
}
fn abi_num_args(&mut self, abi: &Sig) -> usize {
self.lower_ctx.sigs()[*abi].num_args()
self.lower_ctx.sigs().num_args(*abi)
}
fn abi_get_arg(&mut self, abi: &Sig, idx: usize) -> ABIArg {
@@ -440,7 +440,7 @@ macro_rules! isle_lower_prelude_methods {
}
fn abi_num_rets(&mut self, abi: &Sig) -> usize {
self.lower_ctx.sigs()[*abi].num_rets()
self.lower_ctx.sigs().num_rets(*abi)
}
fn abi_get_ret(&mut self, abi: &Sig, idx: usize) -> ABIArg {
@@ -681,7 +681,7 @@ macro_rules! isle_prelude_method_helpers {
) -> InstOutput {
caller.emit_stack_pre_adjust(self.lower_ctx);
let num_args = self.lower_ctx.sigs()[abi].num_args();
let num_args = self.lower_ctx.sigs().num_args(abi);
assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
@@ -710,9 +710,9 @@ macro_rules! isle_prelude_method_helpers {
let mut retval_insts: crate::machinst::abi::SmallInstVec<_> = smallvec::smallvec![];
// We take the *last* `num_rets` returns of the sig:
// this skips a StructReturn, if any, that is present.
let sigdata = &self.lower_ctx.sigs()[abi];
debug_assert!(num_rets <= sigdata.num_rets());
for i in (sigdata.num_rets() - num_rets)..sigdata.num_rets() {
let sigdata_num_rets = self.lower_ctx.sigs().num_rets(abi);
debug_assert!(num_rets <= sigdata_num_rets);
for i in (sigdata_num_rets - num_rets)..sigdata_num_rets {
// Borrow `sigdata` again so we don't hold a `self`
// borrow across the `&mut self` arg to
// `abi_arg_slot_regs()` below.