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.
This commit is contained in:
Jakob Stoklund Olesen
2017-08-17 15:45:21 -07:00
parent 5566c99dba
commit 4b94ea21ed
4 changed files with 43 additions and 54 deletions

View File

@@ -353,16 +353,12 @@ def gen_xform_group(xgrp, fmt, type_sets):
fmt.doc_comment("Legalize the instruction pointed to by `pos`.") fmt.doc_comment("Legalize the instruction pointed to by `pos`.")
fmt.line('#[allow(unused_variables,unused_assignments)]') fmt.line('#[allow(unused_variables,unused_assignments)]')
with fmt.indented( with fmt.indented(
'pub fn {}(dfg: &mut ir::DataFlowGraph, ' 'pub fn {}(inst: ir::Inst, '
'cfg: &mut ::flowgraph::ControlFlowGraph, ' 'func: &mut ir::Function, '
'pos: &mut ir::Cursor) -> ' 'cfg: &mut ::flowgraph::ControlFlowGraph) -> '
'bool {{'.format(xgrp.name), '}'): 'bool {{'.format(xgrp.name), '}'):
fmt.line('use ir::{InstBuilder, CursorBase};') 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. # Group the xforms by opcode so we can generate a big switch.
# Preserve ordering. # Preserve ordering.
xforms = defaultdict(list) # type: DefaultDict[str, List[XForm]] 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 inst = xform.src.rtl[0].expr.inst
xforms[inst.camel_name].append(xform) xforms[inst.camel_name].append(xform)
with fmt.indented('match dfg[inst].opcode() {', '}'): with fmt.indented('{', '}'):
for camel_name in sorted(xforms.keys()): fmt.line(
with fmt.indented( 'let pos = &mut ir::Cursor::new(&mut func.layout)'
'ir::Opcode::{} => {{'.format(camel_name), '}'): '.at_inst(inst);')
for xform in xforms[camel_name]: fmt.line('let dfg = &mut func.dfg;')
gen_xform(xform, fmt, type_sets) with fmt.indented('match dfg[inst].opcode() {', '}'):
# We'll assume there are uncovered opcodes. for camel_name in sorted(xforms.keys()):
fmt.line('_ => {},') 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 we fall through, nothing was expanded. Call the chain if any.
if xgrp.chain: if xgrp.chain:
fmt.format('{}(dfg, cfg, pos)', xgrp.chain.rust_name()) fmt.format('{}(inst, func, cfg)', xgrp.chain.rust_name())
else: else:
fmt.line('false') fmt.line('false')

View File

@@ -138,9 +138,9 @@ impl settings::Configurable for Builder {
/// legalize it? /// legalize it?
/// ///
/// The `Encodings` iterator returns a legalization function to call. /// The `Encodings` iterator returns a legalization function to call.
pub type Legalize = fn(&mut ir::DataFlowGraph, pub type Legalize = fn(ir::Inst,
&mut flowgraph::ControlFlowGraph, &mut ir::Function,
&mut ir::Cursor) &mut flowgraph::ControlFlowGraph)
-> bool; -> bool;
/// Methods that are specialized to a target ISA. /// Methods that are specialized to a target ISA.

View File

@@ -452,18 +452,13 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
/// original return values. The call's result values will be adapted to match the new signature. /// original return values. The call's result values will be adapted to match the new signature.
/// ///
/// Returns `true` if any instructions were inserted. /// Returns `true` if any instructions were inserted.
pub fn handle_call_abi(dfg: &mut DataFlowGraph, pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool {
locations: &mut ValueLocations, let dfg = &mut func.dfg;
stack_slots: &mut StackSlots, let pos = &mut Cursor::new(&mut func.layout).at_inst(inst);
cfg: &ControlFlowGraph,
pos: &mut Cursor)
-> bool {
let mut inst = pos.current_inst()
.expect("Cursor must point to a call instruction");
// Start by checking if the argument types already match the signature. // Start by checking if the argument types already match the signature.
let sig_ref = match check_call_signature(dfg, inst) { 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, Err(s) => s,
}; };
@@ -489,22 +484,19 @@ pub fn handle_call_abi(dfg: &mut DataFlowGraph,
// Go back and insert spills for any stack arguments. // Go back and insert spills for any stack arguments.
pos.goto_inst(inst); 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. // Yes, we changed stuff.
true 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. /// Return `true` if any instructions were inserted.
pub fn handle_return_abi(dfg: &mut DataFlowGraph, pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool {
cfg: &ControlFlowGraph, let dfg = &mut func.dfg;
pos: &mut Cursor, let sig = &mut func.signature;
sig: &Signature) let pos = &mut Cursor::new(&mut func.layout).at_inst(inst);
-> bool {
let inst = pos.current_inst()
.expect("Cursor must point to a return instruction");
// Check if the returned types already match the signature. // Check if the returned types already match the signature.
if check_return_signature(dfg, inst, sig) { if check_return_signature(dfg, inst, sig) {

View File

@@ -13,9 +13,10 @@
//! The legalizer does not deal with register allocation constraints. These constraints are derived //! The legalizer does not deal with register allocation constraints. These constraints are derived
//! from the encoding recipes, and solved later by the register allocator. //! from the encoding recipes, and solved later by the register allocator.
use cursor::{Cursor, FuncCursor};
use dominator_tree::DominatorTree; use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph; use flowgraph::ControlFlowGraph;
use ir::{self, Function, Cursor, CursorBase}; use ir;
use ir::condcodes::IntCC; use ir::condcodes::IntCC;
use isa::TargetIsa; use isa::TargetIsa;
use bitset::BitSet; use bitset::BitSet;
@@ -28,7 +29,7 @@ mod split;
/// - Transform any instructions that don't have a legal representation in `isa`. /// - Transform any instructions that don't have a legal representation in `isa`.
/// - Fill out `func.encodings`. /// - Fill out `func.encodings`.
/// ///
pub fn legalize_function(func: &mut Function, pub fn legalize_function(func: &mut ir::Function,
cfg: &mut ControlFlowGraph, cfg: &mut ControlFlowGraph,
domtree: &DominatorTree, domtree: &DominatorTree,
isa: &TargetIsa) { isa: &TargetIsa) {
@@ -36,7 +37,7 @@ pub fn legalize_function(func: &mut Function,
func.encodings.resize(func.dfg.num_insts()); 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 // Process EBBs in a reverse post-order. This minimizes the number of split instructions we
// need. // need.
@@ -48,36 +49,32 @@ pub fn legalize_function(func: &mut Function,
let mut prev_pos = pos.position(); let mut prev_pos = pos.position();
while let Some(inst) = pos.next_inst() { 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. // Check for ABI boundaries that need to be converted to the legalized signature.
if opcode.is_call() && if opcode.is_call() && boundary::handle_call_abi(inst, pos.func, cfg) {
boundary::handle_call_abi(&mut func.dfg,
&mut func.locations,
&mut func.stack_slots,
cfg,
&mut pos) {
// Go back and legalize the inserted argument conversion instructions. // Go back and legalize the inserted argument conversion instructions.
pos.set_position(prev_pos); pos.set_position(prev_pos);
continue; continue;
} }
if opcode.is_return() && if opcode.is_return() && boundary::handle_return_abi(inst, pos.func, cfg) {
boundary::handle_return_abi(&mut func.dfg, cfg, &mut pos, &func.signature) {
// Go back and legalize the inserted return value conversion instructions. // Go back and legalize the inserted return value conversion instructions.
pos.set_position(prev_pos); pos.set_position(prev_pos);
continue; continue;
} }
if opcode.is_branch() { 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)) { match isa.encode(&pos.func.dfg,
Ok(encoding) => *func.encodings.ensure(inst) = encoding, &pos.func.dfg[inst],
pos.func.dfg.ctrl_typevar(inst)) {
Ok(encoding) => *pos.func.encodings.ensure(inst) = encoding,
Err(action) => { Err(action) => {
// We should transform the instruction into legal equivalents. // 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 // 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 // the expanded sequence. This is both to assign encodings and possible to
// expand further. // expand further.
@@ -94,7 +91,6 @@ pub fn legalize_function(func: &mut Function,
prev_pos = pos.position(); 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 // Include legalization patterns that were generated by `gen_legalizer.py` from the `XForms` in