Skip to content

Commit

Permalink
Port Fence, IsNull/IsInvalid & Debugtrap to ISLE (AArch64) (b…
Browse files Browse the repository at this point in the history
…ytecodealliance#4548)

Ported the existing implementation of the following Opcodes for AArch64
to ISLE:
- `Fence`
- `IsNull`
- `IsInvalid`
- `Debugtrap`

Copyright (c) 2022 Arm Limited
  • Loading branch information
dheaton-arm authored Jul 28, 2022
1 parent 29d4edc commit 5e3bb58
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 34 deletions.
21 changes: 21 additions & 0 deletions cranelift/codegen/src/isa/aarch64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,27 @@
(MInst.AluRRR (ALUOp.SubS) (operand_size ty) dst src1 src2)
dst)))

;; Helper for materializing a boolean value into a register from
;; flags.
(decl materialize_bool_result (u8 Cond) ConsumesFlags)
(rule (materialize_bool_result 1 cond)
(let ((dst WritableReg (temp_writable_reg $I64)))
(ConsumesFlags.ConsumesFlagsReturnsReg
(MInst.CSet dst cond)
dst)))

(rule -1 (materialize_bool_result _ty_bits cond)
(let ((dst WritableReg (temp_writable_reg $I64)))
(ConsumesFlags.ConsumesFlagsReturnsReg
(MInst.CSetm dst cond)
dst)))

(decl cmn_imm (OperandSize Reg Imm12) ProducesFlags)
(rule (cmn_imm size src1 src2)
(ProducesFlags.ProducesFlagsSideEffect
(MInst.AluRRImm12 (ALUOp.AddS) size (writable_zero_reg)
src1 src2)))

(decl cmp_imm (OperandSize Reg Imm12) ProducesFlags)
(rule (cmp_imm size src1 src2)
(ProducesFlags.ProducesFlagsSideEffect
Expand Down
26 changes: 26 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1699,3 +1699,29 @@
(let ((low_half Reg (uqxtn x (lane_size ty)))
(result Reg (uqxtn2 low_half y (lane_size ty))))
result))

;;;; Rules for `Fence` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (fence))
(let ((_ Unit (emit (MInst.Fence))))
(output_none)))

;;;; Rules for `IsNull` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type out_ty (is_null x @ (value_type ty))))
(with_flags (cmp_imm (operand_size ty) x (u8_into_imm12 0))
(materialize_bool_result
(ty_bits out_ty) (Cond.Eq))))

;;;; Rules for `IsInvalid` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type out_ty (is_invalid x @ (value_type ty))))
(with_flags (cmn_imm (operand_size ty) x (u8_into_imm12 1))
(materialize_bool_result
(ty_bits out_ty) (Cond.Eq))))

;;;; Rules for `Debugtrap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (debugtrap))
(let ((_ Unit (emit (MInst.Brk))))
(output_none)))
37 changes: 3 additions & 34 deletions cranelift/codegen/src/isa/aarch64/lower_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(

Opcode::AtomicStore => implemented_in_isle(ctx),

Opcode::Fence => {
ctx.emit(Inst::Fence {});
}
Opcode::Fence => implemented_in_isle(ctx),

Opcode::StackLoad
| Opcode::StackStore
Expand Down Expand Up @@ -399,34 +397,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
materialize_bool_result(ctx, insn, rd, cond);
}

Opcode::IsNull | Opcode::IsInvalid => {
// Null references are represented by the constant value 0; invalid references are
// represented by the constant value -1. See `define_reftypes()` in
// `meta/src/isa/x86/encodings.rs` to confirm.
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let ty = ctx.input_ty(insn, 0);
let (alu_op, const_value) = match op {
Opcode::IsNull => {
// cmp rn, #0
(ALUOp::SubS, 0)
}
Opcode::IsInvalid => {
// cmn rn, #1
(ALUOp::AddS, 1)
}
_ => unreachable!(),
};
let const_value = ResultRSEImm12::Imm12(Imm12::maybe_from_u64(const_value).unwrap());
ctx.emit(alu_inst_imm12(
alu_op,
ty,
writable_zero_reg(),
rn,
const_value,
));
materialize_bool_result(ctx, insn, rd, Cond::Eq);
}
Opcode::IsNull | Opcode::IsInvalid => implemented_in_isle(ctx),

Opcode::Copy => {
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
Expand Down Expand Up @@ -546,9 +517,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}
}

Opcode::Debugtrap => {
ctx.emit(Inst::Brk);
}
Opcode::Debugtrap => implemented_in_isle(ctx),

Opcode::Trap | Opcode::ResumableTrap => implemented_in_isle(ctx),

Expand Down
42 changes: 42 additions & 0 deletions cranelift/filetests/filetests/runtests/ref64-invalid-null.clif
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
; Tests for platforms with 64-bit references.
test run
target aarch64
target x86_64
target s390x

function %is_null_true_r64() -> b1 {
block0:
v0 = null.r64
v1 = is_null v0
return v1
}
; run: %is_null_true_r64() == true

function %is_null_r64(i64) -> b1 {
block0(v0: i64):
v1 = raw_bitcast.r64 v0
v2 = is_null v1
return v2
}
; run: %is_null_r64(256347) == false
; run: %is_null_r64(-1) == false
; run: %is_null_r64(0) == true

function %is_invalid_r64(i64) -> b1 {
block0(v0: i64):
v1 = raw_bitcast.r64 v0
v2 = is_invalid v1
return v2
}
; run: %is_invalid_r64(0xffffffffffffffff) == true
; run: %is_invalid_r64(-1) == true
; run: %is_invalid_r64(256347) == false
; run: %is_invalid_r64(0) == false

function %is_invalid_null_r64() -> b1 {
block0:
v0 = null.r64
v1 = is_invalid v0
return v1
}
; run: %is_invalid_null_r64() == false

0 comments on commit 5e3bb58

Please sign in to comment.