Skip to content

Commit 12a31c8

Browse files
authored
Merge pull request #2021 from akirilov-arm/VectorSize
AArch64: Introduce an enum to specify vector instruction operand sizes
2 parents 806d197 + 95b0b05 commit 12a31c8

File tree

7 files changed

+374
-388
lines changed

7 files changed

+374
-388
lines changed

cranelift/codegen/src/isa/aarch64/inst/args.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Some variants are never constructed, but we still want them as options in the future.
44
#![allow(dead_code)]
55

6+
use crate::ir::types::{F32X2, F32X4, F64X2, I16X4, I16X8, I32X2, I32X4, I64X2, I8X16, I8X8};
67
use crate::ir::Type;
78
use crate::isa::aarch64::inst::*;
89
use crate::isa::aarch64::lower::ty_bits;
@@ -587,3 +588,55 @@ impl ScalarSize {
587588
}
588589
}
589590
}
591+
592+
/// Type used to communicate the size of a vector operand.
593+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
594+
pub enum VectorSize {
595+
Size8x8,
596+
Size8x16,
597+
Size16x4,
598+
Size16x8,
599+
Size32x2,
600+
Size32x4,
601+
Size64x2,
602+
}
603+
604+
impl VectorSize {
605+
/// Convert from a type into a vector operand size.
606+
pub fn from_ty(ty: Type) -> VectorSize {
607+
match ty {
608+
F32X2 => VectorSize::Size32x2,
609+
F32X4 => VectorSize::Size32x4,
610+
F64X2 => VectorSize::Size64x2,
611+
I8X8 => VectorSize::Size8x8,
612+
I8X16 => VectorSize::Size8x16,
613+
I16X4 => VectorSize::Size16x4,
614+
I16X8 => VectorSize::Size16x8,
615+
I32X2 => VectorSize::Size32x2,
616+
I32X4 => VectorSize::Size32x4,
617+
I64X2 => VectorSize::Size64x2,
618+
_ => unimplemented!(),
619+
}
620+
}
621+
622+
/// Get the integer operand size that corresponds to a lane of a vector with a certain size.
623+
pub fn operand_size(&self) -> OperandSize {
624+
match self {
625+
VectorSize::Size64x2 => OperandSize::Size64,
626+
_ => OperandSize::Size32,
627+
}
628+
}
629+
630+
/// Get the scalar operand size that corresponds to a lane of a vector with a certain size.
631+
pub fn lane_size(&self) -> ScalarSize {
632+
match self {
633+
VectorSize::Size8x8 => ScalarSize::Size8,
634+
VectorSize::Size8x16 => ScalarSize::Size8,
635+
VectorSize::Size16x4 => ScalarSize::Size16,
636+
VectorSize::Size16x8 => ScalarSize::Size16,
637+
VectorSize::Size32x2 => ScalarSize::Size32,
638+
VectorSize::Size32x4 => ScalarSize::Size32,
639+
VectorSize::Size64x2 => ScalarSize::Size64,
640+
}
641+
}
642+
}

cranelift/codegen/src/isa/aarch64/inst/emit.rs

Lines changed: 50 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ impl MachInstEmit for Inst {
10071007
sink.put4(enc_vecmov(/* 16b = */ true, rd, rn));
10081008
}
10091009
&Inst::FpuMoveFromVec { rd, rn, idx, size } => {
1010-
let (imm5, shift, mask) = match size {
1010+
let (imm5, shift, mask) = match size.lane_size() {
10111011
ScalarSize::Size32 => (0b00100, 3, 0b011),
10121012
ScalarSize::Size64 => (0b01000, 4, 0b001),
10131013
_ => unimplemented!(),
@@ -1048,6 +1048,10 @@ impl MachInstEmit for Inst {
10481048
FPUOp2::Max64 => 0b000_11110_01_1_00000_010010,
10491049
FPUOp2::Min32 => 0b000_11110_00_1_00000_010110,
10501050
FPUOp2::Min64 => 0b000_11110_01_1_00000_010110,
1051+
FPUOp2::Sqadd64 => 0b010_11110_11_1_00000_000011,
1052+
FPUOp2::Uqadd64 => 0b011_11110_11_1_00000_000011,
1053+
FPUOp2::Sqsub64 => 0b010_11110_11_1_00000_001011,
1054+
FPUOp2::Uqsub64 => 0b011_11110_11_1_00000_001011,
10511055
};
10521056
sink.put4(enc_fpurrr(top22, rd, rn, rm));
10531057
}
@@ -1102,31 +1106,25 @@ impl MachInstEmit for Inst {
11021106
};
11031107
sink.put4(enc_fpurrrr(top17, rd, rn, rm, ra));
11041108
}
1105-
&Inst::VecMisc { op, rd, rn, ty } => {
1106-
let enc_size = match ty {
1107-
I8X16 => 0b00,
1108-
I16X8 => 0b01,
1109-
I32X4 => 0b10,
1110-
I64X2 => 0b11,
1111-
_ => 0,
1109+
&Inst::VecMisc { op, rd, rn, size } => {
1110+
let enc_size = match size {
1111+
VectorSize::Size8x16 => 0b00,
1112+
VectorSize::Size16x8 => 0b01,
1113+
VectorSize::Size32x4 => 0b10,
1114+
VectorSize::Size64x2 => 0b11,
1115+
_ => unimplemented!(),
11121116
};
11131117
let (bits_12_16, size) = match op {
1114-
VecMisc2::Not => {
1115-
debug_assert_eq!(128, ty_bits(ty));
1116-
(0b00101, 0b00)
1117-
}
1118-
VecMisc2::Neg => {
1119-
debug_assert_eq!(128, ty_bits(ty));
1120-
(0b01011, enc_size)
1121-
}
1118+
VecMisc2::Not => (0b00101, 0b00),
1119+
VecMisc2::Neg => (0b01011, enc_size),
11221120
};
11231121
sink.put4(enc_vec_rr_misc(size, bits_12_16, rd, rn));
11241122
}
1125-
&Inst::VecLanes { op, rd, rn, ty } => {
1126-
let (q, size) = match ty {
1127-
I8X16 => (0b1, 0b00),
1128-
I16X8 => (0b1, 0b01),
1129-
I32X4 => (0b1, 0b10),
1123+
&Inst::VecLanes { op, rd, rn, size } => {
1124+
let (q, size) = match size {
1125+
VectorSize::Size8x16 => (0b1, 0b00),
1126+
VectorSize::Size16x8 => (0b1, 0b01),
1127+
VectorSize::Size32x4 => (0b1, 0b10),
11301128
_ => unreachable!(),
11311129
};
11321130
let (u, opcode) = match op {
@@ -1250,12 +1248,12 @@ impl MachInstEmit for Inst {
12501248
| machreg_to_vec(rd.to_reg()),
12511249
);
12521250
}
1253-
&Inst::MovFromVec { rd, rn, idx, ty } => {
1254-
let (q, imm5, shift, mask) = match ty {
1255-
I8 => (0b0, 0b00001, 1, 0b1111),
1256-
I16 => (0b0, 0b00010, 2, 0b0111),
1257-
I32 => (0b0, 0b00100, 3, 0b0011),
1258-
I64 => (0b1, 0b01000, 4, 0b0001),
1251+
&Inst::MovFromVec { rd, rn, idx, size } => {
1252+
let (q, imm5, shift, mask) = match size {
1253+
VectorSize::Size8x16 => (0b0, 0b00001, 1, 0b1111),
1254+
VectorSize::Size16x8 => (0b0, 0b00010, 2, 0b0111),
1255+
VectorSize::Size32x4 => (0b0, 0b00100, 3, 0b0011),
1256+
VectorSize::Size64x2 => (0b1, 0b01000, 4, 0b0001),
12591257
_ => unreachable!(),
12601258
};
12611259
debug_assert_eq!(idx & mask, idx);
@@ -1268,12 +1266,12 @@ impl MachInstEmit for Inst {
12681266
| machreg_to_gpr(rd.to_reg()),
12691267
);
12701268
}
1271-
&Inst::VecDup { rd, rn, ty } => {
1272-
let imm5 = match ty {
1273-
I8 => 0b00001,
1274-
I16 => 0b00010,
1275-
I32 => 0b00100,
1276-
I64 => 0b01000,
1269+
&Inst::VecDup { rd, rn, size } => {
1270+
let imm5 = match size {
1271+
VectorSize::Size8x16 => 0b00001,
1272+
VectorSize::Size16x8 => 0b00010,
1273+
VectorSize::Size32x4 => 0b00100,
1274+
VectorSize::Size64x2 => 0b01000,
12771275
_ => unimplemented!(),
12781276
};
12791277
sink.put4(
@@ -1283,10 +1281,10 @@ impl MachInstEmit for Inst {
12831281
| machreg_to_vec(rd.to_reg()),
12841282
);
12851283
}
1286-
&Inst::VecDupFromFpu { rd, rn, ty } => {
1287-
let imm5 = match ty {
1288-
F32 => 0b00100,
1289-
F64 => 0b01000,
1284+
&Inst::VecDupFromFpu { rd, rn, size } => {
1285+
let imm5 = match size {
1286+
VectorSize::Size32x4 => 0b00100,
1287+
VectorSize::Size64x2 => 0b01000,
12901288
_ => unimplemented!(),
12911289
};
12921290
sink.put4(
@@ -1318,41 +1316,25 @@ impl MachInstEmit for Inst {
13181316
rn,
13191317
rm,
13201318
alu_op,
1321-
ty,
1319+
size,
13221320
} => {
1323-
let enc_size = match ty {
1324-
I8X16 => 0b00,
1325-
I16X8 => 0b01,
1326-
I32X4 => 0b10,
1327-
I64X2 => 0b11,
1321+
let enc_size = match size {
1322+
VectorSize::Size8x16 => 0b00,
1323+
VectorSize::Size16x8 => 0b01,
1324+
VectorSize::Size32x4 => 0b10,
1325+
VectorSize::Size64x2 => 0b11,
13281326
_ => 0,
13291327
};
1330-
let enc_size_for_fcmp = match ty {
1331-
F32X4 => 0b0,
1332-
F64X2 => 0b1,
1328+
let enc_size_for_fcmp = match size {
1329+
VectorSize::Size32x4 => 0b0,
1330+
VectorSize::Size64x2 => 0b1,
13331331
_ => 0,
13341332
};
13351333

13361334
let (top11, bit15_10) = match alu_op {
1337-
VecALUOp::SQAddScalar => {
1338-
debug_assert_eq!(I64, ty);
1339-
(0b010_11110_11_1, 0b000011)
1340-
}
13411335
VecALUOp::Sqadd => (0b010_01110_00_1 | enc_size << 1, 0b000011),
1342-
VecALUOp::SQSubScalar => {
1343-
debug_assert_eq!(I64, ty);
1344-
(0b010_11110_11_1, 0b001011)
1345-
}
13461336
VecALUOp::Sqsub => (0b010_01110_00_1 | enc_size << 1, 0b001011),
1347-
VecALUOp::UQAddScalar => {
1348-
debug_assert_eq!(I64, ty);
1349-
(0b011_11110_11_1, 0b000011)
1350-
}
13511337
VecALUOp::Uqadd => (0b011_01110_00_1 | enc_size << 1, 0b000011),
1352-
VecALUOp::UQSubScalar => {
1353-
debug_assert_eq!(I64, ty);
1354-
(0b011_11110_11_1, 0b001011)
1355-
}
13561338
VecALUOp::Uqsub => (0b011_01110_00_1 | enc_size << 1, 0b001011),
13571339
VecALUOp::Cmeq => (0b011_01110_00_1 | enc_size << 1, 0b100011),
13581340
VecALUOp::Cmge => (0b010_01110_00_1 | enc_size << 1, 0b001111),
@@ -1364,31 +1346,16 @@ impl MachInstEmit for Inst {
13641346
VecALUOp::Fcmge => (0b011_01110_00_1 | enc_size_for_fcmp << 1, 0b111001),
13651347
// The following logical instructions operate on bytes, so are not encoded differently
13661348
// for the different vector types.
1367-
VecALUOp::And => {
1368-
debug_assert_eq!(128, ty_bits(ty));
1369-
(0b010_01110_00_1, 0b000111)
1370-
}
1371-
VecALUOp::Bic => {
1372-
debug_assert_eq!(128, ty_bits(ty));
1373-
(0b010_01110_01_1, 0b000111)
1374-
}
1375-
VecALUOp::Orr => {
1376-
debug_assert_eq!(128, ty_bits(ty));
1377-
(0b010_01110_10_1, 0b000111)
1378-
}
1379-
VecALUOp::Eor => {
1380-
debug_assert_eq!(128, ty_bits(ty));
1381-
(0b011_01110_00_1, 0b000111)
1382-
}
1383-
VecALUOp::Bsl => {
1384-
debug_assert_eq!(128, ty_bits(ty));
1385-
(0b011_01110_01_1, 0b000111)
1386-
}
1349+
VecALUOp::And => (0b010_01110_00_1, 0b000111),
1350+
VecALUOp::Bic => (0b010_01110_01_1, 0b000111),
1351+
VecALUOp::Orr => (0b010_01110_10_1, 0b000111),
1352+
VecALUOp::Eor => (0b011_01110_00_1, 0b000111),
1353+
VecALUOp::Bsl => (0b011_01110_01_1, 0b000111),
13871354
VecALUOp::Umaxp => (0b011_01110_00_1 | enc_size << 1, 0b101001),
13881355
VecALUOp::Add => (0b010_01110_00_1 | enc_size << 1, 0b100001),
13891356
VecALUOp::Sub => (0b011_01110_00_1 | enc_size << 1, 0b100001),
13901357
VecALUOp::Mul => {
1391-
debug_assert_ne!(I64X2, ty);
1358+
debug_assert_ne!(size, VectorSize::Size64x2);
13921359
(0b010_01110_00_1 | enc_size << 1, 0b100111)
13931360
}
13941361
VecALUOp::Sshl => (0b010_01110_00_1 | enc_size << 1, 0b010001),

0 commit comments

Comments
 (0)