Skip to content

Commit da1fb30

Browse files
author
Damian Heaton
authored
Port vconst to ISLE (AArch64) (#4750)
* Port `vconst` to ISLE (AArch64) Ported the existing implementation of `vconst` to ISLE for AArch64, and added support for 64-bit vector constants. Also introduced 64-bit `vconst` support to the interpreter. Copyright (c) 2022 Arm Limited * Replace if-chains with match statements Copyright (c) 2022 Arm Limited
1 parent 418dbc1 commit da1fb30

10 files changed

Lines changed: 97 additions & 21 deletions

File tree

cranelift/codegen/src/isa/aarch64/inst.isle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,11 @@
24352435
(if-let addr_reg (amode_is_reg addr))
24362436
addr_reg)
24372437

2438+
;; Lower a constant f64.
2439+
(decl constant_f64 (u64) Reg)
2440+
;; TODO: Port lower_constant_f64() to ISLE.
2441+
(extern constructor constant_f64 constant_f64)
2442+
24382443
;; Lower a constant f128.
24392444
(decl constant_f128 (u128) Reg)
24402445
;; TODO: Port lower_constant_f128() to ISLE.

cranelift/codegen/src/isa/aarch64/lower.isle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,15 @@
16281628
(rule (lower (resumable_trap trap_code))
16291629
(side_effect (udf trap_code)))
16301630

1631+
;;;; Rules for `vconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1632+
1633+
(rule (lower (has_type (ty_vec128 _) (vconst (u128_from_constant x))))
1634+
(constant_f128 x))
1635+
1636+
(rule (lower (has_type ty (vconst (u64_from_constant x))))
1637+
(if (ty_vec64 ty))
1638+
(constant_f64 x))
1639+
16311640
;;;; Rules for `splat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16321641

16331642
(rule (lower (has_type ty (splat x @ (value_type in_ty))))

cranelift/codegen/src/isa/aarch64/lower.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//! - Floating-point immediates (FIMM instruction).
99
1010
use super::lower_inst;
11-
use crate::data_value::DataValue;
1211
use crate::ir::condcodes::{FloatCC, IntCC};
1312
use crate::ir::types::*;
1413
use crate::ir::Inst as IRInst;
@@ -94,13 +93,6 @@ pub(crate) fn input_to_shiftimm(
9493
input_to_const(ctx, input).and_then(ShiftOpShiftImm::maybe_from_shift)
9594
}
9695

97-
pub(crate) fn const_param_to_u128(ctx: &mut Lower<Inst>, inst: IRInst) -> Option<u128> {
98-
match ctx.get_immediate(inst) {
99-
Some(DataValue::V128(bytes)) => Some(u128::from_le_bytes(bytes)),
100-
_ => None,
101-
}
102-
}
103-
10496
/// How to handle narrow values loaded into registers; see note on `narrow_mode`
10597
/// parameter to `put_input_in_*` below.
10698
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

cranelift/codegen/src/isa/aarch64/lower/isle.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ pub mod generated_code;
55

66
// Types that the generated ISLE code uses via `use super::*`.
77
use super::{
8-
insn_inputs, lower_constant_f128, writable_zero_reg, zero_reg, AMode, ASIMDFPModImm,
9-
ASIMDMovModImm, BranchTarget, CallIndInfo, CallInfo, Cond, CondBrKind, ExtendOp, FPUOpRI,
10-
FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, JTSequenceInfo, MachLabel,
8+
insn_inputs, lower_constant_f128, lower_constant_f64, writable_zero_reg, zero_reg, AMode,
9+
ASIMDFPModImm, ASIMDMovModImm, BranchTarget, CallIndInfo, CallInfo, Cond, CondBrKind, ExtendOp,
10+
FPUOpRI, FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, JTSequenceInfo, MachLabel,
1111
MoveWideConst, MoveWideOp, NarrowValueMode, Opcode, OperandSize, PairAMode, Reg, ScalarSize,
1212
ShiftOpAndAmt, UImm5, VecMisc2, VectorSize, NZCV,
1313
};
@@ -484,6 +484,14 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
484484
address.is_reg()
485485
}
486486

487+
fn constant_f64(&mut self, value: u64) -> Reg {
488+
let rd = self.temp_writable_reg(I8X16);
489+
490+
lower_constant_f64(self.lower_ctx, rd, f64::from_bits(value));
491+
492+
rd.to_reg()
493+
}
494+
487495
fn constant_f128(&mut self, value: u128) -> Reg {
488496
let rd = self.temp_writable_reg(I8X16);
489497

cranelift/codegen/src/isa/aarch64/lower_inst.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,11 +644,7 @@ pub(crate) fn lower_insn_to_regs(
644644
panic!("Branch opcode reached non-branch lowering logic!");
645645
}
646646

647-
Opcode::Vconst => {
648-
let value = const_param_to_u128(ctx, insn).expect("Invalid immediate bytes");
649-
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
650-
lower_constant_f128(ctx, rd, value);
651-
}
647+
Opcode::Vconst => implemented_in_isle(ctx),
652648

653649
Opcode::RawBitcast => {
654650
let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);

cranelift/codegen/src/machinst/isle.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,12 @@ macro_rules! isle_prelude_methods {
683683
Some(u128::from_le_bytes(bytes.try_into().ok()?))
684684
}
685685

686+
#[inline]
687+
fn u64_from_constant(&mut self, constant: Constant) -> Option<u64> {
688+
let bytes = self.lower_ctx.get_constant_data(constant).as_slice();
689+
Some(u64::from_le_bytes(bytes.try_into().ok()?))
690+
}
691+
686692
#[inline]
687693
fn u128_from_constant(&mut self, constant: Constant) -> Option<u128> {
688694
let bytes = self.lower_ctx.get_constant_data(constant).as_slice();

cranelift/codegen/src/machinst/lower.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,15 +1387,23 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
13871387
let inst_data = self.data(ir_inst);
13881388
match inst_data {
13891389
InstructionData::Shuffle { imm, .. } => {
1390-
let buffer = self.f.dfg.immediates.get(imm.clone()).unwrap().as_slice();
1391-
let value = DataValue::V128(buffer.try_into().expect("a 16-byte data buffer"));
1390+
let mask = self.f.dfg.immediates.get(imm.clone()).unwrap().as_slice();
1391+
let value = match mask.len() {
1392+
16 => DataValue::V128(mask.try_into().expect("a 16-byte vector mask")),
1393+
8 => DataValue::V64(mask.try_into().expect("an 8-byte vector mask")),
1394+
length => panic!("unexpected Shuffle mask length {}", length),
1395+
};
13921396
Some(value)
13931397
}
13941398
InstructionData::UnaryConst {
13951399
constant_handle, ..
13961400
} => {
13971401
let buffer = self.f.dfg.constants.get(constant_handle.clone()).as_slice();
1398-
let value = DataValue::V128(buffer.try_into().expect("a 16-byte data buffer"));
1402+
let value = match buffer.len() {
1403+
16 => DataValue::V128(buffer.try_into().expect("a 16-byte data buffer")),
1404+
8 => DataValue::V64(buffer.try_into().expect("an 8-byte data buffer")),
1405+
length => panic!("unexpected UnaryConst buffer length {}", length),
1406+
};
13991407
Some(value)
14001408
}
14011409
_ => inst_data.imm_value(),

cranelift/codegen/src/prelude.isle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,11 @@
799799
(decl u128_from_constant (u128) Constant)
800800
(extern extractor u128_from_constant u128_from_constant)
801801

802+
;; Accessor for `Constant` as u64.
803+
804+
(decl u64_from_constant (u64) Constant)
805+
(extern extractor u64_from_constant u64_from_constant)
806+
802807

803808
;;;; Helpers for tail recursion loops ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
804809

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
test interpret
2+
test run
3+
target aarch64
4+
; x86_64 and s390x do not support 64-bit vectors.
5+
6+
function %vconst_zeroes() -> i8x8 {
7+
block0:
8+
v0 = vconst.i8x8 0x00
9+
return v0
10+
}
11+
; run: %vconst_zeroes() == [0 0 0 0 0 0 0 0]
12+
13+
function %vconst_ones() -> i8x8 {
14+
block0:
15+
v0 = vconst.i8x8 0xffffffffffffffff
16+
return v0
17+
}
18+
; run: %vconst_ones() == [255 255 255 255 255 255 255 255]
19+
20+
function %vconst_i8x8() -> i8x8 {
21+
block0:
22+
v0 = vconst.i8x8 [0 31 63 95 127 159 191 255]
23+
return v0
24+
}
25+
; run: %vconst_i8x8() == [0 31 63 95 127 159 191 255]
26+
27+
function %vconst_i16x4() -> i16x4 {
28+
block0:
29+
v0 = vconst.i16x4 [0 255 32767 65535]
30+
return v0
31+
}
32+
; run: %vconst_i16x4() == [0 255 32767 65535]
33+
34+
function %vconst_i32x2() -> i32x2 {
35+
block0:
36+
v0 = vconst.i32x2 [0 4294967295]
37+
return v0
38+
}
39+
; run: %vconst_i32x2() == [0 4294967295]

cranelift/interpreter/src/step.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ where
7575
.constants
7676
.get(constant_handle.clone())
7777
.as_slice();
78-
DataValue::V128(buffer.try_into().expect("a 16-byte data buffer"))
78+
match ctrl_ty.bytes() {
79+
16 => DataValue::V128(buffer.try_into().expect("a 16-byte data buffer")),
80+
8 => DataValue::V64(buffer.try_into().expect("an 8-byte data buffer")),
81+
length => panic!("unexpected UnaryConst buffer length {}", length),
82+
}
7983
}
8084
InstructionData::Shuffle { imm, .. } => {
8185
let mask = state
@@ -85,7 +89,11 @@ where
8589
.get(imm)
8690
.unwrap()
8791
.as_slice();
88-
DataValue::V128(mask.try_into().expect("a 16-byte vector mask"))
92+
match ctrl_ty.bytes() {
93+
16 => DataValue::V128(mask.try_into().expect("a 16-byte vector mask")),
94+
8 => DataValue::V64(mask.try_into().expect("an 8-byte vector mask")),
95+
length => panic!("unexpected Shuffle mask length {}", length),
96+
}
8997
}
9098
_ => inst.imm_value().unwrap(),
9199
})

0 commit comments

Comments
 (0)