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:
@@ -450,7 +450,7 @@ def emit_recipe_names(isa, fmt):
|
|||||||
This is used for pretty-printing encodings.
|
This is used for pretty-printing encodings.
|
||||||
"""
|
"""
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'pub static RECIPE_NAMES: [&\'static str; {}] = ['
|
'static RECIPE_NAMES: [&\'static str; {}] = ['
|
||||||
.format(len(isa.all_recipes)), '];'):
|
.format(len(isa.all_recipes)), '];'):
|
||||||
for r in isa.all_recipes:
|
for r in isa.all_recipes:
|
||||||
fmt.line('"{}",'.format(r.name))
|
fmt.line('"{}",'.format(r.name))
|
||||||
@@ -465,7 +465,7 @@ def emit_recipe_constraints(isa, fmt):
|
|||||||
properly encoded.
|
properly encoded.
|
||||||
"""
|
"""
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'pub static RECIPE_CONSTRAINTS: [RecipeConstraints; {}] = ['
|
'static RECIPE_CONSTRAINTS: [RecipeConstraints; {}] = ['
|
||||||
.format(len(isa.all_recipes)), '];'):
|
.format(len(isa.all_recipes)), '];'):
|
||||||
for r in isa.all_recipes:
|
for r in isa.all_recipes:
|
||||||
fmt.comment(r.name)
|
fmt.comment(r.name)
|
||||||
@@ -536,6 +536,11 @@ def gen_isa(isa, fmt):
|
|||||||
emit_recipe_names(isa, fmt)
|
emit_recipe_names(isa, fmt)
|
||||||
emit_recipe_constraints(isa, fmt)
|
emit_recipe_constraints(isa, fmt)
|
||||||
|
|
||||||
|
# Finally, tie it all together in an `EncInfo`.
|
||||||
|
with fmt.indented('pub static INFO: EncInfo = EncInfo {', '};'):
|
||||||
|
fmt.line('constraints: &RECIPE_CONSTRAINTS,')
|
||||||
|
fmt.line('names: &RECIPE_NAMES,')
|
||||||
|
|
||||||
|
|
||||||
def generate(isas, out_dir):
|
def generate(isas, out_dir):
|
||||||
# type: (Sequence[TargetISA], str) -> None
|
# type: (Sequence[TargetISA], str) -> None
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use ir::InstructionData;
|
use ir::InstructionData;
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::enc_tables::{Level1Entry, Level2Entry};
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
use isa::enc_tables::{Level1Entry, Level2Entry};
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/encoding-arm32.rs"));
|
include!(concat!(env!("OUT_DIR"), "/encoding-arm32.rs"));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use binemit::CodeSink;
|
|||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, Legalize, RecipeConstraints};
|
use isa::{TargetIsa, RegInfo, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -55,6 +55,10 @@ impl TargetIsa for Isa {
|
|||||||
registers::INFO.clone()
|
registers::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encoding_info(&self) -> EncInfo {
|
||||||
|
enc_tables::INFO.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
dfg: &ir::DataFlowGraph,
|
dfg: &ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData)
|
inst: &ir::InstructionData)
|
||||||
@@ -72,14 +76,6 @@ impl TargetIsa for Isa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recipe_names(&self) -> &'static [&'static str] {
|
|
||||||
&enc_tables::RECIPE_NAMES[..]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recipe_constraints(&self) -> &'static [RecipeConstraints] {
|
|
||||||
&enc_tables::RECIPE_CONSTRAINTS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use ir::InstructionData;
|
use ir::InstructionData;
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::enc_tables::{Level1Entry, Level2Entry};
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
use isa::enc_tables::{Level1Entry, Level2Entry};
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/encoding-arm64.rs"));
|
include!(concat!(env!("OUT_DIR"), "/encoding-arm64.rs"));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use binemit::CodeSink;
|
|||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{lookup_enclist, general_encoding};
|
use isa::enc_tables::{lookup_enclist, general_encoding};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, Legalize, RecipeConstraints};
|
use isa::{TargetIsa, RegInfo, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -48,6 +48,10 @@ impl TargetIsa for Isa {
|
|||||||
registers::INFO.clone()
|
registers::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encoding_info(&self) -> EncInfo {
|
||||||
|
enc_tables::INFO.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
dfg: &ir::DataFlowGraph,
|
dfg: &ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData)
|
inst: &ir::InstructionData)
|
||||||
@@ -65,14 +69,6 @@ impl TargetIsa for Isa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recipe_names(&self) -> &'static [&'static str] {
|
|
||||||
&enc_tables::RECIPE_NAMES[..]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recipe_constraints(&self) -> &'static [RecipeConstraints] {
|
|
||||||
&enc_tables::RECIPE_CONSTRAINTS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! The `Encoding` struct.
|
//! The `Encoding` struct.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use isa::constraints::RecipeConstraints;
|
||||||
|
|
||||||
/// Bits needed to encode an instruction as binary machine code.
|
/// Bits needed to encode an instruction as binary machine code.
|
||||||
///
|
///
|
||||||
@@ -76,3 +77,28 @@ impl fmt::Display for DisplayEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about all the encodings in this ISA.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct EncInfo {
|
||||||
|
/// Constraints on value operands per recipe.
|
||||||
|
pub constraints: &'static [RecipeConstraints],
|
||||||
|
|
||||||
|
/// Names of encoding recipes.
|
||||||
|
pub names: &'static [&'static str],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncInfo {
|
||||||
|
/// Get the value operand constraints for `enc` if it is a legal encoding.
|
||||||
|
pub fn operand_constraints(&self, enc: Encoding) -> Option<&RecipeConstraints> {
|
||||||
|
self.constraints.get(enc.recipe())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an object that can display an ISA-dependent encoding properly.
|
||||||
|
pub fn display(&self, enc: Encoding) -> DisplayEncoding {
|
||||||
|
DisplayEncoding {
|
||||||
|
encoding: enc,
|
||||||
|
recipe_names: self.names,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use ir::InstructionData;
|
use ir::InstructionData;
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::enc_tables::{Level1Entry, Level2Entry};
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
use isa::enc_tables::{Level1Entry, Level2Entry};
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/encoding-intel.rs"));
|
include!(concat!(env!("OUT_DIR"), "/encoding-intel.rs"));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use binemit::CodeSink;
|
|||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, Legalize, RecipeConstraints};
|
use isa::{TargetIsa, RegInfo, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -55,6 +55,10 @@ impl TargetIsa for Isa {
|
|||||||
registers::INFO.clone()
|
registers::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encoding_info(&self) -> EncInfo {
|
||||||
|
enc_tables::INFO.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
dfg: &ir::DataFlowGraph,
|
dfg: &ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData)
|
inst: &ir::InstructionData)
|
||||||
@@ -72,14 +76,6 @@ impl TargetIsa for Isa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recipe_names(&self) -> &'static [&'static str] {
|
|
||||||
&enc_tables::RECIPE_NAMES[..]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recipe_constraints(&self) -> &'static [RecipeConstraints] {
|
|
||||||
&enc_tables::RECIPE_CONSTRAINTS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,9 @@
|
|||||||
//! The configured target ISA trait object is a `Box<TargetIsa>` which can be used for multiple
|
//! The configured target ISA trait object is a `Box<TargetIsa>` which can be used for multiple
|
||||||
//! concurrent function compilations.
|
//! concurrent function compilations.
|
||||||
|
|
||||||
pub use isa::encoding::Encoding;
|
|
||||||
pub use isa::registers::{RegInfo, RegUnit, RegClass, RegClassIndex};
|
|
||||||
pub use isa::constraints::{RecipeConstraints, OperandConstraint, ConstraintKind};
|
pub use isa::constraints::{RecipeConstraints, OperandConstraint, ConstraintKind};
|
||||||
|
pub use isa::encoding::{Encoding, EncInfo};
|
||||||
|
pub use isa::registers::{RegInfo, RegUnit, RegClass, RegClassIndex};
|
||||||
|
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use settings;
|
use settings;
|
||||||
@@ -143,25 +143,8 @@ pub trait TargetIsa {
|
|||||||
/// This is also the main entry point for determining if an instruction is legal.
|
/// This is also the main entry point for determining if an instruction is legal.
|
||||||
fn encode(&self, dfg: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize>;
|
fn encode(&self, dfg: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize>;
|
||||||
|
|
||||||
/// Get a static array of names associated with encoding recipes in this ISA. Encoding recipes
|
/// Get a data structure describing the instruction encodings in this ISA.
|
||||||
/// are numbered starting from 0, corresponding to indexes into the name array.
|
fn encoding_info(&self) -> EncInfo;
|
||||||
///
|
|
||||||
/// This is just used for printing and parsing encodings in the textual IL format.
|
|
||||||
fn recipe_names(&self) -> &'static [&'static str];
|
|
||||||
|
|
||||||
/// Get a static array of value operand constraints associated with encoding recipes in this
|
|
||||||
/// ISA.
|
|
||||||
///
|
|
||||||
/// The constraints describe which registers can be used with an encoding recipe.
|
|
||||||
fn recipe_constraints(&self) -> &'static [RecipeConstraints];
|
|
||||||
|
|
||||||
/// Create an object that can display an ISA-dependent encoding properly.
|
|
||||||
fn display_enc(&self, enc: Encoding) -> encoding::DisplayEncoding {
|
|
||||||
encoding::DisplayEncoding {
|
|
||||||
encoding: enc,
|
|
||||||
recipe_names: self.recipe_names(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Legalize a function signature.
|
/// Legalize a function signature.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
//! Encoding tables for RISC-V.
|
//! Encoding tables for RISC-V.
|
||||||
|
|
||||||
use ir::condcodes::IntCC;
|
use ir::condcodes::IntCC;
|
||||||
use ir::{Opcode, InstructionData};
|
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use predicates;
|
use ir::{Opcode, InstructionData};
|
||||||
use isa::enc_tables::{Level1Entry, Level2Entry};
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
use isa::enc_tables::{Level1Entry, Level2Entry};
|
||||||
|
use predicates;
|
||||||
use super::registers::*;
|
use super::registers::*;
|
||||||
|
|
||||||
// Include the generated encoding tables:
|
// Include the generated encoding tables:
|
||||||
@@ -13,4 +14,5 @@ use super::registers::*;
|
|||||||
// - `LEVEL1_RV64`
|
// - `LEVEL1_RV64`
|
||||||
// - `LEVEL2`
|
// - `LEVEL2`
|
||||||
// - `ENCLIST`
|
// - `ENCLIST`
|
||||||
|
// - `INFO`
|
||||||
include!(concat!(env!("OUT_DIR"), "/encoding-riscv.rs"));
|
include!(concat!(env!("OUT_DIR"), "/encoding-riscv.rs"));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use super::super::settings as shared_settings;
|
|||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, Legalize, RecipeConstraints};
|
use isa::{TargetIsa, RegInfo, EncInfo, Encoding, Legalize};
|
||||||
use ir::{Function, Inst, InstructionData, DataFlowGraph, Signature};
|
use ir::{Function, Inst, InstructionData, DataFlowGraph, Signature};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -56,6 +56,10 @@ impl TargetIsa for Isa {
|
|||||||
registers::INFO.clone()
|
registers::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encoding_info(&self) -> EncInfo {
|
||||||
|
enc_tables::INFO.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn encode(&self, dfg: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize> {
|
fn encode(&self, dfg: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize> {
|
||||||
lookup_enclist(inst.ctrl_typevar(dfg),
|
lookup_enclist(inst.ctrl_typevar(dfg),
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
@@ -70,14 +74,6 @@ impl TargetIsa for Isa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recipe_names(&self) -> &'static [&'static str] {
|
|
||||||
&enc_tables::RECIPE_NAMES[..]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recipe_constraints(&self) -> &'static [RecipeConstraints] {
|
|
||||||
&enc_tables::RECIPE_CONSTRAINTS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn legalize_signature(&self, sig: &mut Signature) {
|
fn legalize_signature(&self, sig: &mut Signature) {
|
||||||
// We can pass in `self.isa_flags` too, if we need it.
|
// We can pass in `self.isa_flags` too, if we need it.
|
||||||
abi::legalize_signature(sig, &self.shared_flags)
|
abi::legalize_signature(sig, &self.shared_flags)
|
||||||
@@ -100,7 +96,7 @@ mod tests {
|
|||||||
use ir::{types, immediates};
|
use ir::{types, immediates};
|
||||||
|
|
||||||
fn encstr(isa: &isa::TargetIsa, enc: isa::Encoding) -> String {
|
fn encstr(isa: &isa::TargetIsa, enc: isa::Encoding) -> String {
|
||||||
isa.display_enc(enc).to_string()
|
isa.encoding_info().display(enc).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -38,7 +38,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};
|
||||||
use isa::{TargetIsa, RegInfo, Encoding, RecipeConstraints, 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;
|
||||||
use regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
|
use regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
|
||||||
@@ -69,7 +69,7 @@ struct Context<'a> {
|
|||||||
// Cached ISA information.
|
// Cached ISA information.
|
||||||
// We save it here to avoid frequent virtual function calls on the `TargetIsa` trait object.
|
// We save it here to avoid frequent virtual function calls on the `TargetIsa` trait object.
|
||||||
reginfo: RegInfo,
|
reginfo: RegInfo,
|
||||||
recipe_constraints: &'a [RecipeConstraints],
|
encinfo: EncInfo,
|
||||||
|
|
||||||
// References to contextual data structures we need.
|
// References to contextual data structures we need.
|
||||||
domtree: &'a DominatorTree,
|
domtree: &'a DominatorTree,
|
||||||
@@ -98,7 +98,7 @@ impl Coloring {
|
|||||||
tracker: &mut LiveValueTracker) {
|
tracker: &mut LiveValueTracker) {
|
||||||
let mut ctx = Context {
|
let mut ctx = Context {
|
||||||
reginfo: isa.register_info(),
|
reginfo: isa.register_info(),
|
||||||
recipe_constraints: isa.recipe_constraints(),
|
encinfo: isa.encoding_info(),
|
||||||
domtree: domtree,
|
domtree: domtree,
|
||||||
liveness: liveness,
|
liveness: liveness,
|
||||||
// TODO: Ask the target ISA about reserved registers etc.
|
// 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);
|
let (kills, defs) = tracker.process_inst(inst, dfg, self.liveness);
|
||||||
|
|
||||||
// Get the operand constraints for `inst` that we are trying to satisfy.
|
// 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.
|
// Get rid of the killed values.
|
||||||
for lv in kills {
|
for lv in kills {
|
||||||
|
|||||||
@@ -178,7 +178,7 @@
|
|||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::ControlFlowGraph;
|
||||||
use ir::dfg::ValueDef;
|
use ir::dfg::ValueDef;
|
||||||
use ir::{Function, Value, Inst, Ebb};
|
use ir::{Function, Value, Inst, Ebb};
|
||||||
use isa::{TargetIsa, RecipeConstraints};
|
use isa::{TargetIsa, EncInfo};
|
||||||
use regalloc::affinity::Affinity;
|
use regalloc::affinity::Affinity;
|
||||||
use regalloc::liverange::LiveRange;
|
use regalloc::liverange::LiveRange;
|
||||||
use sparse_map::SparseMap;
|
use sparse_map::SparseMap;
|
||||||
@@ -191,7 +191,7 @@ type LiveRangeSet = SparseMap<Value, LiveRange>;
|
|||||||
fn get_or_create<'a>(lrset: &'a mut LiveRangeSet,
|
fn get_or_create<'a>(lrset: &'a mut LiveRangeSet,
|
||||||
value: Value,
|
value: Value,
|
||||||
func: &Function,
|
func: &Function,
|
||||||
recipe_constraints: &[RecipeConstraints])
|
enc_info: &EncInfo)
|
||||||
-> &'a mut LiveRange {
|
-> &'a mut LiveRange {
|
||||||
// It would be better to use `get_mut()` here, but that leads to borrow checker fighting
|
// 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.
|
// 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();
|
def = inst.into();
|
||||||
// Initialize the affinity from the defining instruction's result constraints.
|
// 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.
|
// Don't do this for call return values which are always tied to a single register.
|
||||||
affinity = recipe_constraints
|
affinity = enc_info
|
||||||
.get(func.encodings[inst].recipe())
|
.operand_constraints(func.encodings[inst])
|
||||||
.and_then(|rc| rc.outs.get(rnum))
|
.and_then(|rc| rc.outs.get(rnum))
|
||||||
.map(Affinity::new)
|
.map(Affinity::new)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@@ -296,7 +296,7 @@ impl Liveness {
|
|||||||
self.ranges.clear();
|
self.ranges.clear();
|
||||||
|
|
||||||
// Get ISA data structures used for computing live range affinities.
|
// 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();
|
let reg_info = isa.register_info();
|
||||||
|
|
||||||
// The liveness computation needs to visit all uses, but the order doesn't matter.
|
// 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
|
// TODO: When we implement DCE, we can use the absence of a live range to indicate
|
||||||
// an unused value.
|
// an unused value.
|
||||||
for def in func.dfg.inst_results(inst) {
|
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.
|
// Iterator of constraints, one per value operand.
|
||||||
// TODO: Should we fail here if the instruction doesn't have a valid encoding?
|
// TODO: Should we fail here if the instruction doesn't have a valid encoding?
|
||||||
let mut operand_constraints = recipe_constraints
|
let mut operand_constraints = enc_info
|
||||||
.get(recipe)
|
.operand_constraints(func.encodings[inst])
|
||||||
.map(|c| c.ins)
|
.map(|c| c.ins)
|
||||||
.unwrap_or(&[])
|
.unwrap_or(&[])
|
||||||
.iter();
|
.iter();
|
||||||
|
|
||||||
for &arg in func.dfg.inst_args(inst) {
|
for &arg in func.dfg.inst_args(inst) {
|
||||||
// Get the live range, create it as a dead range if necessary.
|
// 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 the live range to reach this use.
|
||||||
extend_to_use(lr, ebb, inst, &mut self.worklist, func, cfg);
|
extend_to_use(lr, ebb, inst, &mut self.worklist, func, cfg);
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ fn write_instruction(w: &mut Write,
|
|||||||
if let Some(enc) = func.encodings.get(inst).cloned() {
|
if let Some(enc) = func.encodings.get(inst).cloned() {
|
||||||
let mut s = String::with_capacity(16);
|
let mut s = String::with_capacity(16);
|
||||||
if let Some(isa) = isa {
|
if let Some(isa) = isa {
|
||||||
write!(s, "[{}", isa.display_enc(enc))?;
|
write!(s, "[{}", isa.encoding_info().display(enc))?;
|
||||||
// Write value locations, if we have them.
|
// Write value locations, if we have them.
|
||||||
if !func.locations.is_empty() {
|
if !func.locations.is_empty() {
|
||||||
let regs = isa.register_info();
|
let regs = isa.register_info();
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ impl<'a> Context<'a> {
|
|||||||
fn find_recipe_index(&self, recipe_name: &str) -> Option<u16> {
|
fn find_recipe_index(&self, recipe_name: &str) -> Option<u16> {
|
||||||
if let Some(unique_isa) = self.unique_isa {
|
if let Some(unique_isa) = self.unique_isa {
|
||||||
unique_isa
|
unique_isa
|
||||||
.recipe_names()
|
.encoding_info()
|
||||||
|
.names
|
||||||
.iter()
|
.iter()
|
||||||
.position(|&name| name == recipe_name)
|
.position(|&name| name == recipe_name)
|
||||||
.map(|idx| idx as u16)
|
.map(|idx| idx as u16)
|
||||||
|
|||||||
Reference in New Issue
Block a user