Color entry block arguments using the function signature.
The arguments to the entry block arrive in registers determined by the ABI. This information is stored in the signature. Use a separate function for coloring entry block arguments using the signature information. We can't handle stack arguments yet.
This commit is contained in:
@@ -6,8 +6,7 @@ isa riscv
|
|||||||
function add(i32, i32) {
|
function add(i32, i32) {
|
||||||
ebb0(v1: i32, v2: i32):
|
ebb0(v1: i32, v2: i32):
|
||||||
v3 = iadd v1, v2
|
v3 = iadd v1, v2
|
||||||
; TODO: This shouldn't clobber the link register.
|
; check: [R#0c,%x5]
|
||||||
; check: [R#0c,%x1]
|
|
||||||
; sameln: iadd
|
; sameln: iadd
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
use entity_map::EntityMap;
|
use entity_map::EntityMap;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use ir::{Ebb, Inst, Value, Function, Cursor, ValueLoc, DataFlowGraph};
|
use ir::{Ebb, Inst, Value, Function, Cursor, ValueLoc, DataFlowGraph, Signature, ArgumentLoc};
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, EncInfo, ConstraintKind};
|
use isa::{TargetIsa, RegInfo, Encoding, EncInfo, ConstraintKind};
|
||||||
use regalloc::affinity::Affinity;
|
use regalloc::affinity::Affinity;
|
||||||
use regalloc::allocatable_set::AllocatableSet;
|
use regalloc::allocatable_set::AllocatableSet;
|
||||||
@@ -180,14 +180,15 @@ impl<'a> Context<'a> {
|
|||||||
let (liveins, args) =
|
let (liveins, args) =
|
||||||
tracker.ebb_top(ebb, &func.dfg, self.liveness, &func.layout, self.domtree);
|
tracker.ebb_top(ebb, &func.dfg, self.liveness, &func.layout, self.domtree);
|
||||||
|
|
||||||
// The live-ins have already been assigned a register. Reconstruct the allocatable set.
|
// Arguments to the entry block have ABI constraints.
|
||||||
let mut regs = self.livein_regs(liveins, func);
|
if func.layout.entry_block() == Some(ebb) {
|
||||||
|
assert_eq!(liveins.len(), 0);
|
||||||
// TODO: Arguments to the entry block are pre-colored by the ABI. We should probably call
|
self.color_entry_args(&func.signature, args, &mut func.locations)
|
||||||
// a whole other function for that case.
|
} else {
|
||||||
self.color_args(args, &mut regs, &mut func.locations);
|
// The live-ins have already been assigned a register. Reconstruct the allocatable set.
|
||||||
|
let regs = self.livein_regs(liveins, func);
|
||||||
regs
|
self.color_args(args, regs, &mut func.locations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize a set of allocatable registers from the values that are live-in to a block.
|
/// Initialize a set of allocatable registers from the values that are live-in to a block.
|
||||||
@@ -218,14 +219,68 @@ impl<'a> Context<'a> {
|
|||||||
regs
|
regs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Color the arguments to the entry block.
|
||||||
|
///
|
||||||
|
/// These are function arguments that should already have assigned register units in the
|
||||||
|
/// function signature.
|
||||||
|
///
|
||||||
|
/// Return the set of remaining allocatable registers.
|
||||||
|
fn color_entry_args(&self,
|
||||||
|
sig: &Signature,
|
||||||
|
args: &[LiveValue],
|
||||||
|
locations: &mut EntityMap<Value, ValueLoc>)
|
||||||
|
-> AllocatableSet {
|
||||||
|
assert_eq!(sig.argument_types.len(), args.len());
|
||||||
|
|
||||||
|
let mut regs = self.usable_regs.clone();
|
||||||
|
|
||||||
|
for (lv, abi) in args.iter().zip(&sig.argument_types) {
|
||||||
|
match lv.affinity {
|
||||||
|
Affinity::Reg(rc_index) => {
|
||||||
|
let regclass = self.reginfo.rc(rc_index);
|
||||||
|
if let ArgumentLoc::Reg(regunit) = abi.location {
|
||||||
|
regs.take(regclass, regunit);
|
||||||
|
*locations.ensure(lv.value) = ValueLoc::Reg(regunit);
|
||||||
|
} else {
|
||||||
|
// This should have been fixed by the reload pass.
|
||||||
|
panic!("Entry arg {} has {} affinity, but ABI {}",
|
||||||
|
lv.value,
|
||||||
|
lv.affinity.display(&self.reginfo),
|
||||||
|
abi.display(&self.reginfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Affinity::Stack => {
|
||||||
|
if let ArgumentLoc::Stack(_offset) = abi.location {
|
||||||
|
// TODO: Allocate a stack slot at incoming offset and assign it.
|
||||||
|
panic!("Unimplemented {}: {} stack allocation",
|
||||||
|
lv.value,
|
||||||
|
abi.display(&self.reginfo));
|
||||||
|
} else {
|
||||||
|
// This should have been fixed by the reload pass.
|
||||||
|
panic!("Entry arg {} has stack affinity, but ABI {}",
|
||||||
|
lv.value,
|
||||||
|
abi.display(&self.reginfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This is a ghost value, unused in the function. Don't assign it to a location
|
||||||
|
// either.
|
||||||
|
Affinity::None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs
|
||||||
|
}
|
||||||
|
|
||||||
/// Color the live arguments to the current block.
|
/// Color the live arguments to the current block.
|
||||||
///
|
///
|
||||||
/// It is assumed that any live-in register values have already been taken out of the register
|
/// It is assumed that any live-in register values have already been taken out of the register
|
||||||
/// set.
|
/// set.
|
||||||
fn color_args(&self,
|
fn color_args(&self,
|
||||||
args: &[LiveValue],
|
args: &[LiveValue],
|
||||||
regs: &mut AllocatableSet,
|
mut regs: AllocatableSet,
|
||||||
locations: &mut EntityMap<Value, ValueLoc>) {
|
locations: &mut EntityMap<Value, ValueLoc>)
|
||||||
|
-> AllocatableSet {
|
||||||
for lv in args {
|
for lv in args {
|
||||||
// Only look at the register arguments.
|
// Only look at the register arguments.
|
||||||
if let Affinity::Reg(rc_index) = lv.affinity {
|
if let Affinity::Reg(rc_index) = lv.affinity {
|
||||||
@@ -238,6 +293,8 @@ impl<'a> Context<'a> {
|
|||||||
*locations.ensure(lv.value) = ValueLoc::Reg(regunit);
|
*locations.ensure(lv.value) = ValueLoc::Reg(regunit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Color the values defined by `inst` and insert any necessary shuffle code to satisfy
|
/// Color the values defined by `inst` and insert any necessary shuffle code to satisfy
|
||||||
|
|||||||
Reference in New Issue
Block a user