Cursor library.
Add a new cursor module and define an EncCursor data type in it. An EncCursor is a cursor that inserts instructions with a valid encoding for the ISA. This is useful for passes generating code after legalization. Implement a builder interface via the new InstInserterBase trait such that the EncCursor builders support with_result(). Use EncCursor in coalescing.rs instead of the layout cursor as a proof of concept.
This commit is contained in:
105
lib/cretonne/src/cursor.rs
Normal file
105
lib/cretonne/src/cursor.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
//! Cursor library.
|
||||
//!
|
||||
//! This module defines cursor data types that can be used for inserting instructions.
|
||||
|
||||
use ir;
|
||||
use isa::TargetIsa;
|
||||
|
||||
// Re-export these types, anticipating their being moved here.
|
||||
pub use ir::layout::CursorBase as Cursor;
|
||||
pub use ir::layout::CursorPosition;
|
||||
pub use ir::layout::Cursor as LayoutCursor;
|
||||
|
||||
/// Encoding cursor.
|
||||
///
|
||||
/// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding.
|
||||
/// The cursor holds a mutable reference to the whole function which can be re-borrowed from the
|
||||
/// public `pos.func` member.
|
||||
pub struct EncCursor<'f> {
|
||||
pos: CursorPosition,
|
||||
built_inst: Option<ir::Inst>,
|
||||
pub func: &'f mut ir::Function,
|
||||
pub isa: &'f TargetIsa,
|
||||
}
|
||||
|
||||
impl<'f> EncCursor<'f> {
|
||||
/// Create a new `EncCursor` pointing nowhere.
|
||||
pub fn new(func: &'f mut ir::Function, isa: &'f TargetIsa) -> EncCursor<'f> {
|
||||
EncCursor {
|
||||
pos: CursorPosition::Nowhere,
|
||||
built_inst: None,
|
||||
func,
|
||||
isa,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instruction builder that will insert an encoded instruction at the current
|
||||
/// position.
|
||||
///
|
||||
/// The builder will panic if it is used to insert an instruction that can't be encoded for
|
||||
/// `self.isa`.
|
||||
pub fn ins(&mut self) -> ir::InsertBuilder<&mut EncCursor<'f>> {
|
||||
ir::InsertBuilder::new(self)
|
||||
}
|
||||
|
||||
/// Get the last built instruction.
|
||||
///
|
||||
/// This returns the last instruction that was built using the `ins()` method on this cursor.
|
||||
/// Panics if no instruction was built.
|
||||
pub fn built_inst(&self) -> ir::Inst {
|
||||
self.built_inst.expect("No instruction was inserted")
|
||||
}
|
||||
|
||||
/// Return an object that can display `inst`.
|
||||
///
|
||||
/// This is a convenience wrapper for the DFG equivalent.
|
||||
pub fn display_inst(&self, inst: ir::Inst) -> ir::dfg::DisplayInst {
|
||||
self.func.dfg.display_inst(inst, self.isa)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f> Cursor for EncCursor<'f> {
|
||||
fn position(&self) -> CursorPosition {
|
||||
self.pos
|
||||
}
|
||||
|
||||
fn set_position(&mut self, pos: CursorPosition) {
|
||||
self.pos = pos
|
||||
}
|
||||
|
||||
fn layout(&self) -> &ir::Layout {
|
||||
&self.func.layout
|
||||
}
|
||||
|
||||
fn layout_mut(&mut self) -> &mut ir::Layout {
|
||||
&mut self.func.layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> {
|
||||
fn data_flow_graph(&self) -> &ir::DataFlowGraph {
|
||||
&self.func.dfg
|
||||
}
|
||||
|
||||
fn data_flow_graph_mut(&mut self) -> &mut ir::DataFlowGraph {
|
||||
&mut self.func.dfg
|
||||
}
|
||||
|
||||
fn insert_built_inst(self,
|
||||
inst: ir::Inst,
|
||||
ctrl_typevar: ir::Type)
|
||||
-> &'c mut ir::DataFlowGraph {
|
||||
// Insert the instruction and remember the reference.
|
||||
self.insert_inst(inst);
|
||||
self.built_inst = Some(inst);
|
||||
|
||||
// Assign an encoding.
|
||||
match self.isa
|
||||
.encode(&self.func.dfg, &self.func.dfg[inst], ctrl_typevar) {
|
||||
Ok(e) => *self.func.encodings.ensure(inst) = e,
|
||||
Err(_) => panic!("can't encode {}", self.display_inst(inst)),
|
||||
}
|
||||
|
||||
&mut self.func.dfg
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ pub mod verifier;
|
||||
mod abi;
|
||||
mod constant_hash;
|
||||
mod context;
|
||||
mod cursor;
|
||||
mod iterators;
|
||||
mod legalizer;
|
||||
mod licm;
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
//! and inserting copies where necessary such that all values passed to an EBB argument will belong
|
||||
//! to the same virtual register as the EBB argument value itself.
|
||||
|
||||
use cursor::{Cursor, EncCursor};
|
||||
use dbg::DisplayList;
|
||||
use dominator_tree::DominatorTree;
|
||||
use flowgraph::{ControlFlowGraph, BasicBlock};
|
||||
use ir::{DataFlowGraph, Layout, Cursor, CursorBase, InstBuilder, ValueDef};
|
||||
use ir::{DataFlowGraph, Layout, InstBuilder, ValueDef};
|
||||
use ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint};
|
||||
use regalloc::affinity::Affinity;
|
||||
use regalloc::liveness::Liveness;
|
||||
@@ -464,37 +465,26 @@ impl<'a> Context<'a> {
|
||||
argnum: usize,
|
||||
pred_val: Value)
|
||||
-> Value {
|
||||
let copy;
|
||||
{
|
||||
let mut pos = Cursor::new(&mut self.func.layout).at_inst(pred_inst);
|
||||
copy = self.func.dfg.ins(&mut pos).copy(pred_val);
|
||||
}
|
||||
let inst = self.func.dfg.value_def(copy).unwrap_inst();
|
||||
let ty = self.func.dfg.value_type(copy);
|
||||
let mut pos = EncCursor::new(self.func, self.isa).at_inst(pred_inst);
|
||||
let copy = pos.ins().copy(pred_val);
|
||||
let inst = pos.built_inst();
|
||||
|
||||
dbg!("Inserted {}, before {}: {}",
|
||||
self.func.dfg.display_inst(inst, self.isa),
|
||||
pos.display_inst(inst),
|
||||
pred_ebb,
|
||||
self.func.dfg.display_inst(pred_inst, self.isa));
|
||||
|
||||
// Give it an encoding.
|
||||
let encoding = match self.isa.encode(&self.func.dfg, &self.func.dfg[inst], ty) {
|
||||
Ok(e) => e,
|
||||
Err(_) => panic!("Can't encode copy.{}", ty),
|
||||
};
|
||||
*self.func.encodings.ensure(inst) = encoding;
|
||||
pos.display_inst(pred_inst));
|
||||
|
||||
// Create a live range for the new value.
|
||||
let affinity = Affinity::new(&self.encinfo
|
||||
.operand_constraints(encoding)
|
||||
.operand_constraints(pos.func.encodings[inst])
|
||||
.expect("Bad copy encoding")
|
||||
.outs
|
||||
[0]);
|
||||
self.liveness.create_dead(copy, inst, affinity);
|
||||
self.liveness
|
||||
.extend_locally(copy, pred_ebb, pred_inst, &self.func.layout);
|
||||
.extend_locally(copy, pred_ebb, pred_inst, &pos.func.layout);
|
||||
|
||||
self.func.dfg.inst_variable_args_mut(pred_inst)[argnum] = copy;
|
||||
pos.func.dfg.inst_variable_args_mut(pred_inst)[argnum] = copy;
|
||||
self.split_values.push(copy);
|
||||
copy
|
||||
}
|
||||
@@ -505,39 +495,26 @@ impl<'a> Context<'a> {
|
||||
let new_val = self.func.dfg.replace_ebb_arg(succ_val, ty);
|
||||
|
||||
// Insert a copy instruction at the top of ebb.
|
||||
{
|
||||
let mut pos = Cursor::new(&mut self.func.layout).at_first_inst(ebb);
|
||||
self.func
|
||||
.dfg
|
||||
.ins(&mut pos)
|
||||
.with_result(succ_val)
|
||||
.copy(new_val);
|
||||
}
|
||||
let inst = self.func.dfg.value_def(succ_val).unwrap_inst();
|
||||
let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb);
|
||||
pos.ins().with_result(succ_val).copy(new_val);
|
||||
let inst = pos.built_inst();
|
||||
self.liveness.move_def_locally(succ_val, inst);
|
||||
|
||||
dbg!("Inserted {}, following {}({}: {})",
|
||||
self.func.dfg.display_inst(inst, self.isa),
|
||||
pos.display_inst(inst),
|
||||
ebb,
|
||||
new_val,
|
||||
ty);
|
||||
|
||||
// Give it an encoding.
|
||||
let encoding = match self.isa.encode(&self.func.dfg, &self.func.dfg[inst], ty) {
|
||||
Ok(e) => e,
|
||||
Err(_) => panic!("Can't encode copy.{}", ty),
|
||||
};
|
||||
*self.func.encodings.ensure(inst) = encoding;
|
||||
|
||||
// Create a live range for the new value.
|
||||
let affinity = Affinity::new(&self.encinfo
|
||||
.operand_constraints(encoding)
|
||||
.operand_constraints(pos.func.encodings[inst])
|
||||
.expect("Bad copy encoding")
|
||||
.outs
|
||||
[0]);
|
||||
self.liveness.create_dead(new_val, ebb, affinity);
|
||||
self.liveness
|
||||
.extend_locally(new_val, ebb, inst, &self.func.layout);
|
||||
.extend_locally(new_val, ebb, inst, &pos.func.layout);
|
||||
|
||||
self.split_values.push(new_val);
|
||||
new_val
|
||||
|
||||
Reference in New Issue
Block a user