Use hand written legalizations in simple_legalize
This allows removal of the legalization dsl once the old backends are removed.
This commit is contained in:
@@ -213,49 +213,126 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
|||||||
/// Perform a simple legalization by expansion of the function, without
|
/// Perform a simple legalization by expansion of the function, without
|
||||||
/// platform-specific transforms.
|
/// platform-specific transforms.
|
||||||
pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa: &dyn TargetIsa) {
|
pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa: &dyn TargetIsa) {
|
||||||
|
macro_rules! expand_imm_op {
|
||||||
|
($pos:ident, $inst:ident: $from:ident => $to:ident) => {{
|
||||||
|
let (arg, imm) = match $pos.func.dfg[$inst] {
|
||||||
|
ir::InstructionData::BinaryImm64 {
|
||||||
|
opcode: _,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => (arg, imm),
|
||||||
|
_ => panic!(
|
||||||
|
concat!("Expected ", stringify!($from), ": {}"),
|
||||||
|
$pos.func.dfg.display_inst($inst, None)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let ty = $pos.func.dfg.value_type(arg);
|
||||||
|
let imm = $pos.ins().iconst(ty, imm);
|
||||||
|
$pos.func.dfg.replace($inst).$to(arg, imm);
|
||||||
|
}};
|
||||||
|
|
||||||
|
($pos:ident, $inst:ident<$ty:ident>: $from:ident => $to:ident) => {{
|
||||||
|
let (arg, imm) = match $pos.func.dfg[$inst] {
|
||||||
|
ir::InstructionData::BinaryImm64 {
|
||||||
|
opcode: _,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => (arg, imm),
|
||||||
|
_ => panic!(
|
||||||
|
concat!("Expected ", stringify!($from), ": {}"),
|
||||||
|
$pos.func.dfg.display_inst($inst, None)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let imm = $pos.ins().iconst($ty, imm);
|
||||||
|
$pos.func.dfg.replace($inst).$to(arg, imm);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
let mut pos = FuncCursor::new(func);
|
let mut pos = FuncCursor::new(func);
|
||||||
let func_begin = pos.position();
|
let func_begin = pos.position();
|
||||||
pos.set_position(func_begin);
|
pos.set_position(func_begin);
|
||||||
while let Some(_block) = pos.next_block() {
|
while let Some(_block) = pos.next_block() {
|
||||||
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 expanded = match pos.func.dfg[inst].opcode() {
|
match pos.func.dfg[inst].opcode() {
|
||||||
ir::Opcode::BrIcmp
|
// control flow
|
||||||
| ir::Opcode::GlobalValue
|
ir::Opcode::BrIcmp => expand_br_icmp(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::HeapAddr
|
ir::Opcode::Trapnz | ir::Opcode::Trapz | ir::Opcode::ResumableTrapnz => {
|
||||||
| ir::Opcode::StackLoad
|
expand_cond_trap(inst, &mut pos.func, cfg, isa);
|
||||||
| ir::Opcode::StackStore
|
}
|
||||||
| ir::Opcode::TableAddr
|
|
||||||
| ir::Opcode::Trapnz
|
// memory and constants
|
||||||
| ir::Opcode::Trapz
|
ir::Opcode::GlobalValue => expand_global_value(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::ResumableTrapnz
|
ir::Opcode::HeapAddr => expand_heap_addr(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::BandImm
|
ir::Opcode::StackLoad => expand_stack_load(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::BorImm
|
ir::Opcode::StackStore => expand_stack_store(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::BxorImm
|
ir::Opcode::TableAddr => expand_table_addr(inst, &mut pos.func, cfg, isa),
|
||||||
| ir::Opcode::IaddImm
|
|
||||||
| ir::Opcode::IfcmpImm
|
// bitops
|
||||||
| ir::Opcode::ImulImm
|
ir::Opcode::BandImm => expand_imm_op!(pos, inst: band_imm => band),
|
||||||
| ir::Opcode::IrsubImm
|
ir::Opcode::BorImm => expand_imm_op!(pos, inst: bor_imm => bor),
|
||||||
| ir::Opcode::IshlImm
|
ir::Opcode::BxorImm => expand_imm_op!(pos, inst: bxor_imm => bxor),
|
||||||
| ir::Opcode::RotlImm
|
ir::Opcode::IaddImm => expand_imm_op!(pos, inst: iadd_imm => iadd),
|
||||||
| ir::Opcode::RotrImm
|
|
||||||
| ir::Opcode::SdivImm
|
// bitshifting
|
||||||
| ir::Opcode::SremImm
|
ir::Opcode::IshlImm => expand_imm_op!(pos, inst<I32>: ishl_imm => ishl),
|
||||||
| ir::Opcode::SshrImm
|
ir::Opcode::RotlImm => expand_imm_op!(pos, inst<I32>: rotl_imm => rotl),
|
||||||
| ir::Opcode::UdivImm
|
ir::Opcode::RotrImm => expand_imm_op!(pos, inst<I32>: rotr_imm => rotr),
|
||||||
| ir::Opcode::UremImm
|
ir::Opcode::SshrImm => expand_imm_op!(pos, inst<I32>: sshr_imm => sshr),
|
||||||
| ir::Opcode::UshrImm
|
ir::Opcode::UshrImm => expand_imm_op!(pos, inst<I32>: ushr_imm => ushr),
|
||||||
| ir::Opcode::IcmpImm => expand(inst, &mut pos.func, cfg, isa),
|
|
||||||
_ => false,
|
// math
|
||||||
|
ir::Opcode::IrsubImm => {
|
||||||
|
let (arg, imm) = match pos.func.dfg[inst] {
|
||||||
|
ir::InstructionData::BinaryImm64 {
|
||||||
|
opcode: _,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => (arg, imm),
|
||||||
|
_ => panic!(
|
||||||
|
"Expected irsub_imm: {}",
|
||||||
|
pos.func.dfg.display_inst(inst, None)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).isub(imm, arg); // note: arg order reversed
|
||||||
|
}
|
||||||
|
ir::Opcode::ImulImm => expand_imm_op!(pos, inst: imul_imm => imul),
|
||||||
|
ir::Opcode::SdivImm => expand_imm_op!(pos, inst: sdiv_imm => sdiv),
|
||||||
|
ir::Opcode::SremImm => expand_imm_op!(pos, inst: srem_imm => srem),
|
||||||
|
ir::Opcode::UdivImm => expand_imm_op!(pos, inst: udiv_imm => udiv),
|
||||||
|
ir::Opcode::UremImm => expand_imm_op!(pos, inst: urem_imm => urem),
|
||||||
|
|
||||||
|
// comparisons
|
||||||
|
ir::Opcode::IfcmpImm => expand_imm_op!(pos, inst: ifcmp_imm => ifcmp),
|
||||||
|
ir::Opcode::IcmpImm => {
|
||||||
|
let (cc, x, y) = match pos.func.dfg[inst] {
|
||||||
|
ir::InstructionData::IntCompareImm {
|
||||||
|
opcode: _,
|
||||||
|
cond,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => (cond, arg, imm),
|
||||||
|
_ => panic!(
|
||||||
|
"Expected ircmp_imm: {}",
|
||||||
|
pos.func.dfg.display_inst(inst, None)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let ty = pos.func.dfg.value_type(x);
|
||||||
|
let y = pos.ins().iconst(ty, y);
|
||||||
|
pos.func.dfg.replace(inst).icmp(cc, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
prev_pos = pos.position();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if expanded {
|
// Legalization implementations require fixpoint loop here.
|
||||||
// Legalization implementations require fixpoint loop
|
// TODO: fix this.
|
||||||
// here. TODO: fix this.
|
pos.set_position(prev_pos);
|
||||||
pos.set_position(prev_pos);
|
|
||||||
} else {
|
|
||||||
prev_pos = pos.position();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user