Avoid introducing a move for struct return (#6245)
* Move sret_reg handling to Lower:new, from gen_arg_setup * Update exp files * Review feedback * Review feedback
This commit is contained in:
@@ -377,12 +377,27 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
||||
}
|
||||
}
|
||||
|
||||
// Make a sret register, if one is needed.
|
||||
// Find the sret register, if it's used.
|
||||
let mut sret_reg = None;
|
||||
for ret in &vcode.abi().signature().returns.clone() {
|
||||
for ret in vcode.abi().signature().returns.iter() {
|
||||
if ret.purpose == ArgumentPurpose::StructReturn {
|
||||
assert!(sret_reg.is_none());
|
||||
sret_reg = Some(vregs.alloc(ret.value_type)?);
|
||||
let entry_bb = f.stencil.layout.entry_block().unwrap();
|
||||
for (¶m, sig_param) in f
|
||||
.dfg
|
||||
.block_params(entry_bb)
|
||||
.iter()
|
||||
.zip(vcode.abi().signature().params.iter())
|
||||
{
|
||||
if sig_param.purpose == ArgumentPurpose::StructReturn {
|
||||
let regs = value_regs[param];
|
||||
assert!(regs.len() == 1);
|
||||
|
||||
assert!(sret_reg.is_none());
|
||||
sret_reg = Some(regs);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(sret_reg.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,24 +591,6 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
||||
{
|
||||
self.emit(insn);
|
||||
}
|
||||
if self.abi().signature().params[i].purpose == ArgumentPurpose::StructReturn {
|
||||
assert!(regs.len() == 1);
|
||||
let ty = self.abi().signature().params[i].value_type;
|
||||
// The ABI implementation must have ensured that a StructReturn
|
||||
// arg is present in the return values.
|
||||
assert!(self
|
||||
.abi()
|
||||
.signature()
|
||||
.returns
|
||||
.iter()
|
||||
.position(|ret| ret.purpose == ArgumentPurpose::StructReturn)
|
||||
.is_some());
|
||||
self.emit(I::gen_move(
|
||||
Writable::from_reg(self.sret_reg.unwrap().regs()[0]),
|
||||
regs.regs()[0].to_reg(),
|
||||
ty,
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(insn) = self
|
||||
.vcode
|
||||
|
||||
Reference in New Issue
Block a user