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:
@@ -1567,6 +1567,27 @@
|
|||||||
(MInst.AluRRR (ALUOp.SubS) (operand_size ty) dst src1 src2)
|
(MInst.AluRRR (ALUOp.SubS) (operand_size ty) dst src1 src2)
|
||||||
dst)))
|
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)
|
(decl cmp_imm (OperandSize Reg Imm12) ProducesFlags)
|
||||||
(rule (cmp_imm size src1 src2)
|
(rule (cmp_imm size src1 src2)
|
||||||
(ProducesFlags.ProducesFlagsSideEffect
|
(ProducesFlags.ProducesFlagsSideEffect
|
||||||
|
|||||||
@@ -1699,3 +1699,29 @@
|
|||||||
(let ((low_half Reg (uqxtn x (lane_size ty)))
|
(let ((low_half Reg (uqxtn x (lane_size ty)))
|
||||||
(result Reg (uqxtn2 low_half y (lane_size ty))))
|
(result Reg (uqxtn2 low_half y (lane_size ty))))
|
||||||
result))
|
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)))
|
||||||
|
|||||||
@@ -254,9 +254,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
|
|
||||||
Opcode::AtomicStore => implemented_in_isle(ctx),
|
Opcode::AtomicStore => implemented_in_isle(ctx),
|
||||||
|
|
||||||
Opcode::Fence => {
|
Opcode::Fence => implemented_in_isle(ctx),
|
||||||
ctx.emit(Inst::Fence {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Opcode::StackLoad
|
Opcode::StackLoad
|
||||||
| Opcode::StackStore
|
| Opcode::StackStore
|
||||||
@@ -399,34 +397,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
materialize_bool_result(ctx, insn, rd, cond);
|
materialize_bool_result(ctx, insn, rd, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::IsNull | Opcode::IsInvalid => {
|
Opcode::IsNull | Opcode::IsInvalid => implemented_in_isle(ctx),
|
||||||
// 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::Copy => {
|
Opcode::Copy => {
|
||||||
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
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 => {
|
Opcode::Debugtrap => implemented_in_isle(ctx),
|
||||||
ctx.emit(Inst::Brk);
|
|
||||||
}
|
|
||||||
|
|
||||||
Opcode::Trap | Opcode::ResumableTrap => implemented_in_isle(ctx),
|
Opcode::Trap | Opcode::ResumableTrap => implemented_in_isle(ctx),
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user