From de6e4a4e2052bf8743131e2fdf8837ba4c9657ee Mon Sep 17 00:00:00 2001 From: Timothy Chen Date: Wed, 16 Nov 2022 16:15:19 -0800 Subject: [PATCH] Shrink the size of SigData in Cranelift (#5261) * Shrink the size of SigData in Cranelift * Update cranelift/codegen/src/machinst/abi.rs Co-authored-by: Jamey Sharp * Change ret arg length to u16 * Add test Co-authored-by: Jamey Sharp --- cranelift/codegen/src/machinst/abi.rs | 87 +++++++++++++++++---------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs index 160281fc1d..acfd22f6a3 100644 --- a/cranelift/codegen/src/machinst/abi.rs +++ b/cranelift/codegen/src/machinst/abi.rs @@ -119,7 +119,6 @@ use std::collections::HashMap; use std::convert::TryFrom; use std::marker::PhantomData; use std::mem; -use std::ops::Range; /// A small vector of instructions (with some reasonable size); appropriate for /// a small fixed sequence implementing one operation. @@ -612,17 +611,23 @@ cranelift_entity::entity_impl!(Sig); /// ABI information shared between body (callee) and caller. #[derive(Clone, Debug)] pub struct SigData { - /// Argument locations (regs or stack slots). Stack offsets are relative to + /// Argument location starting offset (regs or stack slots). Stack offsets are relative to /// SP on entry to function. /// - /// These are indices into the `SigSet::abi_args`. - arg_indices: Range, + /// This is a index into the `SigSet::abi_args`. + args_start: u32, - /// Return-value locations. Stack offsets are relative to the return-area + /// Amount of arguments in the stack. + args_length: u16, + + /// Return-value location starting offset. Stack offsets are relative to the return-area /// pointer. /// - /// These are indices into the `SigSet::abi_args`. - ret_indices: Range, + /// This is a index into the `SigSet::abi_args`. + rets_start: u32, + + /// Amount of Return value locations in the stack. + rets_length: u16, /// Space on stack used to store arguments. sized_stack_arg_space: i64, @@ -631,7 +636,7 @@ pub struct SigData { sized_stack_ret_space: i64, /// Index in `args` of the stack-return-value-area argument. - stack_ret_arg: Option, + stack_ret_arg: Option, /// Calling convention used. call_conv: isa::CallConv, @@ -671,22 +676,28 @@ impl SigData { )?; let args_end = u32::try_from(sigs.abi_args.len()).unwrap(); - let arg_indices = args_start..args_end; - let ret_indices = rets_start..rets_end; + 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 = {:?} rets = {:?} arg stack = {} ret stack = {} stack_ret_arg = {:?}", + "ABISig: sig {:?} => args start = {} args len = {} rets start = {} rets len = {} + arg stack = {} ret stack = {} stack_ret_arg = {:?}", sig, - arg_indices, - ret_indices, + args_start, + args_length, + rets_start, + rets_length, sized_stack_arg_space, sized_stack_ret_space, stack_ret_arg, ); + let stack_ret_arg = stack_ret_arg.map(|s| u16::try_from(s).unwrap()); Ok(SigData { - arg_indices, - ret_indices, + args_start, + args_length, + rets_start, + rets_length, sized_stack_arg_space, sized_stack_ret_space, stack_ret_arg, @@ -696,15 +707,15 @@ impl SigData { /// Get this signature's ABI arguments. pub fn args<'a>(&self, sigs: &'a SigSet) -> &'a [ABIArg] { - let start = usize::try_from(self.arg_indices.start).unwrap(); - let end = usize::try_from(self.arg_indices.end).unwrap(); + let start = usize::try_from(self.args_start).unwrap(); + let end = usize::try_from(self.args_start + u32::from(self.args_length)).unwrap(); &sigs.abi_args[start..end] } /// Get this signature's ABI returns. pub fn rets<'a>(&self, sigs: &'a SigSet) -> &'a [ABIArg] { - let start = usize::try_from(self.ret_indices.start).unwrap(); - let end = usize::try_from(self.ret_indices.end).unwrap(); + let start = usize::try_from(self.rets_start).unwrap(); + let end = usize::try_from(self.rets_start + u32::from(self.rets_length)).unwrap(); &sigs.abi_args[start..end] } @@ -742,13 +753,13 @@ impl SigData { /// Get the number of arguments expected. pub fn num_args(&self) -> usize { - let len = self.arg_indices.end - self.arg_indices.start; - let len = usize::try_from(len).unwrap(); - if self.stack_ret_arg.is_some() { - len - 1 + let num = if self.stack_ret_arg.is_some() { + self.args_length - 1 } else { - len - } + self.args_length + }; + + usize::from(num) } /// Get information specifying how to pass one argument. @@ -763,8 +774,7 @@ impl SigData { /// Get the number of return values expected. pub fn num_rets(&self) -> usize { - let len = self.ret_indices.end - self.ret_indices.start; - usize::try_from(len).unwrap() + usize::from(self.rets_length) } /// Get information specifying how to pass one return value. @@ -780,7 +790,7 @@ impl SigData { /// Get information specifying how to pass the implicit pointer /// to the return-value area on the stack, if required. pub fn get_ret_arg(&self, sigs: &SigSet) -> Option { - let ret_arg = self.stack_ret_arg?; + let ret_arg = usize::from(self.stack_ret_arg?); Some(self.args(sigs)[ret_arg].clone()) } @@ -1598,8 +1608,11 @@ impl Callee { /// pointer to that memory. pub fn gen_retval_area_setup(&mut self, sigs: &SigSet) -> Option { if let Some(i) = sigs[self.sig].stack_ret_arg { - let insts = - self.gen_copy_arg_to_regs(sigs, i, ValueRegs::one(self.ret_area_ptr.unwrap())); + let insts = self.gen_copy_arg_to_regs( + sigs, + i.into(), + ValueRegs::one(self.ret_area_ptr.unwrap()), + ); insts.into_iter().next().map(|inst| { trace!( "gen_retval_area_setup: inst {:?}; ptr reg is {:?}", @@ -2338,7 +2351,7 @@ impl Caller { rd, I8, )); - for inst in self.gen_arg(ctx, i, ValueRegs::one(rd.to_reg())) { + for inst in self.gen_arg(ctx, i.into(), ValueRegs::one(rd.to_reg())) { ctx.emit(inst); } } @@ -2365,3 +2378,15 @@ impl Caller { } } } + +#[cfg(test)] +mod tests { + use super::SigData; + + #[test] + 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::(), 40); + } +}