Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/isa/aarch64/lower.rs
1693 views
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
10
use crate::ir::Inst as IRInst;
11
use crate::ir::condcodes::{FloatCC, IntCC};
12
use crate::ir::pcc::{FactContext, PccResult};
13
use crate::ir::{Opcode, Value};
14
use crate::isa::aarch64::AArch64Backend;
15
use crate::isa::aarch64::inst::*;
16
use crate::isa::aarch64::pcc;
17
use crate::machinst::lower::*;
18
use crate::machinst::*;
19
20
pub mod isle;
21
22
//============================================================================
23
// Lowering: convert instruction inputs to forms that we can use.
24
25
fn get_as_extended_value(ctx: &mut Lower<Inst>, val: Value) -> Option<(Value, ExtendOp)> {
26
let inputs = ctx.get_value_as_source_or_const(val);
27
let (insn, n) = inputs.inst.as_inst()?;
28
if n != 0 {
29
return None;
30
}
31
let op = ctx.data(insn).opcode();
32
let out_ty = ctx.output_ty(insn, 0);
33
let out_bits = ty_bits(out_ty);
34
35
// Is this a zero-extend or sign-extend and can we handle that with a register-mode operator?
36
if op == Opcode::Uextend || op == Opcode::Sextend {
37
let sign_extend = op == Opcode::Sextend;
38
let inner_ty = ctx.input_ty(insn, 0);
39
let inner_bits = ty_bits(inner_ty);
40
assert!(inner_bits < out_bits);
41
let extendop = match (sign_extend, inner_bits) {
42
(true, 8) => ExtendOp::SXTB,
43
(false, 8) => ExtendOp::UXTB,
44
(true, 16) => ExtendOp::SXTH,
45
(false, 16) => ExtendOp::UXTH,
46
(true, 32) => ExtendOp::SXTW,
47
(false, 32) => ExtendOp::UXTW,
48
_ => unreachable!(),
49
};
50
return Some((ctx.input_as_value(insn, 0), extendop));
51
}
52
53
None
54
}
55
56
pub(crate) fn lower_condcode(cc: IntCC) -> Cond {
57
match cc {
58
IntCC::Equal => Cond::Eq,
59
IntCC::NotEqual => Cond::Ne,
60
IntCC::SignedGreaterThanOrEqual => Cond::Ge,
61
IntCC::SignedGreaterThan => Cond::Gt,
62
IntCC::SignedLessThanOrEqual => Cond::Le,
63
IntCC::SignedLessThan => Cond::Lt,
64
IntCC::UnsignedGreaterThanOrEqual => Cond::Hs,
65
IntCC::UnsignedGreaterThan => Cond::Hi,
66
IntCC::UnsignedLessThanOrEqual => Cond::Ls,
67
IntCC::UnsignedLessThan => Cond::Lo,
68
}
69
}
70
71
pub(crate) fn lower_fp_condcode(cc: FloatCC) -> Cond {
72
// Refer to `codegen/shared/src/condcodes.rs` and to the `FCMP` AArch64 docs.
73
// The FCMP instruction sets:
74
// NZCV
75
// - PCSR.NZCV = 0011 on UN (unordered),
76
// 0110 on EQ,
77
// 1000 on LT,
78
// 0010 on GT.
79
match cc {
80
// EQ | LT | GT. Vc => V clear.
81
FloatCC::Ordered => Cond::Vc,
82
// UN. Vs => V set.
83
FloatCC::Unordered => Cond::Vs,
84
// EQ. Eq => Z set.
85
FloatCC::Equal => Cond::Eq,
86
// UN | LT | GT. Ne => Z clear.
87
FloatCC::NotEqual => Cond::Ne,
88
// LT | GT.
89
FloatCC::OrderedNotEqual => unimplemented!(),
90
// UN | EQ
91
FloatCC::UnorderedOrEqual => unimplemented!(),
92
// LT. Mi => N set.
93
FloatCC::LessThan => Cond::Mi,
94
// LT | EQ. Ls => C clear or Z set.
95
FloatCC::LessThanOrEqual => Cond::Ls,
96
// GT. Gt => Z clear, N = V.
97
FloatCC::GreaterThan => Cond::Gt,
98
// GT | EQ. Ge => N = V.
99
FloatCC::GreaterThanOrEqual => Cond::Ge,
100
// UN | LT
101
FloatCC::UnorderedOrLessThan => unimplemented!(),
102
// UN | LT | EQ
103
FloatCC::UnorderedOrLessThanOrEqual => unimplemented!(),
104
// UN | GT
105
FloatCC::UnorderedOrGreaterThan => unimplemented!(),
106
// UN | GT | EQ
107
FloatCC::UnorderedOrGreaterThanOrEqual => unimplemented!(),
108
}
109
}
110
111
//=============================================================================
112
// Lowering-backend trait implementation.
113
114
impl LowerBackend for AArch64Backend {
115
type MInst = Inst;
116
117
fn lower(&self, ctx: &mut Lower<Inst>, ir_inst: IRInst) -> Option<InstOutput> {
118
isle::lower(ctx, self, ir_inst)
119
}
120
121
fn lower_branch(
122
&self,
123
ctx: &mut Lower<Inst>,
124
ir_inst: IRInst,
125
targets: &[MachLabel],
126
) -> Option<()> {
127
isle::lower_branch(ctx, self, ir_inst, targets)
128
}
129
130
fn maybe_pinned_reg(&self) -> Option<Reg> {
131
Some(regs::pinned_reg())
132
}
133
134
fn check_fact(
135
&self,
136
ctx: &FactContext<'_>,
137
vcode: &mut VCode<Self::MInst>,
138
inst: InsnIndex,
139
state: &mut pcc::FactFlowState,
140
) -> PccResult<()> {
141
pcc::check(ctx, vcode, inst, state)
142
}
143
144
type FactFlowState = pcc::FactFlowState;
145
}
146
147