Port Fence, IsNull/IsInvalid & Debugtrap to ISLE (AArch64) (#4548)

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

Copyright (c) 2022 Arm Limited
This commit is contained in:
Damian Heaton
2022-07-28 23:36:13 +01:00
committed by GitHub
parent 29d4edc76b
commit 5e3bb588a8
4 changed files with 92 additions and 34 deletions

View File

@@ -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

View File

@@ -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)))

View File

@@ -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
@@ -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();
@@ -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),

View File

@@ -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