Match on InstructionData instead of Opcode
This should be faster by avoiding matching on InstructionData to get the Opcode, then on Opcode and then finally on the InstructionData again to get the arguments
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
use crate::cursor::{Cursor, FuncCursor};
|
use crate::cursor::{Cursor, FuncCursor};
|
||||||
use crate::flowgraph::ControlFlowGraph;
|
use crate::flowgraph::ControlFlowGraph;
|
||||||
use crate::ir::types::I32;
|
use crate::ir::types::I32;
|
||||||
use crate::ir::{self, InstBuilder, MemFlags};
|
use crate::ir::{self, InstBuilder, InstructionData, MemFlags};
|
||||||
use crate::isa::TargetIsa;
|
use crate::isa::TargetIsa;
|
||||||
|
|
||||||
mod globalvalue;
|
mod globalvalue;
|
||||||
@@ -30,116 +30,211 @@ use self::table::expand_table_addr;
|
|||||||
/// 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)
|
|
||||||
),
|
|
||||||
};
|
|
||||||
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)
|
|
||||||
),
|
|
||||||
};
|
|
||||||
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() {
|
||||||
match pos.func.dfg[inst].opcode() {
|
match pos.func.dfg[inst] {
|
||||||
// control flow
|
// control flow
|
||||||
ir::Opcode::BrIcmp => expand_br_icmp(inst, &mut pos.func, cfg, isa),
|
InstructionData::BranchIcmp {
|
||||||
ir::Opcode::Trapnz | ir::Opcode::Trapz | ir::Opcode::ResumableTrapnz => {
|
opcode: ir::Opcode::BrIcmp,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
expand_br_icmp(inst, &mut pos.func, cfg, isa);
|
||||||
|
}
|
||||||
|
InstructionData::CondTrap {
|
||||||
|
opcode: ir::Opcode::Trapnz | ir::Opcode::Trapz | ir::Opcode::ResumableTrapnz,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
expand_cond_trap(inst, &mut pos.func, cfg, isa);
|
expand_cond_trap(inst, &mut pos.func, cfg, isa);
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory and constants
|
// memory and constants
|
||||||
ir::Opcode::GlobalValue => expand_global_value(inst, &mut pos.func, cfg, isa),
|
InstructionData::UnaryGlobalValue {
|
||||||
ir::Opcode::HeapAddr => expand_heap_addr(inst, &mut pos.func, cfg, isa),
|
opcode: ir::Opcode::GlobalValue,
|
||||||
ir::Opcode::StackLoad => expand_stack_load(inst, &mut pos.func, cfg, isa),
|
..
|
||||||
ir::Opcode::StackStore => expand_stack_store(inst, &mut pos.func, cfg, isa),
|
} => expand_global_value(inst, &mut pos.func, cfg, isa),
|
||||||
ir::Opcode::TableAddr => expand_table_addr(inst, &mut pos.func, cfg, isa),
|
InstructionData::HeapAddr {
|
||||||
|
opcode: ir::Opcode::HeapAddr,
|
||||||
|
..
|
||||||
|
} => expand_heap_addr(inst, &mut pos.func, cfg, isa),
|
||||||
|
InstructionData::StackLoad {
|
||||||
|
opcode: ir::Opcode::StackLoad,
|
||||||
|
..
|
||||||
|
} => expand_stack_load(inst, &mut pos.func, cfg, isa),
|
||||||
|
InstructionData::StackStore {
|
||||||
|
opcode: ir::Opcode::StackStore,
|
||||||
|
..
|
||||||
|
} => expand_stack_store(inst, &mut pos.func, cfg, isa),
|
||||||
|
InstructionData::TableAddr {
|
||||||
|
opcode: ir::Opcode::TableAddr,
|
||||||
|
..
|
||||||
|
} => expand_table_addr(inst, &mut pos.func, cfg, isa),
|
||||||
|
|
||||||
// bitops
|
// bitops
|
||||||
ir::Opcode::BandImm => expand_imm_op!(pos, inst: band_imm => band),
|
InstructionData::BinaryImm64 {
|
||||||
ir::Opcode::BorImm => expand_imm_op!(pos, inst: bor_imm => bor),
|
opcode: ir::Opcode::BandImm,
|
||||||
ir::Opcode::BxorImm => expand_imm_op!(pos, inst: bxor_imm => bxor),
|
arg,
|
||||||
ir::Opcode::IaddImm => expand_imm_op!(pos, inst: iadd_imm => iadd),
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).band(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::BorImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).bor(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::BxorImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).bxor(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::IaddImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).iadd(arg, imm);
|
||||||
|
}
|
||||||
|
|
||||||
// bitshifting
|
// bitshifting
|
||||||
ir::Opcode::IshlImm => expand_imm_op!(pos, inst<I32>: ishl_imm => ishl),
|
InstructionData::BinaryImm64 {
|
||||||
ir::Opcode::RotlImm => expand_imm_op!(pos, inst<I32>: rotl_imm => rotl),
|
opcode: ir::Opcode::IshlImm,
|
||||||
ir::Opcode::RotrImm => expand_imm_op!(pos, inst<I32>: rotr_imm => rotr),
|
arg,
|
||||||
ir::Opcode::SshrImm => expand_imm_op!(pos, inst<I32>: sshr_imm => sshr),
|
imm,
|
||||||
ir::Opcode::UshrImm => expand_imm_op!(pos, inst<I32>: ushr_imm => ushr),
|
} => {
|
||||||
|
let imm = pos.ins().iconst(I32, imm);
|
||||||
|
pos.func.dfg.replace(inst).ishl(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::RotlImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let imm = pos.ins().iconst(I32, imm);
|
||||||
|
pos.func.dfg.replace(inst).rotl(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::RotrImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let imm = pos.ins().iconst(I32, imm);
|
||||||
|
pos.func.dfg.replace(inst).rotr(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::SshrImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let imm = pos.ins().iconst(I32, imm);
|
||||||
|
pos.func.dfg.replace(inst).sshr(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::UshrImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let imm = pos.ins().iconst(I32, imm);
|
||||||
|
pos.func.dfg.replace(inst).ushr(arg, imm);
|
||||||
|
}
|
||||||
|
|
||||||
// math
|
// math
|
||||||
ir::Opcode::IrsubImm => {
|
InstructionData::BinaryImm64 {
|
||||||
let (arg, imm) = match pos.func.dfg[inst] {
|
opcode: ir::Opcode::IrsubImm,
|
||||||
ir::InstructionData::BinaryImm64 {
|
arg,
|
||||||
opcode: _,
|
imm,
|
||||||
arg,
|
} => {
|
||||||
imm,
|
|
||||||
} => (arg, imm),
|
|
||||||
_ => panic!("Expected irsub_imm: {}", pos.func.dfg.display_inst(inst)),
|
|
||||||
};
|
|
||||||
let ty = pos.func.dfg.value_type(arg);
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
let imm = pos.ins().iconst(ty, imm);
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
pos.func.dfg.replace(inst).isub(imm, arg); // note: arg order reversed
|
pos.func.dfg.replace(inst).isub(imm, arg); // note: arg order reversed
|
||||||
}
|
}
|
||||||
ir::Opcode::ImulImm => expand_imm_op!(pos, inst: imul_imm => imul),
|
InstructionData::BinaryImm64 {
|
||||||
ir::Opcode::SdivImm => expand_imm_op!(pos, inst: sdiv_imm => sdiv),
|
opcode: ir::Opcode::ImulImm,
|
||||||
ir::Opcode::SremImm => expand_imm_op!(pos, inst: srem_imm => srem),
|
arg,
|
||||||
ir::Opcode::UdivImm => expand_imm_op!(pos, inst: udiv_imm => udiv),
|
imm,
|
||||||
ir::Opcode::UremImm => expand_imm_op!(pos, inst: urem_imm => urem),
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).imul(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::SdivImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).sdiv(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::SremImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).srem(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::UdivImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).udiv(arg, imm);
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm64 {
|
||||||
|
opcode: ir::Opcode::UremImm,
|
||||||
|
arg,
|
||||||
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).urem(arg, imm);
|
||||||
|
}
|
||||||
|
|
||||||
// comparisons
|
// comparisons
|
||||||
ir::Opcode::IfcmpImm => expand_imm_op!(pos, inst: ifcmp_imm => ifcmp),
|
InstructionData::BinaryImm64 {
|
||||||
ir::Opcode::IcmpImm => {
|
opcode: ir::Opcode::IfcmpImm,
|
||||||
let (cc, x, y) = match pos.func.dfg[inst] {
|
arg,
|
||||||
ir::InstructionData::IntCompareImm {
|
imm,
|
||||||
opcode: _,
|
} => {
|
||||||
cond,
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
arg,
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
imm,
|
pos.func.dfg.replace(inst).ifcmp(arg, imm);
|
||||||
} => (cond, arg, imm),
|
}
|
||||||
_ => panic!("Expected ircmp_imm: {}", pos.func.dfg.display_inst(inst)),
|
InstructionData::IntCompareImm {
|
||||||
};
|
opcode: ir::Opcode::IcmpImm,
|
||||||
let ty = pos.func.dfg.value_type(x);
|
cond,
|
||||||
let y = pos.ins().iconst(ty, y);
|
arg,
|
||||||
pos.func.dfg.replace(inst).icmp(cc, x, y);
|
imm,
|
||||||
|
} => {
|
||||||
|
let ty = pos.func.dfg.value_type(arg);
|
||||||
|
let imm = pos.ins().iconst(ty, imm);
|
||||||
|
pos.func.dfg.replace(inst).icmp(cond, arg, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
prev_pos = pos.position();
|
prev_pos = pos.position();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Legalization implementations require fixpoint loop here.
|
// Legalization implementations require fixpoint loop here.
|
||||||
// TODO: fix this.
|
// TODO: fix this.
|
||||||
|
|||||||
Reference in New Issue
Block a user