From 4b94ea21ed6d299bbcdc288ecc08180a1eba5877 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 17 Aug 2017 15:45:21 -0700 Subject: [PATCH] Switch to a FuncCursor in the top-level legalizer loop. Stop passing Cursor references to legalizer functions. Give them the whole &mut Function instead. Given the whole Function reference, these functions can create their own cursors. This lets legalizer actions access other Function data structures like the global variables. --- lib/cretonne/meta/gen_legalizer.py | 33 +++++++++++++------------- lib/cretonne/src/isa/mod.rs | 6 ++--- lib/cretonne/src/legalizer/boundary.rs | 28 ++++++++-------------- lib/cretonne/src/legalizer/mod.rs | 30 ++++++++++------------- 4 files changed, 43 insertions(+), 54 deletions(-) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 7189695a71..b9c125681b 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -353,16 +353,12 @@ def gen_xform_group(xgrp, fmt, type_sets): fmt.doc_comment("Legalize the instruction pointed to by `pos`.") fmt.line('#[allow(unused_variables,unused_assignments)]') with fmt.indented( - 'pub fn {}(dfg: &mut ir::DataFlowGraph, ' - 'cfg: &mut ::flowgraph::ControlFlowGraph, ' - 'pos: &mut ir::Cursor) -> ' + 'pub fn {}(inst: ir::Inst, ' + 'func: &mut ir::Function, ' + 'cfg: &mut ::flowgraph::ControlFlowGraph) -> ' 'bool {{'.format(xgrp.name), '}'): fmt.line('use ir::{InstBuilder, CursorBase};') - # Gen the instruction to be legalized. The cursor we're passed must be - # pointing at an instruction. - fmt.line('let inst = pos.current_inst().expect("need instruction");') - # Group the xforms by opcode so we can generate a big switch. # Preserve ordering. xforms = defaultdict(list) # type: DefaultDict[str, List[XForm]] @@ -370,18 +366,23 @@ def gen_xform_group(xgrp, fmt, type_sets): inst = xform.src.rtl[0].expr.inst xforms[inst.camel_name].append(xform) - with fmt.indented('match dfg[inst].opcode() {', '}'): - for camel_name in sorted(xforms.keys()): - with fmt.indented( - 'ir::Opcode::{} => {{'.format(camel_name), '}'): - for xform in xforms[camel_name]: - gen_xform(xform, fmt, type_sets) - # We'll assume there are uncovered opcodes. - fmt.line('_ => {},') + with fmt.indented('{', '}'): + fmt.line( + 'let pos = &mut ir::Cursor::new(&mut func.layout)' + '.at_inst(inst);') + fmt.line('let dfg = &mut func.dfg;') + with fmt.indented('match dfg[inst].opcode() {', '}'): + for camel_name in sorted(xforms.keys()): + with fmt.indented( + 'ir::Opcode::{} => {{'.format(camel_name), '}'): + for xform in xforms[camel_name]: + gen_xform(xform, fmt, type_sets) + # We'll assume there are uncovered opcodes. + fmt.line('_ => {},') # If we fall through, nothing was expanded. Call the chain if any. if xgrp.chain: - fmt.format('{}(dfg, cfg, pos)', xgrp.chain.rust_name()) + fmt.format('{}(inst, func, cfg)', xgrp.chain.rust_name()) else: fmt.line('false') diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index 08c45dd8b8..28a7c9d615 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -138,9 +138,9 @@ impl settings::Configurable for Builder { /// legalize it? /// /// The `Encodings` iterator returns a legalization function to call. -pub type Legalize = fn(&mut ir::DataFlowGraph, - &mut flowgraph::ControlFlowGraph, - &mut ir::Cursor) +pub type Legalize = fn(ir::Inst, + &mut ir::Function, + &mut flowgraph::ControlFlowGraph) -> bool; /// Methods that are specialized to a target ISA. diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 7d248c0cfa..17ff37c8f7 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -452,18 +452,13 @@ fn legalize_inst_arguments(dfg: &mut DataFlowGraph, /// original return values. The call's result values will be adapted to match the new signature. /// /// Returns `true` if any instructions were inserted. -pub fn handle_call_abi(dfg: &mut DataFlowGraph, - locations: &mut ValueLocations, - stack_slots: &mut StackSlots, - cfg: &ControlFlowGraph, - pos: &mut Cursor) - -> bool { - let mut inst = pos.current_inst() - .expect("Cursor must point to a call instruction"); +pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool { + let dfg = &mut func.dfg; + let pos = &mut Cursor::new(&mut func.layout).at_inst(inst); // Start by checking if the argument types already match the signature. let sig_ref = match check_call_signature(dfg, inst) { - Ok(_) => return spill_call_arguments(dfg, locations, stack_slots, pos), + Ok(_) => return spill_call_arguments(dfg, &mut func.locations, &mut func.stack_slots, pos), Err(s) => s, }; @@ -489,22 +484,19 @@ pub fn handle_call_abi(dfg: &mut DataFlowGraph, // Go back and insert spills for any stack arguments. pos.goto_inst(inst); - spill_call_arguments(dfg, locations, stack_slots, pos); + spill_call_arguments(dfg, &mut func.locations, &mut func.stack_slots, pos); // Yes, we changed stuff. true } -/// Insert ABI conversion code before and after the return instruction at `pos`. +/// Insert ABI conversion code before and after the return instruction at `inst`. /// /// Return `true` if any instructions were inserted. -pub fn handle_return_abi(dfg: &mut DataFlowGraph, - cfg: &ControlFlowGraph, - pos: &mut Cursor, - sig: &Signature) - -> bool { - let inst = pos.current_inst() - .expect("Cursor must point to a return instruction"); +pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool { + let dfg = &mut func.dfg; + let sig = &mut func.signature; + let pos = &mut Cursor::new(&mut func.layout).at_inst(inst); // Check if the returned types already match the signature. if check_return_signature(dfg, inst, sig) { diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index 9cc37dd896..f4db515c6b 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -13,9 +13,10 @@ //! The legalizer does not deal with register allocation constraints. These constraints are derived //! from the encoding recipes, and solved later by the register allocator. +use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; use flowgraph::ControlFlowGraph; -use ir::{self, Function, Cursor, CursorBase}; +use ir; use ir::condcodes::IntCC; use isa::TargetIsa; use bitset::BitSet; @@ -28,7 +29,7 @@ mod split; /// - Transform any instructions that don't have a legal representation in `isa`. /// - Fill out `func.encodings`. /// -pub fn legalize_function(func: &mut Function, +pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, domtree: &DominatorTree, isa: &TargetIsa) { @@ -36,7 +37,7 @@ pub fn legalize_function(func: &mut Function, func.encodings.resize(func.dfg.num_insts()); - let mut pos = Cursor::new(&mut func.layout); + let mut pos = FuncCursor::new(func); // Process EBBs in a reverse post-order. This minimizes the number of split instructions we // need. @@ -48,36 +49,32 @@ pub fn legalize_function(func: &mut Function, let mut prev_pos = pos.position(); while let Some(inst) = pos.next_inst() { - let opcode = func.dfg[inst].opcode(); + let opcode = pos.func.dfg[inst].opcode(); // Check for ABI boundaries that need to be converted to the legalized signature. - if opcode.is_call() && - boundary::handle_call_abi(&mut func.dfg, - &mut func.locations, - &mut func.stack_slots, - cfg, - &mut pos) { + if opcode.is_call() && boundary::handle_call_abi(inst, pos.func, cfg) { // Go back and legalize the inserted argument conversion instructions. pos.set_position(prev_pos); continue; } - if opcode.is_return() && - boundary::handle_return_abi(&mut func.dfg, cfg, &mut pos, &func.signature) { + if opcode.is_return() && boundary::handle_return_abi(inst, pos.func, cfg) { // Go back and legalize the inserted return value conversion instructions. pos.set_position(prev_pos); continue; } if opcode.is_branch() { - split::simplify_branch_arguments(&mut func.dfg, inst); + split::simplify_branch_arguments(&mut pos.func.dfg, inst); } - match isa.encode(&func.dfg, &func.dfg[inst], func.dfg.ctrl_typevar(inst)) { - Ok(encoding) => *func.encodings.ensure(inst) = encoding, + match isa.encode(&pos.func.dfg, + &pos.func.dfg[inst], + pos.func.dfg.ctrl_typevar(inst)) { + Ok(encoding) => *pos.func.encodings.ensure(inst) = encoding, Err(action) => { // We should transform the instruction into legal equivalents. - let changed = action(&mut func.dfg, cfg, &mut pos); + let changed = action(inst, pos.func, cfg); // If the current instruction was replaced, we need to double back and revisit // the expanded sequence. This is both to assign encodings and possible to // expand further. @@ -94,7 +91,6 @@ pub fn legalize_function(func: &mut Function, prev_pos = pos.position(); } } - func.encodings.resize(func.dfg.num_insts()); } // Include legalization patterns that were generated by `gen_legalizer.py` from the `XForms` in