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:
bjorn3
2021-10-31 17:52:43 +01:00
parent 795e381be4
commit 96b14ed8eb

View File

@@ -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.