Skip to main content

cranelift_codegen/isa/aarch64/
lower.rs

1//! Lowering rules for AArch64.
2//!
3//! TODO: opportunities for better code generation:
4//!
5//! - Smarter use of addressing modes. Recognize a+SCALE*b patterns. Recognize
6//!   pre/post-index opportunities.
7//!
8//! - Floating-point immediates (FIMM instruction).
9
10use crate::ir::Inst as IRInst;
11use crate::ir::condcodes::{FloatCC, IntCC};
12use crate::ir::{Opcode, Value};
13use crate::isa::aarch64::AArch64Backend;
14use crate::isa::aarch64::inst::*;
15use crate::machinst::*;
16
17pub mod isle;
18
19//============================================================================
20// Lowering: convert instruction inputs to forms that we can use.
21
22fn get_as_extended_value(ctx: &mut Lower<Inst>, val: Value) -> Option<(Value, ExtendOp)> {
23    let inputs = ctx.get_value_as_source_or_const(val);
24    let (insn, n) = inputs.inst.as_inst()?;
25    if n != 0 {
26        return None;
27    }
28    let op = ctx.data(insn).opcode();
29    let out_ty = ctx.output_ty(insn, 0);
30    let out_bits = ty_bits(out_ty);
31
32    // Is this a zero-extend or sign-extend and can we handle that with a register-mode operator?
33    if op == Opcode::Uextend || op == Opcode::Sextend {
34        let sign_extend = op == Opcode::Sextend;
35        let inner_ty = ctx.input_ty(insn, 0);
36        let inner_bits = ty_bits(inner_ty);
37        assert!(inner_bits < out_bits);
38        let extendop = match (sign_extend, inner_bits) {
39            (true, 8) => ExtendOp::SXTB,
40            (false, 8) => ExtendOp::UXTB,
41            (true, 16) => ExtendOp::SXTH,
42            (false, 16) => ExtendOp::UXTH,
43            (true, 32) => ExtendOp::SXTW,
44            (false, 32) => ExtendOp::UXTW,
45            _ => unreachable!(),
46        };
47        return Some((ctx.input_as_value(insn, 0), extendop));
48    }
49
50    None
51}
52
53pub(crate) fn lower_condcode(cc: IntCC) -> Cond {
54    match cc {
55        IntCC::Equal => Cond::Eq,
56        IntCC::NotEqual => Cond::Ne,
57        IntCC::SignedGreaterThanOrEqual => Cond::Ge,
58        IntCC::SignedGreaterThan => Cond::Gt,
59        IntCC::SignedLessThanOrEqual => Cond::Le,
60        IntCC::SignedLessThan => Cond::Lt,
61        IntCC::UnsignedGreaterThanOrEqual => Cond::Hs,
62        IntCC::UnsignedGreaterThan => Cond::Hi,
63        IntCC::UnsignedLessThanOrEqual => Cond::Ls,
64        IntCC::UnsignedLessThan => Cond::Lo,
65    }
66}
67
68//=============================================================================
69// Lowering-backend trait implementation.
70
71impl LowerBackend for AArch64Backend {
72    type MInst = Inst;
73
74    fn lower(&self, ctx: &mut Lower<Inst>, ir_inst: IRInst) -> Option<InstOutput> {
75        isle::lower(ctx, self, ir_inst)
76    }
77
78    fn lower_branch(
79        &self,
80        ctx: &mut Lower<Inst>,
81        ir_inst: IRInst,
82        targets: &[MachLabel],
83    ) -> Option<()> {
84        isle::lower_branch(ctx, self, ir_inst, targets)
85    }
86
87    fn maybe_pinned_reg(&self) -> Option<Reg> {
88        Some(regs::pinned_reg())
89    }
90}