Path: blob/main/cranelift/codegen/src/isa/aarch64/lower.rs
1693 views
//! Lowering rules for AArch64.1//!2//! TODO: opportunities for better code generation:3//!4//! - Smarter use of addressing modes. Recognize a+SCALE*b patterns. Recognize5//! pre/post-index opportunities.6//!7//! - Floating-point immediates (FIMM instruction).89use crate::ir::Inst as IRInst;10use crate::ir::condcodes::{FloatCC, IntCC};11use crate::ir::pcc::{FactContext, PccResult};12use crate::ir::{Opcode, Value};13use crate::isa::aarch64::AArch64Backend;14use crate::isa::aarch64::inst::*;15use crate::isa::aarch64::pcc;16use crate::machinst::lower::*;17use crate::machinst::*;1819pub mod isle;2021//============================================================================22// Lowering: convert instruction inputs to forms that we can use.2324fn get_as_extended_value(ctx: &mut Lower<Inst>, val: Value) -> Option<(Value, ExtendOp)> {25let inputs = ctx.get_value_as_source_or_const(val);26let (insn, n) = inputs.inst.as_inst()?;27if n != 0 {28return None;29}30let op = ctx.data(insn).opcode();31let out_ty = ctx.output_ty(insn, 0);32let out_bits = ty_bits(out_ty);3334// Is this a zero-extend or sign-extend and can we handle that with a register-mode operator?35if op == Opcode::Uextend || op == Opcode::Sextend {36let sign_extend = op == Opcode::Sextend;37let inner_ty = ctx.input_ty(insn, 0);38let inner_bits = ty_bits(inner_ty);39assert!(inner_bits < out_bits);40let extendop = match (sign_extend, inner_bits) {41(true, 8) => ExtendOp::SXTB,42(false, 8) => ExtendOp::UXTB,43(true, 16) => ExtendOp::SXTH,44(false, 16) => ExtendOp::UXTH,45(true, 32) => ExtendOp::SXTW,46(false, 32) => ExtendOp::UXTW,47_ => unreachable!(),48};49return Some((ctx.input_as_value(insn, 0), extendop));50}5152None53}5455pub(crate) fn lower_condcode(cc: IntCC) -> Cond {56match cc {57IntCC::Equal => Cond::Eq,58IntCC::NotEqual => Cond::Ne,59IntCC::SignedGreaterThanOrEqual => Cond::Ge,60IntCC::SignedGreaterThan => Cond::Gt,61IntCC::SignedLessThanOrEqual => Cond::Le,62IntCC::SignedLessThan => Cond::Lt,63IntCC::UnsignedGreaterThanOrEqual => Cond::Hs,64IntCC::UnsignedGreaterThan => Cond::Hi,65IntCC::UnsignedLessThanOrEqual => Cond::Ls,66IntCC::UnsignedLessThan => Cond::Lo,67}68}6970pub(crate) fn lower_fp_condcode(cc: FloatCC) -> Cond {71// Refer to `codegen/shared/src/condcodes.rs` and to the `FCMP` AArch64 docs.72// The FCMP instruction sets:73// NZCV74// - PCSR.NZCV = 0011 on UN (unordered),75// 0110 on EQ,76// 1000 on LT,77// 0010 on GT.78match cc {79// EQ | LT | GT. Vc => V clear.80FloatCC::Ordered => Cond::Vc,81// UN. Vs => V set.82FloatCC::Unordered => Cond::Vs,83// EQ. Eq => Z set.84FloatCC::Equal => Cond::Eq,85// UN | LT | GT. Ne => Z clear.86FloatCC::NotEqual => Cond::Ne,87// LT | GT.88FloatCC::OrderedNotEqual => unimplemented!(),89// UN | EQ90FloatCC::UnorderedOrEqual => unimplemented!(),91// LT. Mi => N set.92FloatCC::LessThan => Cond::Mi,93// LT | EQ. Ls => C clear or Z set.94FloatCC::LessThanOrEqual => Cond::Ls,95// GT. Gt => Z clear, N = V.96FloatCC::GreaterThan => Cond::Gt,97// GT | EQ. Ge => N = V.98FloatCC::GreaterThanOrEqual => Cond::Ge,99// UN | LT100FloatCC::UnorderedOrLessThan => unimplemented!(),101// UN | LT | EQ102FloatCC::UnorderedOrLessThanOrEqual => unimplemented!(),103// UN | GT104FloatCC::UnorderedOrGreaterThan => unimplemented!(),105// UN | GT | EQ106FloatCC::UnorderedOrGreaterThanOrEqual => unimplemented!(),107}108}109110//=============================================================================111// Lowering-backend trait implementation.112113impl LowerBackend for AArch64Backend {114type MInst = Inst;115116fn lower(&self, ctx: &mut Lower<Inst>, ir_inst: IRInst) -> Option<InstOutput> {117isle::lower(ctx, self, ir_inst)118}119120fn lower_branch(121&self,122ctx: &mut Lower<Inst>,123ir_inst: IRInst,124targets: &[MachLabel],125) -> Option<()> {126isle::lower_branch(ctx, self, ir_inst, targets)127}128129fn maybe_pinned_reg(&self) -> Option<Reg> {130Some(regs::pinned_reg())131}132133fn check_fact(134&self,135ctx: &FactContext<'_>,136vcode: &mut VCode<Self::MInst>,137inst: InsnIndex,138state: &mut pcc::FactFlowState,139) -> PccResult<()> {140pcc::check(ctx, vcode, inst, state)141}142143type FactFlowState = pcc::FactFlowState;144}145146147