diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index b92a6d7336..c2c8f5ea7a 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -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)); diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index a95ec2cfba..b3e7b64658 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -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; diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index f47dc87241..6dbeb15d04 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -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); diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index 0a739f8f2d..c7b4ff72f6 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -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(); diff --git a/lib/cretonne/src/regalloc/coloring.rs b/lib/cretonne/src/regalloc/coloring.rs index 31fe44f03c..9a9122ba2f 100644 --- a/lib/cretonne/src/regalloc/coloring.rs +++ b/lib/cretonne/src/regalloc/coloring.rs @@ -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( diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 73d10e0494..e054ee511c 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -444,8 +444,7 @@ where if !layout.is_ebb_inserted(dest_ebb) { layout.append_ebb(dest_ebb) }; - let mut cur = Cursor::new(layout); - cur.goto_first_insertion_point(dest_ebb); + let mut cur = Cursor::new(layout).at_first_insertion_point(dest_ebb); let ty = dfg.value_type(temp_arg_val); let val = if ty.is_int() { dfg.ins(&mut cur).iconst(ty, 0) @@ -545,8 +544,7 @@ where *old_dest = PackedOption::from(middle_ebb); } } - let mut cur = Cursor::new(layout); - cur.goto_bottom(middle_ebb); + let mut cur = Cursor::new(layout).at_bottom(middle_ebb); let middle_jump_inst = dfg.ins(&mut cur).jump(dest_ebb, &[val]); self.def_var(var, val, block); Some((middle_ebb, block, middle_jump_inst)) @@ -627,14 +625,12 @@ mod tests { let x_ssa = { let cur = &mut Cursor::new(&mut func.layout); cur.insert_ebb(ebb0); - cur.goto_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 1) }; ssa.def_var(x_var, x_ssa, block); let y_var = Variable(1); let y_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 2) }; ssa.def_var(y_var, y_ssa, block); @@ -679,8 +675,7 @@ mod tests { block, ).0; let z1_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iadd(x_use1, y_use1) }; ssa.def_var(z_var, z1_ssa, block); @@ -712,8 +707,7 @@ mod tests { block, ).0; let z2_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iadd(x_use2, z_use1) }; ssa.def_var(z_var, z2_ssa, block); @@ -758,8 +752,7 @@ mod tests { ssa.def_var(x_var, x_ssa, block0); let y_var = Variable(1); let y_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 2) }; ssa.def_var(y_var, y_ssa, block0); @@ -803,8 +796,7 @@ mod tests { block0, ).0; let z1_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iadd(x_use1, y_use1) }; ssa.def_var(z_var, z1_ssa, block0); @@ -828,8 +820,7 @@ mod tests { block0, ).0; let jump_inst: Inst = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).brnz(y_use2, ebb1, &[]) }; let block1 = ssa.declare_ebb_body_block(block0); @@ -852,8 +843,7 @@ mod tests { ).0; assert_eq!(z_use1, z1_ssa); let z2_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iadd(x_use2, z_use1) }; ssa.def_var(z_var, z2_ssa, block1); @@ -891,8 +881,7 @@ mod tests { ).0; assert_eq!(y_ssa, y_use3); let y2_ssa = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).iadd(x_use3, y_use3) }; ssa.def_var(y_var, y2_ssa, block2); @@ -952,8 +941,7 @@ mod tests { ); let y_var = Variable(1); let y1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 2) }; ssa.def_var(y_var, y1, block0); @@ -988,14 +976,12 @@ mod tests { ).0; assert_eq!(y2, y1); let z1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iadd(x2, y2) }; ssa.def_var(z_var, z1, block0); let jump_ebb0_ebb1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).jump(ebb1, &[]) }; let block1 = ssa.declare_ebb_header_block(ebb1); @@ -1017,8 +1003,7 @@ mod tests { block1, ).0; let z3 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).iadd(z2, y3) }; ssa.def_var(z_var, z3, block1); @@ -1032,8 +1017,7 @@ mod tests { ).0; assert_eq!(y4, y3); let jump_ebb1_ebb2 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).brnz(y4, ebb2, &[]) }; let block2 = ssa.declare_ebb_body_block(block1); @@ -1055,8 +1039,7 @@ mod tests { block2, ).0; let z5 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).isub(z4, x3) }; ssa.def_var(z_var, z5, block2); @@ -1070,8 +1053,7 @@ mod tests { ).0; assert_eq!(y5, y3); { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).return_(&[y5]) }; @@ -1097,14 +1079,12 @@ mod tests { ).0; assert_eq!(x4, x3); let y7 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb2); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb2); func.dfg.ins(cur).isub(y6, x4) }; ssa.def_var(y_var, y7, block3); let jump_ebb2_ebb1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb2); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb2); func.dfg.ins(cur).jump(ebb1, &[]) }; @@ -1156,20 +1136,17 @@ mod tests { block0, ).0; let br_table = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).br_table(x1, jt) }; let block1 = ssa.declare_ebb_body_block(block0); let x3 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 2) }; ssa.def_var(x_var, x3, block1); let jump_inst = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).jump(ebb1, &[]) }; let block2 = ssa.declare_ebb_header_block(ebb1); @@ -1185,13 +1162,11 @@ mod tests { block2, ).0; { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).iadd_imm(x4, 1) }; { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).return_(&[]) }; let flags = settings::Flags::new(&settings::builder()); @@ -1232,20 +1207,17 @@ mod tests { }; ssa.def_var(x_var, x1, block0); let y1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 1) }; ssa.def_var(y_var, y1, block0); let z1 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).iconst(I32, 2) }; ssa.def_var(z_var, z1, block0); let jump_inst = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb0); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb0); func.dfg.ins(cur).jump(ebb1, &[]) }; let block1 = ssa.declare_ebb_header_block(ebb1); @@ -1269,8 +1241,7 @@ mod tests { ).0; assert_eq!(func.dfg.ebb_args(ebb1)[1], x2); let x3 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).iadd(x2, z2) }; ssa.def_var(x_var, x3, block1); @@ -1292,14 +1263,12 @@ mod tests { ).0; assert_eq!(func.dfg.ebb_args(ebb1)[2], y3); let y4 = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).isub(y3, x4) }; ssa.def_var(y_var, y4, block1); let jump_inst = { - let cur = &mut Cursor::new(&mut func.layout); - cur.goto_bottom(ebb1); + let cur = &mut Cursor::new(&mut func.layout).at_bottom(ebb1); func.dfg.ins(cur).jump(ebb1, &[]) }; ssa.declare_ebb_predecessor(ebb1, block1, jump_inst);