diff --git a/cranelift/codegen/meta/src/isa/arm64/mod.rs b/cranelift/codegen/meta/src/isa/arm64/mod.rs index 3440c8af82..5d8bc76fc4 100644 --- a/cranelift/codegen/meta/src/isa/arm64/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm64/mod.rs @@ -54,7 +54,9 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { 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]; diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index 3a33649d4d..33655a26bd 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -54,7 +54,9 @@ pub enum Reloc { X86GOTPCRel4, /// Arm32 call target Arm32Call, - /// Arm64 call target + /// Arm64 call target. Encoded as bottom 26 bits of instruction. This + /// value is sign-extended, multiplied by 4, and added to the PC of + /// the call instruction to form the destination address. Arm64Call, /// RISC-V call target RiscvCall, diff --git a/cranelift/codegen/src/dce.rs b/cranelift/codegen/src/dce.rs index b217534c3e..827ae98ec4 100644 --- a/cranelift/codegen/src/dce.rs +++ b/cranelift/codegen/src/dce.rs @@ -40,6 +40,14 @@ fn is_load_with_defined_trapping(opcode: Opcode, data: &InstructionData) -> bool } } +/// Does the given instruction have any side-effect that would preclude it from being removed when +/// its value is unused? +pub fn has_side_effect(func: &Function, inst: Inst) -> bool { + let data = &func.dfg[inst]; + let opcode = data.opcode(); + trivially_unsafe_for_dce(opcode) || is_load_with_defined_trapping(opcode, data) +} + /// Perform DCE on `func`. pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) { let _tt = timing::dce(); @@ -50,10 +58,7 @@ pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) { let mut pos = FuncCursor::new(func).at_bottom(block); while let Some(inst) = pos.prev_inst() { { - let data = &pos.func.dfg[inst]; - let opcode = data.opcode(); - if trivially_unsafe_for_dce(opcode) - || is_load_with_defined_trapping(opcode, &data) + if has_side_effect(pos.func, inst) || any_inst_results_used(inst, &live, &pos.func.dfg) { for arg in pos.func.dfg.inst_args(inst) { diff --git a/cranelift/codegen/src/ir/immediates.rs b/cranelift/codegen/src/ir/immediates.rs index b1d142bd9e..5104d83f9d 100644 --- a/cranelift/codegen/src/ir/immediates.rs +++ b/cranelift/codegen/src/ir/immediates.rs @@ -57,6 +57,11 @@ impl Imm64 { pub fn wrapping_neg(self) -> Self { Self(self.0.wrapping_neg()) } + + /// Return bits of this immediate. + pub fn bits(&self) -> i64 { + self.0 + } } impl Into for Imm64 { diff --git a/cranelift/codegen/src/legalizer/mod.rs b/cranelift/codegen/src/legalizer/mod.rs index 781767336a..e28cc47d6a 100644 --- a/cranelift/codegen/src/legalizer/mod.rs +++ b/cranelift/codegen/src/legalizer/mod.rs @@ -196,6 +196,55 @@ 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) { + 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::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, + }; + + if expanded { + // Legalization implementations require fixpoint loop + // here. TODO: fix this. + pos.set_position(prev_pos); + } else { + prev_pos = pos.position(); + } + } + } +} + // Include legalization patterns that were generated by `gen_legalizer.rs` from the // `TransformGroup` in `cranelift-codegen/meta/shared/legalize.rs`. //