Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cranelift AArch64: Migrate AMode to ISLE #4832

Merged
merged 2 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024;
impl Into<AMode> for StackAMode {
fn into(self) -> AMode {
match self {
StackAMode::FPOffset(off, ty) => AMode::FPOffset(off, ty),
StackAMode::NominalSPOffset(off, ty) => AMode::NominalSPOffset(off, ty),
StackAMode::SPOffset(off, ty) => AMode::SPOffset(off, ty),
StackAMode::FPOffset(off, ty) => AMode::FPOffset { off, ty },
StackAMode::NominalSPOffset(off, ty) => AMode::NominalSPOffset { off, ty },
StackAMode::SPOffset(off, ty) => AMode::SPOffset { off, ty },
}
}
}
Expand Down Expand Up @@ -462,12 +462,20 @@ impl ABIMachineSpec for AArch64MachineDeps {
}

fn gen_load_base_offset(into_reg: Writable<Reg>, base: Reg, offset: i32, ty: Type) -> Inst {
let mem = AMode::RegOffset(base, offset as i64, ty);
let mem = AMode::RegOffset {
rn: base,
off: offset as i64,
ty,
};
Inst::gen_load(into_reg, mem, ty, MemFlags::trusted())
}

fn gen_store_base_offset(base: Reg, offset: i32, from_reg: Reg, ty: Type) -> Inst {
let mem = AMode::RegOffset(base, offset as i64, ty);
let mem = AMode::RegOffset {
rn: base,
off: offset as i64,
ty,
};
Inst::gen_store(mem, from_reg, ty, MemFlags::trusted())
}

Expand Down Expand Up @@ -676,10 +684,10 @@ impl ABIMachineSpec for AArch64MachineDeps {
// str rd, [sp, #-16]!
insts.push(Inst::Store64 {
rd,
mem: AMode::PreIndexed(
writable_stack_reg(),
SImm9::maybe_from_i64(-clobber_offset_change).unwrap(),
),
mem: AMode::PreIndexed {
rn: writable_stack_reg(),
simm9: SImm9::maybe_from_i64(-clobber_offset_change).unwrap(),
},
flags: MemFlags::trusted(),
});

Expand Down Expand Up @@ -734,10 +742,10 @@ impl ABIMachineSpec for AArch64MachineDeps {

let store_vec_reg = |rd| Inst::FpuStore64 {
rd,
mem: AMode::PreIndexed(
writable_stack_reg(),
SImm9::maybe_from_i64(-clobber_offset_change).unwrap(),
),
mem: AMode::PreIndexed {
rn: writable_stack_reg(),
simm9: SImm9::maybe_from_i64(-clobber_offset_change).unwrap(),
},
flags: MemFlags::trusted(),
};
let iter = clobbered_vec.chunks_exact(2);
Expand Down Expand Up @@ -831,7 +839,10 @@ impl ABIMachineSpec for AArch64MachineDeps {

let load_vec_reg = |rd| Inst::FpuLoad64 {
rd,
mem: AMode::PostIndexed(writable_stack_reg(), SImm9::maybe_from_i64(16).unwrap()),
mem: AMode::PostIndexed {
rn: writable_stack_reg(),
simm9: SImm9::maybe_from_i64(16).unwrap(),
},
flags: MemFlags::trusted(),
};
let load_vec_reg_pair = |rt, rt2| Inst::FpuLoadP64 {
Expand Down Expand Up @@ -893,7 +904,10 @@ impl ABIMachineSpec for AArch64MachineDeps {
// ldr rd, [sp], #16
insts.push(Inst::ULoad64 {
rd,
mem: AMode::PostIndexed(writable_stack_reg(), SImm9::maybe_from_i64(16).unwrap()),
mem: AMode::PostIndexed {
rn: writable_stack_reg(),
simm9: SImm9::maybe_from_i64(16).unwrap(),
},
flags: MemFlags::trusted(),
});
}
Expand Down
150 changes: 136 additions & 14 deletions cranelift/codegen/src/isa/aarch64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,108 @@
(Cls)
))

(type AMode extern (enum))
(type MemLabel extern (enum))
(type SImm9 extern (enum))
(type UImm12Scaled extern (enum))

;; An addressing mode specified for a load/store operation.
(type AMode
(enum
;;
;; Real ARM64 addressing modes:
;;
;; "post-indexed" mode as per AArch64 docs: postincrement reg after
;; address computation.
(PostIndexed
(rn WritableReg)
(simm9 SImm9))

;; "pre-indexed" mode as per AArch64 docs: preincrement reg before
;; address computation.
(PreIndexed
(rn WritableReg)
(simm9 SImm9))

;; N.B.: RegReg, RegScaled, and RegScaledExtended all correspond to
;; what the ISA calls the "register offset" addressing mode. We split
;; out several options here for more ergonomic codegen.
;;
;; Register plus register offset.
(RegReg
(rn Reg)
(rm Reg))

;; Register plus register offset, scaled by type's size.
(RegScaled
(rn Reg)
(rm Reg)
(ty Type))

;; Register plus register offset, scaled by type's size, with index
;; sign- or zero-extended first.
(RegScaledExtended
(rn Reg)
(rm Reg)
(ty Type)
(extendop ExtendOp))

;; Register plus register offset, with index sign- or zero-extended
;; first.
(RegExtended
(rn Reg)
(rm Reg)
(extendop ExtendOp))

;; Unscaled signed 9-bit immediate offset from reg.
(Unscaled
(rn Reg)
(simm9 SImm9))

;; Scaled (by size of a type) unsigned 12-bit immediate offset from reg.
(UnsignedOffset
(rn Reg)
(uimm12 UImm12Scaled))

;; virtual addressing modes that are lowered at emission time:
;;
;; Reference to a "label": e.g., a symbol.
(Label
(label MemLabel))

;; Arbitrary offset from a register. Converted to generation of large
;; offsets with multiple instructions as necessary during code emission.
(RegOffset
(rn Reg)
(off i64)
(ty Type))

;; Offset from the stack pointer.
(SPOffset
(off i64)
(ty Type))

;; Offset from the frame pointer.
(FPOffset
(off i64)
(ty Type))

;; Offset from the "nominal stack pointer", which is where the real SP is
;; just after stack and spill slots are allocated in the function prologue.
;; At emission time, this is converted to `SPOffset` with a fixup added to
;; the offset constant. The fixup is a running value that is tracked as
;; emission iterates through instructions in linear order, and can be
;; adjusted up and down with [Inst::VirtualSPOffsetAdj].
;;
;; The standard ABI is in charge of handling this (by emitting the
;; adjustment meta-instructions). It maintains the invariant that "nominal
;; SP" is where the actual SP is after the function prologue and before
;; clobber pushes. See the diagram in the documentation for
;; [crate::isa::aarch64::abi](the ABI module) for more details.
(NominalSPOffset
(off i64)
(ty Type))
))

(type PairAMode extern (enum))
(type FPUOpRI extern (enum))

Expand Down Expand Up @@ -1470,6 +1571,12 @@
(decl valid_atomic_transaction (Type) Type)
(extern extractor valid_atomic_transaction valid_atomic_transaction)

(decl pure is_zero_simm9 (SImm9) Unit)
(extern constructor is_zero_simm9 is_zero_simm9)

(decl pure is_zero_uimm12 (UImm12Scaled) Unit)
(extern constructor is_zero_uimm12 is_zero_uimm12)

;; Helper to go directly from a `Value`, when it's an `iconst`, to an `Imm12`.
(decl imm12_from_value (Imm12) Value)
(extractor
Expand Down Expand Up @@ -1502,25 +1609,21 @@
(decl cond_br_cond (Cond) CondBrKind)
(extern constructor cond_br_cond cond_br_cond)

;; Lower the address of a load or a store.
(decl amode (Type Value u32) AMode)
;; TODO: Port lower_address() to ISLE.
(extern constructor amode amode)

(decl pair_amode (Value u32) PairAMode)
(extern constructor pair_amode pair_amode)

;; Matches an `AMode` that is just a register.
(decl pure amode_is_reg (AMode) Reg)
;; TODO: Implement in ISLE.
(extern constructor amode_is_reg amode_is_reg)

;; Instruction creation helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Helper for creating the zero register.
(decl zero_reg () Reg)
(extern constructor zero_reg zero_reg)

(decl fp_reg () Reg)
(extern constructor fp_reg fp_reg)

(decl stack_reg () Reg)
(extern constructor stack_reg stack_reg)

(decl writable_zero_reg () WritableReg)
(extern constructor writable_zero_reg writable_zero_reg)

Expand Down Expand Up @@ -2615,14 +2718,33 @@

;; Helper for emitting `MInst.LoadAddr` instructions.
(decl load_addr (AMode) Reg)

(rule (load_addr (AMode.UnsignedOffset r imm))
(if (is_zero_uimm12 imm))
r)

(rule (load_addr (AMode.Unscaled r imm))
(if (is_zero_simm9 imm))
r)

(rule (load_addr (AMode.RegOffset r 0 _)) r)
(rule (load_addr (AMode.FPOffset 0 _)) (fp_reg))
(rule (load_addr (AMode.SPOffset 0 _)) (stack_reg))

(rule (load_addr addr)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.LoadAddr dst addr))))
dst))

(rule (load_addr addr)
(if-let addr_reg (amode_is_reg addr))
addr_reg)
;; Lower the address of a load or a store.
(decl amode (Type Value u32) AMode)
;; TODO: Port lower_address() to ISLE.
(extern constructor amode amode)

(decl sink_load_into_amode (Type Inst) AMode)
(rule (sink_load_into_amode ty x @ (load _ addr offset))
(let ((_ Unit (sink_inst x)))
(amode ty addr offset)))

;; Lower a constant f64.
(decl constant_f64 (u64) Reg)
Expand Down
Loading