diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 41b64ede5d..0d8407bb30 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -152,7 +152,7 @@ def unwrap_inst(iref, node, fmt): # type: (str, Def, Formatter) -> bool """ Given a `Def` node, emit code that extracts all the instruction fields from - `dfg[iref]`. + `pos.func.dfg[iref]`. Create local variables named after the `Var` instances in `node`. @@ -181,7 +181,8 @@ def unwrap_inst(iref, node, fmt): elif iform.has_value_list or nvops > 1: fmt.line('ref args,') fmt.line('..') - fmt.outdented_line('} = dfg[inst] {') + fmt.outdented_line('} = pos.func.dfg[inst] {') + fmt.line('let dfg = &pos.func.dfg;') if iform.has_value_list: fmt.line('let args = args.as_slice(&dfg.value_lists);') elif nvops == 1: @@ -205,7 +206,7 @@ def unwrap_inst(iref, node, fmt): for opnum in expr.inst.value_opnums: v = expr.args[opnum] if isinstance(v, Var) and v.has_free_typevar(): - fmt.line('let typeof_{0} = dfg.value_type({0});'.format(v)) + fmt.format('let typeof_{0} = pos.func.dfg.value_type({0});', v) # If the node has results, detach the values. # Place the values in locals. @@ -223,13 +224,13 @@ def unwrap_inst(iref, node, fmt): for d in node.defs: fmt.line('let {};'.format(d)) with fmt.indented('{', '}'): - fmt.line('let r = dfg.inst_results(inst);') + fmt.line('let r = pos.func.dfg.inst_results(inst);') for i in range(len(node.defs)): fmt.line('{} = r[{}];'.format(node.defs[i], i)) for d in node.defs: if d.has_free_typevar(): fmt.line( - 'let typeof_{0} = dfg.value_type({0});' + 'let typeof_{0} = pos.func.dfg.value_type({0});' .format(d)) return replace_inst @@ -265,8 +266,9 @@ def emit_dst_inst(node, fmt): # special functions in the `legalizer::split` module. These functions # will eliminate concat-split patterns. fmt.line('let curpos = pos.position();') + fmt.line('let srcloc = pos.srcloc();') fmt.format( - 'let {} = split::{}(dfg, pos.layout, cfg, curpos, {});', + 'let {} = split::{}(pos.func, cfg, curpos, srcloc, {});', wrap_tup(node.defs), node.expr.inst.snake_name(), node.expr.args[0]) @@ -274,7 +276,7 @@ def emit_dst_inst(node, fmt): if len(node.defs) == 0: # This node doesn't define any values, so just insert the new # instruction. - builder = 'dfg.ins(pos)' + builder = 'pos.ins()' else: src_def0 = node.defs[0].src_def if src_def0 and node.defs == src_def0.defs: @@ -282,12 +284,12 @@ def emit_dst_inst(node, fmt): # the source pattern. Unwrapping would have left the results # intact. # Replace the whole instruction. - builder = 'let {} = dfg.replace(inst)'.format( + builder = 'let {} = pos.func.dfg.replace(inst)'.format( wrap_tup(node.defs)) replaced_inst = 'inst' else: # Insert a new instruction. - builder = 'let {} = dfg.ins(pos)'.format(wrap_tup(node.defs)) + builder = 'let {} = pos.ins()'.format(wrap_tup(node.defs)) # We may want to reuse some of the detached output values. if len(node.defs) == 1 and node.defs[0].is_output(): # Reuse the single source result value. @@ -335,7 +337,7 @@ def gen_xform(xform, fmt, type_sets): # If we're going to delete `inst`, we need to detach its results first # so they can be reattached during pattern expansion. if not replace_inst: - fmt.line('dfg.clear_results(inst);') + fmt.line('pos.func.dfg.clear_results(inst);') # Emit the destination pattern. for dst in xform.dst.rtl: @@ -357,8 +359,10 @@ def gen_xform_group(xgrp, fmt, type_sets): 'func: &mut ir::Function, ' 'cfg: &mut ::flowgraph::ControlFlowGraph) -> ' 'bool {{'.format(xgrp.name), '}'): - fmt.line('use ir::{InstBuilder, CursorBase};') - fmt.line('let srcloc = func.srclocs[inst];') + fmt.line('use ir::{InstBuilder};') + fmt.line('use cursor::{Cursor, FuncCursor};') + fmt.line('let pos = &mut FuncCursor::new(func).at_inst(inst);') + fmt.line('pos.use_srcloc(inst);') # Group the xforms by opcode so we can generate a big switch. # Preserve ordering. @@ -368,16 +372,10 @@ def gen_xform_group(xgrp, fmt, type_sets): xforms[inst.camel_name].append(xform) with fmt.indented('{', '}'): - with fmt.indented('match func.dfg[inst].opcode() {', '}'): + with fmt.indented('match pos.func.dfg[inst].opcode() {', '}'): for camel_name in sorted(xforms.keys()): with fmt.indented( 'ir::Opcode::{} => {{'.format(camel_name), '}'): - fmt.line( - 'let pos = &mut ir::Cursor::new' - '(&mut func.layout, &mut func.srclocs)' - '.with_srcloc(srcloc)' - '.at_inst(inst);') - fmt.line('let dfg = &mut func.dfg;') for xform in xforms[camel_name]: gen_xform(xform, fmt, type_sets) @@ -387,7 +385,7 @@ def gen_xform_group(xgrp, fmt, type_sets): with fmt.indented( 'ir::Opcode::{} => {{' .format(inst.camel_name), '}'): - fmt.format('{}(inst, func, cfg);', funcname) + fmt.format('{}(inst, pos.func, cfg);', funcname) fmt.line('return true;') # We'll assume there are uncovered opcodes. @@ -395,7 +393,7 @@ def gen_xform_group(xgrp, fmt, type_sets): # If we fall through, nothing was expanded. Call the chain if any. if xgrp.chain: - fmt.format('{}(inst, func, cfg)', xgrp.chain.rust_name()) + fmt.format('{}(inst, pos.func, cfg)', xgrp.chain.rust_name()) else: fmt.line('false') diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index c7b4627af1..5522db921f 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -325,13 +325,15 @@ fn convert_to_abi( match legalize_abi_value(ty, &arg_type) { ValueConversion::IntSplit => { let curpos = pos.position(); - let (lo, hi) = isplit(&mut pos.func.dfg, &mut pos.func.layout, cfg, curpos, value); + let srcloc = pos.srcloc(); + let (lo, hi) = isplit(&mut pos.func, cfg, curpos, srcloc, value); convert_to_abi(pos, cfg, lo, put_arg); convert_to_abi(pos, cfg, hi, put_arg); } ValueConversion::VectorSplit => { let curpos = pos.position(); - let (lo, hi) = vsplit(&mut pos.func.dfg, &mut pos.func.layout, cfg, curpos, value); + let srcloc = pos.srcloc(); + let (lo, hi) = vsplit(&mut pos.func, cfg, curpos, srcloc, value); convert_to_abi(pos, cfg, lo, put_arg); convert_to_abi(pos, cfg, hi, put_arg); } diff --git a/lib/cretonne/src/legalizer/split.rs b/lib/cretonne/src/legalizer/split.rs index bc73db6817..62e5391474 100644 --- a/lib/cretonne/src/legalizer/split.rs +++ b/lib/cretonne/src/legalizer/split.rs @@ -64,7 +64,7 @@ //! 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 cursor::{Cursor, CursorPosition, FuncCursor}; use flowgraph::ControlFlowGraph; use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder}; use std::iter; @@ -72,25 +72,25 @@ 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 ir::DataFlowGraph, - layout: &mut ir::Layout, + func: &mut ir::Function, cfg: &ControlFlowGraph, pos: CursorPosition, + srcloc: ir::SourceLoc, value: Value, ) -> (Value, Value) { - split_any(dfg, layout, cfg, pos, value, Opcode::Iconcat) + split_any(func, cfg, pos, srcloc, value, Opcode::Iconcat) } /// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if /// possible. pub fn vsplit( - dfg: &mut ir::DataFlowGraph, - layout: &mut ir::Layout, + func: &mut ir::Function, cfg: &ControlFlowGraph, pos: CursorPosition, + srcloc: ir::SourceLoc, value: Value, ) -> (Value, Value) { - split_any(dfg, layout, cfg, pos, value, Opcode::Vconcat) + split_any(func, cfg, pos, srcloc, value, Opcode::Vconcat) } /// After splitting an EBB argument, we need to go back and fix up all of the predecessor @@ -112,54 +112,53 @@ struct Repair { /// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode. fn split_any( - dfg: &mut ir::DataFlowGraph, - layout: &mut ir::Layout, + func: &mut ir::Function, cfg: &ControlFlowGraph, pos: CursorPosition, + srcloc: ir::SourceLoc, value: Value, concat: Opcode, ) -> (Value, Value) { let mut repairs = Vec::new(); - let mut pos = ir::Cursor::new(layout, None).at_position(pos); - let result = split_value(dfg, &mut pos, value, concat, &mut repairs); + let pos = &mut FuncCursor::new(func).at_position(pos).with_srcloc(srcloc); + let result = split_value(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() { for &(_, inst) in cfg.get_predecessors(repair.ebb) { - let branch_opc = dfg[inst].opcode(); + let branch_opc = pos.func.dfg[inst].opcode(); assert!( branch_opc.is_branch(), "Predecessor not a branch: {}", - dfg.display_inst(inst, None) + pos.func.dfg.display_inst(inst, None) ); let fixed_args = branch_opc.constraints().fixed_value_arguments(); - let mut args = dfg[inst].take_value_list().expect( + let mut args = pos.func.dfg[inst].take_value_list().expect( "Branches must have value lists.", ); - let num_args = args.len(&dfg.value_lists); + let num_args = args.len(&pos.func.dfg.value_lists); // Get the old value passed to the EBB argument we're repairing. - let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists).expect( - "Too few branch arguments", - ); + let old_arg = args.get(fixed_args + repair.num, &pos.func.dfg.value_lists) + .expect("Too few branch arguments"); // It's possible that the CFG's predecessor list has duplicates. Detect them here. - if dfg.value_type(old_arg) == repair.split_type { - dfg[inst].put_value_list(args); + if pos.func.dfg.value_type(old_arg) == repair.split_type { + pos.func.dfg[inst].put_value_list(args); continue; } // Split the old argument, possibly causing more repairs to be scheduled. pos.goto_inst(inst); - let (lo, hi) = split_value(dfg, &mut pos, old_arg, repair.concat, &mut repairs); + let (lo, hi) = split_value(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) + *args.get_mut(fixed_args + repair.num, &mut pos.func.dfg.value_lists) .unwrap() = lo; // The `hi` part goes at the end. Since multiple repairs may have been scheduled to the // same EBB, there could be multiple arguments missing. if num_args > fixed_args + repair.hi_num { - *args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists) + *args.get_mut(fixed_args + repair.hi_num, &mut pos.func.dfg.value_lists) .unwrap() = hi; } else { // We need to append one or more arguments. If we're adding more than one argument, @@ -167,12 +166,12 @@ fn split_any( // instead of `hi`. args.extend( iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args), - &mut dfg.value_lists, + &mut pos.func.dfg.value_lists, ); } // Put the value list back after manipulating it. - dfg[inst].put_value_list(args); + pos.func.dfg[inst].put_value_list(args); } } @@ -186,20 +185,19 @@ fn split_any( /// /// Return the two new values representing the parts of `value`. fn split_value( - dfg: &mut ir::DataFlowGraph, - pos: &mut ir::Cursor, + pos: &mut FuncCursor, value: Value, concat: Opcode, repairs: &mut Vec, ) -> (Value, Value) { - let value = dfg.resolve_copies(value); + let value = pos.func.dfg.resolve_copies(value); let mut reuse = None; - match dfg.value_def(value) { + match pos.func.dfg.value_def(value) { ValueDef::Res(inst, num) => { // This is an instruction result. See if the value was created by a `concat` // instruction. - if let InstructionData::Binary { opcode, args, .. } = dfg[inst] { + if let InstructionData::Binary { opcode, args, .. } = pos.func.dfg[inst] { assert_eq!(num, 0); if opcode == concat { reuse = Some((args[0], args[1])); @@ -209,10 +207,10 @@ fn split_value( ValueDef::Arg(ebb, num) => { // This is an EBB argument. We can split the argument value unless this is the entry // block. - if pos.layout.entry_block() != Some(ebb) { + if pos.func.layout.entry_block() != Some(ebb) { // We are going to replace the argument at `num` with two new arguments. // Determine the new value types. - let ty = dfg.value_type(value); + let ty = pos.func.dfg.value_type(value); let split_type = match concat { Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"), Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"), @@ -225,9 +223,9 @@ fn split_value( // // Replace the original `value` with the low part, and append the high part at the // end of the argument list. - let lo = dfg.replace_ebb_arg(value, split_type); - let hi_num = dfg.num_ebb_args(ebb); - let hi = dfg.append_ebb_arg(ebb, split_type); + let lo = pos.func.dfg.replace_ebb_arg(value, split_type); + let hi_num = pos.func.dfg.num_ebb_args(ebb); + let hi = pos.func.dfg.append_ebb_arg(ebb, split_type); reuse = Some((lo, hi)); @@ -238,7 +236,7 @@ fn split_value( // Note that it is safe to move `pos` here since `reuse` was set above, so we don't // need to insert a split instruction before returning. pos.goto_first_inst(ebb); - dfg.ins(pos).with_result(value).Binary( + pos.ins().with_result(value).Binary( concat, split_type, lo, @@ -259,8 +257,8 @@ fn split_value( // No, we'll just have to insert the requested split instruction at `pos`. Note that `pos` // has not been moved by the EBB argument code above when `reuse` is `None`. match concat { - Opcode::Iconcat => dfg.ins(pos).isplit(value), - Opcode::Vconcat => dfg.ins(pos).vsplit(value), + Opcode::Iconcat => pos.ins().isplit(value), + Opcode::Vconcat => pos.ins().vsplit(value), _ => panic!("Unhandled concat opcode: {}", concat), } }