Move encoding-related information into an EncInfo struct.
The tables returned by recipe_names() and recipe_constraints() are now collected into an EncInfo struct that is available from TargetIsa::encoding_info(). This is equivalent to the register bank tables available fro TargetIsa::register_info(). This cleans of the TargetIsa interface and makes it easier to add encoding-related information.
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
use entity_map::EntityMap;
|
||||
use dominator_tree::DominatorTree;
|
||||
use ir::{Ebb, Inst, Value, Function, Cursor, ValueLoc, DataFlowGraph};
|
||||
use isa::{TargetIsa, RegInfo, Encoding, RecipeConstraints, ConstraintKind};
|
||||
use isa::{TargetIsa, RegInfo, Encoding, EncInfo, ConstraintKind};
|
||||
use regalloc::affinity::Affinity;
|
||||
use regalloc::allocatable_set::AllocatableSet;
|
||||
use regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
|
||||
@@ -69,7 +69,7 @@ struct Context<'a> {
|
||||
// Cached ISA information.
|
||||
// We save it here to avoid frequent virtual function calls on the `TargetIsa` trait object.
|
||||
reginfo: RegInfo,
|
||||
recipe_constraints: &'a [RecipeConstraints],
|
||||
encinfo: EncInfo,
|
||||
|
||||
// References to contextual data structures we need.
|
||||
domtree: &'a DominatorTree,
|
||||
@@ -98,7 +98,7 @@ impl Coloring {
|
||||
tracker: &mut LiveValueTracker) {
|
||||
let mut ctx = Context {
|
||||
reginfo: isa.register_info(),
|
||||
recipe_constraints: isa.recipe_constraints(),
|
||||
encinfo: isa.encoding_info(),
|
||||
domtree: domtree,
|
||||
liveness: liveness,
|
||||
// TODO: Ask the target ISA about reserved registers etc.
|
||||
@@ -259,7 +259,10 @@ impl<'a> Context<'a> {
|
||||
let (kills, defs) = tracker.process_inst(inst, dfg, self.liveness);
|
||||
|
||||
// Get the operand constraints for `inst` that we are trying to satisfy.
|
||||
let constraints = self.recipe_constraints[encoding.recipe()].clone();
|
||||
let constraints = self.encinfo
|
||||
.operand_constraints(encoding)
|
||||
.expect("Missing instruction encoding")
|
||||
.clone();
|
||||
|
||||
// Get rid of the killed values.
|
||||
for lv in kills {
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir::dfg::ValueDef;
|
||||
use ir::{Function, Value, Inst, Ebb};
|
||||
use isa::{TargetIsa, RecipeConstraints};
|
||||
use isa::{TargetIsa, EncInfo};
|
||||
use regalloc::affinity::Affinity;
|
||||
use regalloc::liverange::LiveRange;
|
||||
use sparse_map::SparseMap;
|
||||
@@ -191,7 +191,7 @@ type LiveRangeSet = SparseMap<Value, LiveRange>;
|
||||
fn get_or_create<'a>(lrset: &'a mut LiveRangeSet,
|
||||
value: Value,
|
||||
func: &Function,
|
||||
recipe_constraints: &[RecipeConstraints])
|
||||
enc_info: &EncInfo)
|
||||
-> &'a mut LiveRange {
|
||||
// It would be better to use `get_mut()` here, but that leads to borrow checker fighting
|
||||
// which can probably only be resolved by non-lexical lifetimes.
|
||||
@@ -205,8 +205,8 @@ fn get_or_create<'a>(lrset: &'a mut LiveRangeSet,
|
||||
def = inst.into();
|
||||
// Initialize the affinity from the defining instruction's result constraints.
|
||||
// Don't do this for call return values which are always tied to a single register.
|
||||
affinity = recipe_constraints
|
||||
.get(func.encodings[inst].recipe())
|
||||
affinity = enc_info
|
||||
.operand_constraints(func.encodings[inst])
|
||||
.and_then(|rc| rc.outs.get(rnum))
|
||||
.map(Affinity::new)
|
||||
.unwrap_or_default();
|
||||
@@ -296,7 +296,7 @@ impl Liveness {
|
||||
self.ranges.clear();
|
||||
|
||||
// Get ISA data structures used for computing live range affinities.
|
||||
let recipe_constraints = isa.recipe_constraints();
|
||||
let enc_info = isa.encoding_info();
|
||||
let reg_info = isa.register_info();
|
||||
|
||||
// The liveness computation needs to visit all uses, but the order doesn't matter.
|
||||
@@ -309,22 +309,20 @@ impl Liveness {
|
||||
// TODO: When we implement DCE, we can use the absence of a live range to indicate
|
||||
// an unused value.
|
||||
for def in func.dfg.inst_results(inst) {
|
||||
get_or_create(&mut self.ranges, def, func, recipe_constraints);
|
||||
get_or_create(&mut self.ranges, def, func, &enc_info);
|
||||
}
|
||||
|
||||
// The instruction encoding is used to compute affinities.
|
||||
let recipe = func.encodings[inst].recipe();
|
||||
// Iterator of constraints, one per value operand.
|
||||
// TODO: Should we fail here if the instruction doesn't have a valid encoding?
|
||||
let mut operand_constraints = recipe_constraints
|
||||
.get(recipe)
|
||||
let mut operand_constraints = enc_info
|
||||
.operand_constraints(func.encodings[inst])
|
||||
.map(|c| c.ins)
|
||||
.unwrap_or(&[])
|
||||
.iter();
|
||||
|
||||
for &arg in func.dfg.inst_args(inst) {
|
||||
// Get the live range, create it as a dead range if necessary.
|
||||
let lr = get_or_create(&mut self.ranges, arg, func, recipe_constraints);
|
||||
let lr = get_or_create(&mut self.ranges, arg, func, &enc_info);
|
||||
|
||||
// Extend the live range to reach this use.
|
||||
extend_to_use(lr, ebb, inst, &mut self.worklist, func, cfg);
|
||||
|
||||
Reference in New Issue
Block a user