Remove ancient register allocation (#3401)
This commit is contained in:
@@ -19,179 +19,14 @@ use crate::ir::types::I32;
|
||||
use crate::ir::{self, InstBuilder, MemFlags};
|
||||
use crate::isa::TargetIsa;
|
||||
|
||||
use crate::timing;
|
||||
use alloc::collections::BTreeSet;
|
||||
|
||||
mod boundary;
|
||||
mod globalvalue;
|
||||
mod heap;
|
||||
mod libcall;
|
||||
mod split;
|
||||
mod table;
|
||||
|
||||
use self::globalvalue::expand_global_value;
|
||||
use self::heap::expand_heap_addr;
|
||||
pub(crate) use self::libcall::expand_as_libcall;
|
||||
use self::table::expand_table_addr;
|
||||
|
||||
enum LegalizeInstResult {
|
||||
Done,
|
||||
Legalized,
|
||||
SplitLegalizePending,
|
||||
}
|
||||
|
||||
/// Legalize `inst` for `isa`.
|
||||
fn legalize_inst(
|
||||
inst: ir::Inst,
|
||||
pos: &mut FuncCursor,
|
||||
cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) -> LegalizeInstResult {
|
||||
let opcode = pos.func.dfg[inst].opcode();
|
||||
|
||||
// Check for ABI boundaries that need to be converted to the legalized signature.
|
||||
if opcode.is_call() {
|
||||
if boundary::handle_call_abi(isa, inst, pos.func, cfg) {
|
||||
return LegalizeInstResult::Legalized;
|
||||
}
|
||||
} else if opcode.is_return() {
|
||||
if boundary::handle_return_abi(inst, pos.func, cfg) {
|
||||
return LegalizeInstResult::Legalized;
|
||||
}
|
||||
} else if opcode.is_branch() {
|
||||
split::simplify_branch_arguments(&mut pos.func.dfg, inst);
|
||||
} else if opcode == ir::Opcode::Isplit {
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let arg = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::Unary { arg, .. } => pos.func.dfg.resolve_aliases(arg),
|
||||
_ => panic!("Expected isplit: {}", pos.func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
match pos.func.dfg.value_def(arg) {
|
||||
ir::ValueDef::Result(inst, _num) => {
|
||||
if let ir::InstructionData::Binary {
|
||||
opcode: ir::Opcode::Iconcat,
|
||||
..
|
||||
} = pos.func.dfg[inst]
|
||||
{
|
||||
// `arg` was created by an `iconcat` instruction.
|
||||
} else {
|
||||
// `arg` was not created by an `iconcat` instruction. Don't try to resolve it,
|
||||
// as otherwise `split::isplit` will re-insert the original `isplit`, causing
|
||||
// an endless loop.
|
||||
return LegalizeInstResult::SplitLegalizePending;
|
||||
}
|
||||
}
|
||||
ir::ValueDef::Param(_block, _num) => {}
|
||||
}
|
||||
|
||||
let res = pos.func.dfg.inst_results(inst).to_vec();
|
||||
assert_eq!(res.len(), 2);
|
||||
let (resl, resh) = (res[0], res[1]); // Prevent borrowck error
|
||||
|
||||
// Remove old isplit
|
||||
pos.func.dfg.clear_results(inst);
|
||||
pos.remove_inst();
|
||||
|
||||
let curpos = pos.position();
|
||||
let srcloc = pos.srcloc();
|
||||
let (xl, xh) = split::isplit(pos.func, cfg, curpos, srcloc, arg);
|
||||
|
||||
pos.func.dfg.change_to_alias(resl, xl);
|
||||
pos.func.dfg.change_to_alias(resh, xh);
|
||||
|
||||
return LegalizeInstResult::Legalized;
|
||||
}
|
||||
|
||||
match pos.func.update_encoding(inst, isa) {
|
||||
Ok(()) => LegalizeInstResult::Done,
|
||||
Err(action) => {
|
||||
// We should transform the instruction into legal equivalents.
|
||||
// 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.
|
||||
// There's a risk of infinite looping here if the legalization patterns are
|
||||
// unsound. Should we attempt to detect that?
|
||||
if action(inst, pos.func, cfg, isa) {
|
||||
return LegalizeInstResult::Legalized;
|
||||
}
|
||||
|
||||
// We don't have any pattern expansion for this instruction either.
|
||||
// Try converting it to a library call as a last resort.
|
||||
if expand_as_libcall(inst, pos.func, isa) {
|
||||
LegalizeInstResult::Legalized
|
||||
} else {
|
||||
LegalizeInstResult::Done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Legalize `func` for `isa`.
|
||||
///
|
||||
/// - Transform any instructions that don't have a legal representation in `isa`.
|
||||
/// - Fill out `func.encodings`.
|
||||
///
|
||||
pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa: &dyn TargetIsa) {
|
||||
let _tt = timing::legalize();
|
||||
debug_assert!(cfg.is_valid());
|
||||
|
||||
boundary::legalize_signatures(func, isa);
|
||||
|
||||
func.encodings.resize(func.dfg.num_insts());
|
||||
|
||||
let mut pos = FuncCursor::new(func);
|
||||
let func_begin = pos.position();
|
||||
|
||||
// Split block params before trying to legalize instructions, so that the newly introduced
|
||||
// isplit instructions get legalized.
|
||||
while let Some(block) = pos.next_block() {
|
||||
split::split_block_params(pos.func, cfg, block);
|
||||
}
|
||||
|
||||
pos.set_position(func_begin);
|
||||
|
||||
// This must be a set to prevent trying to legalize `isplit` and `vsplit` twice in certain cases.
|
||||
let mut pending_splits = BTreeSet::new();
|
||||
|
||||
// Process blocks in layout order. Some legalization actions may split the current block or append
|
||||
// new ones to the end. We need to make sure we visit those new blocks too.
|
||||
while let Some(_block) = pos.next_block() {
|
||||
// Keep track of the cursor position before the instruction being processed, so we can
|
||||
// double back when replacing instructions.
|
||||
let mut prev_pos = pos.position();
|
||||
|
||||
while let Some(inst) = pos.next_inst() {
|
||||
match legalize_inst(inst, &mut pos, cfg, isa) {
|
||||
// Remember this position in case we need to double back.
|
||||
LegalizeInstResult::Done => prev_pos = pos.position(),
|
||||
|
||||
// Go back and legalize the inserted return value conversion instructions.
|
||||
LegalizeInstResult::Legalized => pos.set_position(prev_pos),
|
||||
|
||||
// The argument of a `isplit` or `vsplit` instruction didn't resolve to a
|
||||
// `iconcat` or `vconcat` instruction. Try again after legalizing the rest of
|
||||
// the instructions.
|
||||
LegalizeInstResult::SplitLegalizePending => {
|
||||
pending_splits.insert(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try legalizing `isplit` and `vsplit` instructions, which could not previously be legalized.
|
||||
for inst in pending_splits {
|
||||
pos.goto_inst(inst);
|
||||
legalize_inst(inst, &mut pos, cfg, isa);
|
||||
}
|
||||
|
||||
// Now that we've lowered all br_tables, we don't need the jump tables anymore.
|
||||
if !isa.flags().enable_jump_tables() {
|
||||
pos.func.jump_tables.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a simple legalization by expansion of the function, without
|
||||
/// platform-specific transforms.
|
||||
pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa: &dyn TargetIsa) {
|
||||
|
||||
Reference in New Issue
Block a user