Don't coalesce incoming stack arguments.
A function parameter in an incoming_arg stack slot should not be coalesced into any virtual registers. We don't want to force the whole virtual register to spill to the incoming_arg slot.
This commit is contained in:
@@ -91,3 +91,21 @@ ebb1(v10: i32, v11: i32):
|
|||||||
brnz v13, ebb1(v11, v12)
|
brnz v13, ebb1(v11, v12)
|
||||||
return v12
|
return v12
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function arguments passed on the stack aren't allowed to be part of a virtual
|
||||||
|
; register, at least for now. This is because the other values in the virtual
|
||||||
|
; register would need to be spilled to the incoming_arg stack slot which we treat
|
||||||
|
; as belonging to the caller.
|
||||||
|
function %stackarg(i32, i32, i32, i32, i32, i32, i32, i32, i32) -> i32 {
|
||||||
|
; check: ss0 = incoming_arg 4
|
||||||
|
; not: incoming_arg
|
||||||
|
ebb0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v8: i32):
|
||||||
|
; check: fill v8
|
||||||
|
; not: v8
|
||||||
|
brnz v0, ebb1(v8)
|
||||||
|
jump ebb1(v7)
|
||||||
|
|
||||||
|
ebb1(v10: i32):
|
||||||
|
v11 = iadd_imm v10, 1
|
||||||
|
return v11
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use flowgraph::{ControlFlowGraph, BasicBlock};
|
use flowgraph::{ControlFlowGraph, BasicBlock};
|
||||||
use ir::{DataFlowGraph, Layout, Cursor, InstBuilder};
|
use ir::{DataFlowGraph, Layout, Cursor, InstBuilder, ValueDef};
|
||||||
use ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint};
|
use ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint};
|
||||||
use regalloc::affinity::Affinity;
|
use regalloc::affinity::Affinity;
|
||||||
use regalloc::liveness::Liveness;
|
use regalloc::liveness::Liveness;
|
||||||
@@ -400,6 +400,22 @@ impl<'a> Context<'a> {
|
|||||||
pred_val,
|
pred_val,
|
||||||
pred_ebb,
|
pred_ebb,
|
||||||
self.func.dfg.display_inst(pred_inst));
|
self.func.dfg.display_inst(pred_inst));
|
||||||
|
|
||||||
|
// Never coalesce incoming function arguments on the stack. These arguments are
|
||||||
|
// pre-spilled, and the rest of the virtual register would be forced to spill to the
|
||||||
|
// `incoming_arg` stack slot too.
|
||||||
|
if let ValueDef::Arg(def_ebb, def_num) = self.func.dfg.value_def(pred_val) {
|
||||||
|
if Some(def_ebb) == self.func.layout.entry_block() &&
|
||||||
|
self.func.signature.argument_types[def_num]
|
||||||
|
.location
|
||||||
|
.is_stack() {
|
||||||
|
dbg!("Isolating incoming stack parameter {}", pred_val);
|
||||||
|
let new_val = self.split_pred(pred_inst, pred_ebb, argnum, pred_val);
|
||||||
|
assert!(self.add_class(new_val).is_ok());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Err((a, b)) = self.add_class(pred_val) {
|
if let Err((a, b)) = self.add_class(pred_val) {
|
||||||
dbg!("Found conflict between {} and {}", a, b);
|
dbg!("Found conflict between {} and {}", a, b);
|
||||||
// We have a conflict between the already merged value `a` and one of the new
|
// We have a conflict between the already merged value `a` and one of the new
|
||||||
|
|||||||
Reference in New Issue
Block a user