Convert scalar_to_vector to ISLE (AArch64) (#4401)

* Convert `scalar_to_vector` to ISLE (AArch64)

Converted the exisiting implementation of `scalar_to_vector` for AArch64 to
ISLE.

Copyright (c) 2022 Arm Limited

* Add support for floats and fix FpuExtend

- Added rules to cover `f32 -> f32x4` and `f64 -> f64x2` for
`scalar_to_vector`
- Added tests for `scalar_to_vector` on floats.
- Corrected an invalid instruction emitted by `FpuExtend` on 64-bit
values.

Copyright (c) 2022 Arm Limited
This commit is contained in:
Damian Heaton
2022-07-18 19:11:54 +01:00
committed by GitHub
parent f0337c9c76
commit db7f9ccd2b
10 changed files with 135 additions and 25 deletions

View File

@@ -1637,6 +1637,13 @@
(_ Unit (emit (MInst.Extend dst rn signed from_bits to_bits))))
dst))
;; Helper for emitting `MInst.FpuExtend` instructions.
(decl fpu_extend (Reg ScalarSize) Reg)
(rule (fpu_extend src size)
(let ((dst WritableReg (temp_writable_reg $F32X4))
(_ Unit (emit (MInst.FpuExtend dst src size))))
dst))
;; Helper for emitting `MInst.LoadAcquire` instructions.
(decl load_acquire (Type Reg) Reg)
(rule (load_acquire ty addr)

View File

@@ -1688,7 +1688,7 @@ impl MachInstEmit for Inst {
let rd = allocs.next_writable(rd);
let rn = allocs.next(rn);
sink.put4(enc_fpurr(
0b000_11110_00_1_000000_10000 | (size.ftype() << 13),
0b000_11110_00_1_000000_10000 | (size.ftype() << 12),
rd,
rn,
));

View File

@@ -5528,6 +5528,16 @@ fn test_aarch64_binemit() {
"fmov s31, s0",
));
insns.push((
Inst::FpuExtend {
rd: writable_vreg(31),
rn: vreg(0),
size: ScalarSize::Size64,
},
"1F40601E",
"fmov d31, d0",
));
insns.push((
Inst::FpuRR {
fpu_op: FPUOp1::Abs,

View File

@@ -121,6 +121,20 @@
(rule (lower (has_type $I128 (iconcat lo hi)))
(output (value_regs lo hi)))
;;;; Rules for `scalar_to_vector` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (has_type $F32X4 (scalar_to_vector x)))
(fpu_extend x (ScalarSize.Size32)))
(rule (lower (has_type $F64X2 (scalar_to_vector x)))
(fpu_extend x (ScalarSize.Size64)))
(rule (lower (scalar_to_vector x @ (value_type (ty_int_bool_64 _))))
(mov_to_fpu x (ScalarSize.Size64)))
(rule (lower (scalar_to_vector x @ (value_type (int_bool_fits_in_32 _))))
(mov_to_fpu (put_in_reg_zext32 x) (ScalarSize.Size32)))
;;;; Rules for `iadd_pairwise` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (has_type $I16X8 (iadd_pairwise (swiden_low x) (swiden_high y))))

View File

@@ -816,25 +816,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}
}
Opcode::ScalarToVector => {
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
let input_ty = ctx.input_ty(insn, 0);
if (input_ty == I32 && ty.unwrap() == I32X4)
|| (input_ty == I64 && ty.unwrap() == I64X2)
{
ctx.emit(Inst::MovToFpu {
rd,
rn,
size: ScalarSize::from_ty(input_ty),
});
} else {
return Err(CodegenError::Unsupported(format!(
"ScalarToVector: unsupported types {:?} -> {:?}",
input_ty, ty
)));
}
}
Opcode::ScalarToVector => implemented_in_isle(ctx),
Opcode::VallTrue if ctx.input_ty(insn, 0).lane_bits() == 64 => {
let input_ty = ctx.input_ty(insn, 0);

View File

@@ -299,6 +299,14 @@ macro_rules! isle_prelude_methods {
}
}
#[inline]
fn int_bool_fits_in_32(&mut self, ty: Type) -> Option<Type> {
match ty {
I8 | I16 | I32 | B8 | B16 | B32 => Some(ty),
_ => None,
}
}
#[inline]
fn ty_int_bool_64(&mut self, ty: Type) -> Option<Type> {
match ty {

View File

@@ -313,6 +313,10 @@
(decl ty_8_or_16 (Type) Type)
(extern extractor ty_8_or_16 ty_8_or_16)
;; An extractor that matches int and bool types that fit in 32 bits.
(decl int_bool_fits_in_32 (Type) Type)
(extern extractor int_bool_fits_in_32 int_bool_fits_in_32)
;; An extractor that matches I64 or B64.
(decl ty_int_bool_64 (Type) Type)
(extern extractor ty_int_bool_64 ty_int_bool_64)