Spill live-ins and EBB arguments if there are too many.
This commit is contained in:
@@ -121,3 +121,26 @@ ebb0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32):
|
|||||||
v10 = iadd v6, v7
|
v10 = iadd v6, v7
|
||||||
return v10
|
return v10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; More EBB arguments than registers.
|
||||||
|
function %ebbargs(i32) -> i32 {
|
||||||
|
ebb0(v1: i32):
|
||||||
|
; check: $v1 = spill
|
||||||
|
v2 = iconst.i32 1
|
||||||
|
jump ebb1(v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2)
|
||||||
|
|
||||||
|
ebb1(v10: i32, v11: i32, v12: i32, v13: i32, v14: i32, v15: i32, v16: i32, v17: i32, v18: i32, v19: i32, v20: i32, v21: i32):
|
||||||
|
v22 = iadd v10, v11
|
||||||
|
v23 = iadd v22, v12
|
||||||
|
v24 = iadd v23, v13
|
||||||
|
v25 = iadd v24, v14
|
||||||
|
v26 = iadd v25, v15
|
||||||
|
v27 = iadd v26, v16
|
||||||
|
v28 = iadd v27, v17
|
||||||
|
v29 = iadd v28, v18
|
||||||
|
v30 = iadd v29, v19
|
||||||
|
v31 = iadd v30, v20
|
||||||
|
v32 = iadd v31, v21
|
||||||
|
v33 = iadd v32, v1
|
||||||
|
return v33
|
||||||
|
}
|
||||||
|
|||||||
@@ -224,6 +224,14 @@ impl Pressure {
|
|||||||
e.transient_count = 0;
|
e.transient_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Preserve the transient counts by transferring them to the base counts.
|
||||||
|
pub fn preserve_transient(&mut self) {
|
||||||
|
for e in &mut self.toprc {
|
||||||
|
e.base_count += e.transient_count;
|
||||||
|
e.transient_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Pressure {
|
impl fmt::Display for Pressure {
|
||||||
|
|||||||
@@ -200,8 +200,42 @@ impl<'a> Context<'a> {
|
|||||||
self.pressure.reset();
|
self.pressure.reset();
|
||||||
self.take_live_regs(liveins);
|
self.take_live_regs(liveins);
|
||||||
|
|
||||||
// TODO: Process and count EBB arguments. Some may need spilling.
|
// An EBB can have an arbitrary (up to 2^16...) number of EBB arguments, so they are not
|
||||||
self.take_live_regs(args);
|
// guaranteed to fit in registers.
|
||||||
|
for lv in args {
|
||||||
|
if let Affinity::Reg(rci) = lv.affinity {
|
||||||
|
let rc = self.reginfo.rc(rci);
|
||||||
|
'try_take: while let Err(mask) = self.pressure.take_transient(rc) {
|
||||||
|
dbg!("Need {} reg for EBB argument {} from {} live-ins",
|
||||||
|
rc,
|
||||||
|
lv.value,
|
||||||
|
liveins.len());
|
||||||
|
match self.spill_candidate(mask, liveins, dfg, layout) {
|
||||||
|
Some(cand) => {
|
||||||
|
dbg!("Spilling live-in {} to make room for {} EBB argument {}",
|
||||||
|
cand,
|
||||||
|
rc,
|
||||||
|
lv.value);
|
||||||
|
self.spill_reg(cand, dfg);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// We can't spill any of the live-in registers, so we have to spill an
|
||||||
|
// EBB argument. Since the current spill metric would consider all the
|
||||||
|
// EBB arguments equal, just spill the present register.
|
||||||
|
dbg!("Spilling {} EBB argument {}", rc, lv.value);
|
||||||
|
|
||||||
|
// Since `spill_reg` will free a register, add the current one here.
|
||||||
|
self.pressure.take(rc);
|
||||||
|
self.spill_reg(lv.value, dfg);
|
||||||
|
break 'try_take;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The transient pressure counts for the EBB arguments are accurate. Just preserve them.
|
||||||
|
self.pressure.preserve_transient();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_inst(&mut self,
|
fn visit_inst(&mut self,
|
||||||
|
|||||||
Reference in New Issue
Block a user