diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index f3e5067420..a79b05da76 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -264,12 +264,12 @@ def emit_dst_inst(node, fmt): # Split instructions are not emitted with the builder, but by calling # special functions in the `legalizer::split` module. These functions # will eliminate concat-split patterns. - fmt.line( - 'let {} = split::{}(dfg, cfg, pos, {});' - .format( - wrap_tup(node.defs), - node.expr.inst.snake_name(), - node.expr.args[0])) + fmt.line('let curpos = pos.position();') + fmt.format( + 'let {} = split::{}(dfg, pos.layout, cfg, curpos, {});', + wrap_tup(node.defs), + node.expr.inst.snake_name(), + node.expr.args[0]) else: if len(node.defs) == 0: # This node doesn't define any values, so just insert the new diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 2139848382..877701a1a1 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -709,6 +709,15 @@ pub trait CursorBase { /// Borrow a mutable reference to the function layout that this cursor is navigating. fn layout_mut(&mut self) -> &mut Layout; + /// Rebuild this cursor positioned at `pos`. + fn at_position(mut self, pos: CursorPosition) -> Self + where + Self: Sized, + { + self.set_position(pos); + self + } + /// Rebuild this cursor positioned at `inst`. /// /// This is intended to be used as a builder method: diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index b3e7b64658..dfeb88b777 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -331,12 +331,14 @@ fn convert_to_abi( let ty = dfg.value_type(value); match legalize_abi_value(ty, &arg_type) { ValueConversion::IntSplit => { - let (lo, hi) = isplit(dfg, cfg, pos, value); + let curpos = pos.position(); + let (lo, hi) = isplit(dfg, pos.layout, cfg, curpos, value); convert_to_abi(dfg, cfg, pos, lo, put_arg); convert_to_abi(dfg, cfg, pos, hi, put_arg); } ValueConversion::VectorSplit => { - let (lo, hi) = vsplit(dfg, cfg, pos, value); + let curpos = pos.position(); + let (lo, hi) = vsplit(dfg, pos.layout, cfg, curpos, value); convert_to_abi(dfg, cfg, pos, lo, put_arg); convert_to_abi(dfg, cfg, pos, hi, put_arg); } diff --git a/lib/cretonne/src/legalizer/split.rs b/lib/cretonne/src/legalizer/split.rs index 23c0e02bcd..f3df6b7b82 100644 --- a/lib/cretonne/src/legalizer/split.rs +++ b/lib/cretonne/src/legalizer/split.rs @@ -64,31 +64,33 @@ //! It is possible to have circular dependencies of EBB arguments that are never used by any real //! instructions. These loops will remain in the program. +use cursor::{Cursor, CursorPosition}; use flowgraph::ControlFlowGraph; -use ir::{DataFlowGraph, Ebb, Inst, Cursor, CursorBase, Value, Type, Opcode, ValueDef, - InstructionData, InstBuilder}; +use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder}; use std::iter; /// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values /// if possible. pub fn isplit( - dfg: &mut DataFlowGraph, + dfg: &mut ir::DataFlowGraph, + layout: &mut ir::Layout, cfg: &ControlFlowGraph, - pos: &mut Cursor, + pos: CursorPosition, value: Value, ) -> (Value, Value) { - split_any(dfg, cfg, pos, value, Opcode::Iconcat) + split_any(dfg, layout, cfg, pos, value, Opcode::Iconcat) } /// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if /// possible. pub fn vsplit( - dfg: &mut DataFlowGraph, + dfg: &mut ir::DataFlowGraph, + layout: &mut ir::Layout, cfg: &ControlFlowGraph, - pos: &mut Cursor, + pos: CursorPosition, value: Value, ) -> (Value, Value) { - split_any(dfg, cfg, pos, value, Opcode::Vconcat) + split_any(dfg, layout, cfg, pos, value, Opcode::Vconcat) } /// After splitting an EBB argument, we need to go back and fix up all of the predecessor @@ -110,15 +112,16 @@ struct Repair { /// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode. fn split_any( - dfg: &mut DataFlowGraph, + dfg: &mut ir::DataFlowGraph, + layout: &mut ir::Layout, cfg: &ControlFlowGraph, - pos: &mut Cursor, + pos: CursorPosition, value: Value, concat: Opcode, ) -> (Value, Value) { - let saved_pos = pos.position(); let mut repairs = Vec::new(); - let result = split_value(dfg, pos, value, concat, &mut repairs); + let mut pos = ir::Cursor::new(layout).at_position(pos); + let result = split_value(dfg, &mut pos, value, concat, &mut repairs); // We have split the value requested, and now we may need to fix some EBB predecessors. while let Some(repair) = repairs.pop() { @@ -147,7 +150,7 @@ fn split_any( // Split the old argument, possibly causing more repairs to be scheduled. pos.goto_inst(inst); - let (lo, hi) = split_value(dfg, pos, old_arg, repair.concat, &mut repairs); + let (lo, hi) = split_value(dfg, &mut pos, old_arg, repair.concat, &mut repairs); // The `lo` part replaces the original argument. *args.get_mut(fixed_args + repair.num, &mut dfg.value_lists) @@ -173,7 +176,6 @@ fn split_any( } } - pos.set_position(saved_pos); result } @@ -184,8 +186,8 @@ fn split_any( /// /// Return the two new values representing the parts of `value`. fn split_value( - dfg: &mut DataFlowGraph, - pos: &mut Cursor, + dfg: &mut ir::DataFlowGraph, + pos: &mut ir::Cursor, value: Value, concat: Opcode, repairs: &mut Vec, @@ -292,7 +294,7 @@ fn add_repair( /// ``` /// /// This function resolves `v11` to `v1` and `v12` to `v2`. -fn resolve_splits(dfg: &DataFlowGraph, value: Value) -> Value { +fn resolve_splits(dfg: &ir::DataFlowGraph, value: Value) -> Value { let value = dfg.resolve_copies(value); // Deconstruct a split instruction. @@ -330,7 +332,7 @@ fn resolve_splits(dfg: &DataFlowGraph, value: Value) -> Value { /// /// After legalizing the instructions computing the value that was split, it is likely that we can /// avoid depending on the split instruction. Its input probably comes from a concatenation. -pub fn simplify_branch_arguments(dfg: &mut DataFlowGraph, branch: Inst) { +pub fn simplify_branch_arguments(dfg: &mut ir::DataFlowGraph, branch: Inst) { let mut new_args = Vec::new(); for &arg in dfg.inst_args(branch) {