diff --git a/cranelift/codegen/meta/src/isa/arm32/mod.rs b/cranelift/codegen/meta/src/isa/arm32/mod.rs index f699ece8eb54..84d93afadcac 100644 --- a/cranelift/codegen/meta/src/isa/arm32/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm32/mod.rs @@ -1,4 +1,3 @@ -use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; use crate::cdsl::recipes::Recipes; @@ -55,20 +54,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build(); - // CPU modes for 32-bit ARM and Thumb2. - let mut a32 = CpuMode::new("A32"); - let mut t32 = CpuMode::new("T32"); - - // TODO refine these. - let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags"); - a32.legalize_default(narrow_flags); - t32.legalize_default(narrow_flags); - - // Make sure that the expand code is used, thus generated. - let expand = shared_defs.transform_groups.by_name("expand"); - a32.legalize_monomorphic(expand); - - let cpu_modes = vec![a32, t32]; + let cpu_modes = vec![]; // TODO implement arm32 recipes. let recipes = Recipes::new(); diff --git a/cranelift/codegen/meta/src/isa/arm64/mod.rs b/cranelift/codegen/meta/src/isa/arm64/mod.rs index 4277e147a7d3..2ad618d3cddb 100644 --- a/cranelift/codegen/meta/src/isa/arm64/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm64/mod.rs @@ -1,4 +1,3 @@ -use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; use crate::cdsl::recipes::Recipes; @@ -54,15 +53,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build(); - let mut a64 = CpuMode::new("A64"); - - // TODO refine these. - let expand_flags = shared_defs.transform_groups.by_name("expand_flags"); - let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags"); - a64.legalize_monomorphic(expand_flags); - a64.legalize_default(narrow_flags); - - let cpu_modes = vec![a64]; + let cpu_modes = vec![]; // TODO implement arm64 recipes. let recipes = Recipes::new(); diff --git a/cranelift/codegen/meta/src/isa/s390x/mod.rs b/cranelift/codegen/meta/src/isa/s390x/mod.rs index b0837dc22db8..20796804b0c1 100644 --- a/cranelift/codegen/meta/src/isa/s390x/mod.rs +++ b/cranelift/codegen/meta/src/isa/s390x/mod.rs @@ -1,4 +1,3 @@ -use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; use crate::cdsl::recipes::Recipes; @@ -51,10 +50,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let recipes = Recipes::new(); let encodings_predicates = InstructionPredicateMap::new(); - let mut mode = CpuMode::new("s390x"); - let expand = shared_defs.transform_groups.by_name("expand"); - mode.legalize_default(expand); - let cpu_modes = vec![mode]; + let cpu_modes = vec![]; TargetIsa::new( "s390x", diff --git a/cranelift/codegen/src/legalizer/mod.rs b/cranelift/codegen/src/legalizer/mod.rs index 149a65b6394f..3b794a1e2527 100644 --- a/cranelift/codegen/src/legalizer/mod.rs +++ b/cranelift/codegen/src/legalizer/mod.rs @@ -13,6 +13,7 @@ //! The legalizer does not deal with register allocation constraints. These constraints are derived //! from the encoding recipes, and solved later by the register allocator. +#[cfg(any(feature = "x86", feature = "riscv"))] use crate::bitset::BitSet; use crate::cursor::{Cursor, FuncCursor}; use crate::flowgraph::ControlFlowGraph; @@ -20,19 +21,9 @@ use crate::ir::types::{I32, I64}; use crate::ir::{self, InstBuilder, MemFlags}; use crate::isa::TargetIsa; -#[cfg(any( - feature = "x86", - feature = "arm32", - feature = "arm64", - feature = "riscv" -))] +#[cfg(any(feature = "x86", feature = "riscv"))] use crate::predicates; -#[cfg(any( - feature = "x86", - feature = "arm32", - feature = "arm64", - feature = "riscv" -))] +#[cfg(any(feature = "x86", feature = "riscv"))] use alloc::vec::Vec; use crate::timing; @@ -46,6 +37,7 @@ mod libcall; mod split; mod table; +#[cfg(any(feature = "x86", feature = "riscv"))] use self::call::expand_call; use self::globalvalue::expand_global_value; use self::heap::expand_heap_addr; @@ -213,49 +205,126 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is /// 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) { + 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 func_begin = pos.position(); pos.set_position(func_begin); while let Some(_block) = pos.next_block() { let mut prev_pos = pos.position(); while let Some(inst) = pos.next_inst() { - let expanded = match pos.func.dfg[inst].opcode() { - ir::Opcode::BrIcmp - | ir::Opcode::GlobalValue - | ir::Opcode::HeapAddr - | ir::Opcode::StackLoad - | ir::Opcode::StackStore - | ir::Opcode::TableAddr - | ir::Opcode::Trapnz - | ir::Opcode::Trapz - | ir::Opcode::ResumableTrapnz - | ir::Opcode::BandImm - | ir::Opcode::BorImm - | ir::Opcode::BxorImm - | ir::Opcode::IaddImm - | ir::Opcode::IfcmpImm - | ir::Opcode::ImulImm - | ir::Opcode::IrsubImm - | ir::Opcode::IshlImm - | ir::Opcode::RotlImm - | ir::Opcode::RotrImm - | ir::Opcode::SdivImm - | ir::Opcode::SremImm - | ir::Opcode::SshrImm - | ir::Opcode::UdivImm - | ir::Opcode::UremImm - | ir::Opcode::UshrImm - | ir::Opcode::IcmpImm => expand(inst, &mut pos.func, cfg, isa), - _ => false, + match pos.func.dfg[inst].opcode() { + // control flow + ir::Opcode::BrIcmp => expand_br_icmp(inst, &mut pos.func, cfg, isa), + ir::Opcode::Trapnz | ir::Opcode::Trapz | ir::Opcode::ResumableTrapnz => { + expand_cond_trap(inst, &mut pos.func, cfg, isa); + } + + // memory and constants + ir::Opcode::GlobalValue => expand_global_value(inst, &mut pos.func, cfg, isa), + ir::Opcode::HeapAddr => expand_heap_addr(inst, &mut pos.func, cfg, isa), + ir::Opcode::StackLoad => expand_stack_load(inst, &mut pos.func, cfg, isa), + ir::Opcode::StackStore => expand_stack_store(inst, &mut pos.func, cfg, isa), + ir::Opcode::TableAddr => expand_table_addr(inst, &mut pos.func, cfg, isa), + + // bitops + ir::Opcode::BandImm => expand_imm_op!(pos, inst: band_imm => band), + ir::Opcode::BorImm => expand_imm_op!(pos, inst: bor_imm => bor), + ir::Opcode::BxorImm => expand_imm_op!(pos, inst: bxor_imm => bxor), + ir::Opcode::IaddImm => expand_imm_op!(pos, inst: iadd_imm => iadd), + + // bitshifting + ir::Opcode::IshlImm => expand_imm_op!(pos, inst: ishl_imm => ishl), + ir::Opcode::RotlImm => expand_imm_op!(pos, inst: rotl_imm => rotl), + ir::Opcode::RotrImm => expand_imm_op!(pos, inst: rotr_imm => rotr), + ir::Opcode::SshrImm => expand_imm_op!(pos, inst: sshr_imm => sshr), + ir::Opcode::UshrImm => expand_imm_op!(pos, inst: ushr_imm => ushr), + + // 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. TODO: fix this. - pos.set_position(prev_pos); - } else { - prev_pos = pos.position(); - } + // Legalization implementations require fixpoint loop here. + // TODO: fix this. + pos.set_position(prev_pos); } } }