Use more helper functions on CursorBase to reduce cursor repositioning.
This commit is contained in:
@@ -720,6 +720,29 @@ pub trait CursorBase {
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned at the first insertion point for `ebb`.
|
||||
/// This differs from `at_first_inst` in that it doesn't assume that any
|
||||
/// instructions have been inserted into `ebb` yet.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
///
|
||||
/// ```
|
||||
/// # use cretonne::ir::{Function, Ebb, Inst};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_func(func: &mut Function, ebb: Ebb) {
|
||||
/// let mut pos = Cursor::new(&mut func.layout).at_first_insertion_point(ebb);
|
||||
///
|
||||
/// // Use `pos`...
|
||||
/// }
|
||||
/// ```
|
||||
fn at_first_insertion_point(mut self, ebb: Ebb) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_first_insertion_point(ebb);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned at the first instruction in `ebb`.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
@@ -741,6 +764,69 @@ pub trait CursorBase {
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned at the last instruction in `ebb`.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
///
|
||||
/// ```
|
||||
/// # use cretonne::ir::{Function, Ebb, Inst};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_func(func: &mut Function, ebb: Ebb) {
|
||||
/// let mut pos = Cursor::new(&mut func.layout).at_last_inst(ebb);
|
||||
///
|
||||
/// // Use `pos`...
|
||||
/// }
|
||||
/// ```
|
||||
fn at_last_inst(mut self, ebb: Ebb) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_last_inst(ebb);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned after `inst`.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
///
|
||||
/// ```
|
||||
/// # use cretonne::ir::{Function, Ebb, Inst};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_func(func: &mut Function, inst: Inst) {
|
||||
/// let mut pos = Cursor::new(&mut func.layout).after_inst(inst);
|
||||
///
|
||||
/// // Use `pos`...
|
||||
/// }
|
||||
/// ```
|
||||
fn after_inst(mut self, inst: Inst) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_after_inst(inst);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned at the top of `ebb`.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
///
|
||||
/// ```
|
||||
/// # use cretonne::ir::{Function, Ebb, Inst};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_func(func: &mut Function, ebb: Ebb) {
|
||||
/// let mut pos = Cursor::new(&mut func.layout).at_top(ebb);
|
||||
///
|
||||
/// // Use `pos`...
|
||||
/// }
|
||||
/// ```
|
||||
fn at_top(mut self, ebb: Ebb) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_top(ebb);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rebuild this cursor positioned at the bottom of `ebb`.
|
||||
///
|
||||
/// This is intended to be used as a builder method:
|
||||
@@ -781,6 +867,20 @@ pub trait CursorBase {
|
||||
}
|
||||
}
|
||||
|
||||
/// Go to the position after a specific instruction, which must be inserted
|
||||
/// in the layout. New instructions will be inserted after `inst`.
|
||||
fn goto_after_inst(&mut self, inst: Inst) {
|
||||
debug_assert!(self.layout().inst_ebb(inst).is_some());
|
||||
let new_pos = if let Some(next) = self.layout().insts[inst].next.expand() {
|
||||
CursorPosition::At(next)
|
||||
} else {
|
||||
CursorPosition::After(self.layout().inst_ebb(inst).expect(
|
||||
"current instruction removed?",
|
||||
))
|
||||
};
|
||||
self.set_position(new_pos);
|
||||
}
|
||||
|
||||
/// Go to a specific instruction which must be inserted in the layout.
|
||||
/// New instructions will be inserted before `inst`.
|
||||
fn goto_inst(&mut self, inst: Inst) {
|
||||
@@ -910,8 +1010,7 @@ pub trait CursorBase {
|
||||
/// # use cretonne::ir::{Function, Ebb};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_ebb(func: &mut Function, ebb: Ebb) {
|
||||
/// let mut cursor = Cursor::new(&mut func.layout);
|
||||
/// cursor.goto_top(ebb);
|
||||
/// let mut cursor = Cursor::new(&mut func.layout).at_top(ebb);
|
||||
/// while let Some(inst) = cursor.next_inst() {
|
||||
/// // Edit instructions...
|
||||
/// }
|
||||
@@ -979,8 +1078,7 @@ pub trait CursorBase {
|
||||
/// # use cretonne::ir::{Function, Ebb};
|
||||
/// # use cretonne::ir::layout::{Cursor, CursorBase};
|
||||
/// fn edit_ebb(func: &mut Function, ebb: Ebb) {
|
||||
/// let mut cursor = Cursor::new(&mut func.layout);
|
||||
/// cursor.goto_bottom(ebb);
|
||||
/// let mut cursor = Cursor::new(&mut func.layout).at_bottom(ebb);
|
||||
/// while let Some(inst) = cursor.prev_inst() {
|
||||
/// // Edit instructions...
|
||||
/// }
|
||||
@@ -1357,8 +1455,7 @@ mod tests {
|
||||
verify(&mut layout, &[(e1, &[i1, i2, i0])]);
|
||||
|
||||
// Test cursor positioning.
|
||||
let mut cur = Cursor::new(&mut layout);
|
||||
cur.goto_top(e1);
|
||||
let mut cur = Cursor::new(&mut layout).at_top(e1);
|
||||
assert_eq!(cur.position(), CursorPosition::Before(e1));
|
||||
assert_eq!(cur.prev_inst(), None);
|
||||
assert_eq!(cur.position(), CursorPosition::Before(e1));
|
||||
|
||||
@@ -62,8 +62,7 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
|
||||
// Insert position for argument conversion code.
|
||||
// We want to insert instructions before the first instruction in the entry block.
|
||||
// If the entry block is empty, append instructions to it instead.
|
||||
let mut pos = Cursor::new(&mut func.layout);
|
||||
pos.goto_first_inst(entry);
|
||||
let mut pos = Cursor::new(&mut func.layout).at_first_inst(entry);
|
||||
|
||||
// Keep track of the argument types in the ABI-legalized signature.
|
||||
let abi_types = &func.signature.argument_types;
|
||||
|
||||
@@ -137,8 +137,7 @@ fn expand_cond_trap(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFl
|
||||
func.dfg.replace(inst).brz(arg, new_ebb, &[]);
|
||||
}
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.next_inst();
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.ins().trap();
|
||||
pos.insert_ebb(new_ebb);
|
||||
|
||||
|
||||
@@ -33,14 +33,12 @@ pub fn do_licm(
|
||||
None => {
|
||||
let pre_header =
|
||||
create_pre_header(loop_analysis.loop_header(lp), func, cfg, domtree);
|
||||
pos = Cursor::new(&mut func.layout);
|
||||
pos.goto_last_inst(pre_header);
|
||||
pos = Cursor::new(&mut func.layout).at_last_inst(pre_header);
|
||||
}
|
||||
// If there is a natural pre-header we insert new instructions just before the
|
||||
// related jumping instruction (which is not necessarily at the end).
|
||||
Some((_, last_inst)) => {
|
||||
pos = Cursor::new(&mut func.layout);
|
||||
pos.goto_inst(last_inst);
|
||||
pos = Cursor::new(&mut func.layout).at_inst(last_inst);
|
||||
}
|
||||
};
|
||||
// The last instruction of the pre-header is the termination instruction (usually
|
||||
@@ -82,8 +80,7 @@ fn create_pre_header(
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut pos = Cursor::new(&mut func.layout);
|
||||
pos.goto_top(header);
|
||||
let mut pos = Cursor::new(&mut func.layout).at_top(header);
|
||||
// Inserts the pre-header at the right place in the layout.
|
||||
pos.insert_ebb(pre_header);
|
||||
pos.next_inst();
|
||||
|
||||
@@ -148,8 +148,7 @@ impl<'a> Context<'a> {
|
||||
self.divert.clear();
|
||||
|
||||
// Now go through the instructions in `ebb` and color the values they define.
|
||||
let mut pos = Cursor::new(&mut func.layout);
|
||||
pos.goto_top(ebb);
|
||||
let mut pos = Cursor::new(&mut func.layout).at_top(ebb);
|
||||
while let Some(inst) = pos.next_inst() {
|
||||
if let Some(constraints) = self.encinfo.operand_constraints(func.encodings[inst]) {
|
||||
self.visit_inst(
|
||||
|
||||
Reference in New Issue
Block a user