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 abi;
|
||||||
mod constant_hash;
|
mod constant_hash;
|
||||||
mod context;
|
mod context;
|
||||||
|
mod cursor;
|
||||||
mod iterators;
|
mod iterators;
|
||||||
mod legalizer;
|
mod legalizer;
|
||||||
mod licm;
|
mod licm;
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
//! and inserting copies where necessary such that all values passed to an EBB argument will belong
|
//! 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.
|
//! to the same virtual register as the EBB argument value itself.
|
||||||
|
|
||||||
|
use cursor::{Cursor, EncCursor};
|
||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use flowgraph::{ControlFlowGraph, BasicBlock};
|
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 ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint};
|
||||||
use regalloc::affinity::Affinity;
|
use regalloc::affinity::Affinity;
|
||||||
use regalloc::liveness::Liveness;
|
use regalloc::liveness::Liveness;
|
||||||
@@ -464,37 +465,26 @@ impl<'a> Context<'a> {
|
|||||||
argnum: usize,
|
argnum: usize,
|
||||||
pred_val: Value)
|
pred_val: Value)
|
||||||
-> Value {
|
-> Value {
|
||||||
let copy;
|
let mut pos = EncCursor::new(self.func, self.isa).at_inst(pred_inst);
|
||||||
{
|
let copy = pos.ins().copy(pred_val);
|
||||||
let mut pos = Cursor::new(&mut self.func.layout).at_inst(pred_inst);
|
let inst = pos.built_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);
|
|
||||||
|
|
||||||
dbg!("Inserted {}, before {}: {}",
|
dbg!("Inserted {}, before {}: {}",
|
||||||
self.func.dfg.display_inst(inst, self.isa),
|
pos.display_inst(inst),
|
||||||
pred_ebb,
|
pred_ebb,
|
||||||
self.func.dfg.display_inst(pred_inst, self.isa));
|
pos.display_inst(pred_inst));
|
||||||
|
|
||||||
// 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.
|
// Create a live range for the new value.
|
||||||
let affinity = Affinity::new(&self.encinfo
|
let affinity = Affinity::new(&self.encinfo
|
||||||
.operand_constraints(encoding)
|
.operand_constraints(pos.func.encodings[inst])
|
||||||
.expect("Bad copy encoding")
|
.expect("Bad copy encoding")
|
||||||
.outs
|
.outs
|
||||||
[0]);
|
[0]);
|
||||||
self.liveness.create_dead(copy, inst, affinity);
|
self.liveness.create_dead(copy, inst, affinity);
|
||||||
self.liveness
|
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);
|
self.split_values.push(copy);
|
||||||
copy
|
copy
|
||||||
}
|
}
|
||||||
@@ -505,39 +495,26 @@ impl<'a> Context<'a> {
|
|||||||
let new_val = self.func.dfg.replace_ebb_arg(succ_val, ty);
|
let new_val = self.func.dfg.replace_ebb_arg(succ_val, ty);
|
||||||
|
|
||||||
// Insert a copy instruction at the top of ebb.
|
// Insert a copy instruction at the top of ebb.
|
||||||
{
|
let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb);
|
||||||
let mut pos = Cursor::new(&mut self.func.layout).at_first_inst(ebb);
|
pos.ins().with_result(succ_val).copy(new_val);
|
||||||
self.func
|
let inst = pos.built_inst();
|
||||||
.dfg
|
|
||||||
.ins(&mut pos)
|
|
||||||
.with_result(succ_val)
|
|
||||||
.copy(new_val);
|
|
||||||
}
|
|
||||||
let inst = self.func.dfg.value_def(succ_val).unwrap_inst();
|
|
||||||
self.liveness.move_def_locally(succ_val, inst);
|
self.liveness.move_def_locally(succ_val, inst);
|
||||||
|
|
||||||
dbg!("Inserted {}, following {}({}: {})",
|
dbg!("Inserted {}, following {}({}: {})",
|
||||||
self.func.dfg.display_inst(inst, self.isa),
|
pos.display_inst(inst),
|
||||||
ebb,
|
ebb,
|
||||||
new_val,
|
new_val,
|
||||||
ty);
|
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.
|
// Create a live range for the new value.
|
||||||
let affinity = Affinity::new(&self.encinfo
|
let affinity = Affinity::new(&self.encinfo
|
||||||
.operand_constraints(encoding)
|
.operand_constraints(pos.func.encodings[inst])
|
||||||
.expect("Bad copy encoding")
|
.expect("Bad copy encoding")
|
||||||
.outs
|
.outs
|
||||||
[0]);
|
[0]);
|
||||||
self.liveness.create_dead(new_val, ebb, affinity);
|
self.liveness.create_dead(new_val, ebb, affinity);
|
||||||
self.liveness
|
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);
|
self.split_values.push(new_val);
|
||||||
new_val
|
new_val
|
||||||
|
|||||||
Reference in New Issue
Block a user