Skip to content

Commit 8659b5c

Browse files
committed
Overlap input and output stack slots
1 parent ebc1c35 commit 8659b5c

File tree

1 file changed

+40
-21
lines changed

1 file changed

+40
-21
lines changed

src/inline_asm.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
128128
let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
129129
fx.cx.global_asm.push_str(&generated_asm);
130130

131-
// FIXME overlap input and output slots to save stack space
132131
for (i, operand) in operands.iter().enumerate() {
133132
match *operand {
134133
InlineAsmOperand::In { reg: _, ref value } => {
@@ -306,19 +305,19 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
306305
let mut slots_input = vec![None; self.operands.len()];
307306
let mut slots_output = vec![None; self.operands.len()];
308307

309-
let mut new_slot = |reg_class: InlineAsmRegClass| {
308+
let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| {
310309
let reg_size = reg_class
311310
.supported_types(InlineAsmArch::X86_64)
312311
.iter()
313312
.map(|(ty, _)| ty.size())
314313
.max()
315314
.unwrap();
316315
let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap();
317-
slot_size = slot_size.align_to(align);
318-
let offset = slot_size;
319-
slot_size += reg_size;
316+
let offset = slot_size.align_to(align);
317+
*slot_size = offset + reg_size;
320318
offset
321319
};
320+
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
322321

323322
// Allocate stack slots for saving clobbered registers
324323
let abi_clobber =
@@ -346,30 +345,50 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
346345
}
347346
}
348347

349-
// FIXME overlap input and output slots to save stack space
348+
// Allocate stack slots for inout
350349
for (i, operand) in self.operands.iter().enumerate() {
351350
match *operand {
352-
InlineAsmOperand::In { reg, .. } => {
353-
slots_input[i] = Some(new_slot(reg.reg_class()));
354-
}
355-
InlineAsmOperand::Out { reg, place, .. } => {
356-
if place.is_some() {
357-
slots_output[i] = Some(new_slot(reg.reg_class()));
358-
}
359-
}
360-
InlineAsmOperand::InOut { reg, out_place, .. } => {
351+
InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => {
361352
let slot = new_slot(reg.reg_class());
362353
slots_input[i] = Some(slot);
363-
if out_place.is_some() {
364-
slots_output[i] = Some(slot);
365-
}
354+
slots_output[i] = Some(slot);
355+
}
356+
_ => (),
357+
}
358+
}
359+
360+
let slot_size_before_input = slot_size;
361+
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
362+
363+
// Allocate stack slots for input
364+
for (i, operand) in self.operands.iter().enumerate() {
365+
match *operand {
366+
InlineAsmOperand::In { reg, .. }
367+
| InlineAsmOperand::InOut { reg, out_place: None, .. } => {
368+
slots_input[i] = Some(new_slot(reg.reg_class()));
369+
}
370+
_ => (),
371+
}
372+
}
373+
374+
// Reset slot size to before input so that input and output operands can overlap
375+
// and save some memory.
376+
let slot_size_after_input = slot_size;
377+
slot_size = slot_size_before_input;
378+
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
379+
380+
// Allocate stack slots for output
381+
for (i, operand) in self.operands.iter().enumerate() {
382+
match *operand {
383+
InlineAsmOperand::Out { reg, place: Some(_), .. } => {
384+
slots_output[i] = Some(new_slot(reg.reg_class()));
366385
}
367-
InlineAsmOperand::Const { value: _ } => (),
368-
InlineAsmOperand::SymFn { value: _ } => (),
369-
InlineAsmOperand::SymStatic { def_id: _ } => (),
386+
_ => (),
370387
}
371388
}
372389

390+
slot_size = slot_size.max(slot_size_after_input);
391+
373392
self.stack_slots_clobber = slots_clobber;
374393
self.stack_slots_input = slots_input;
375394
self.stack_slots_output = slots_output;

0 commit comments

Comments
 (0)