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:
Jakob Stoklund Olesen
2017-08-03 21:08:36 -07:00
parent 621abb5026
commit 87cee86acb
3 changed files with 122 additions and 39 deletions

105
lib/cretonne/src/cursor.rs Normal file
View 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
}
}

View File

@@ -34,6 +34,7 @@ pub mod verifier;
mod abi;
mod constant_hash;
mod context;
mod cursor;
mod iterators;
mod legalizer;
mod licm;

View File

@@ -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