Skip to content

Commit 79dfac5

Browse files
committed
Refactor the InstSize enum in the AArch64 backend
The main issue with the InstSize enum was that it was used both for GPR and SIMD & FP operands, even though machine instructions do not mix them in general (as in a destination register is either a GPR or not). As a result it had methods such as sf_bit() that made sense only for one type of operand. Another issue was that the enum name was not reflecting its purpose accurately - it was meant to represent an instruction operand size, not an instruction size, which is fixed in A64 (always 4 bytes). Now the enum is split into one for GPR operands and another for scalar SIMD & FP operands. Copyright (c) 2020, Arm Limited.
1 parent 85ffc8f commit 79dfac5

File tree

7 files changed

+268
-231
lines changed

7 files changed

+268
-231
lines changed

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

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,8 @@ impl ShowWithRRU for MemArg {
403403
&MemArg::RegScaledExtended(r1, r2, ty, op) => {
404404
let shift = shift_for_type(ty);
405405
let size = match op {
406-
ExtendOp::SXTW | ExtendOp::UXTW => InstSize::Size32,
407-
_ => InstSize::Size64,
406+
ExtendOp::SXTW | ExtendOp::UXTW => OperandSize::Size32,
407+
_ => OperandSize::Size64,
408408
};
409409
let op = op.show_rru(mb_rru);
410410
format!(
@@ -417,8 +417,8 @@ impl ShowWithRRU for MemArg {
417417
}
418418
&MemArg::RegExtended(r1, r2, op) => {
419419
let size = match op {
420-
ExtendOp::SXTW | ExtendOp::UXTW => InstSize::Size32,
421-
_ => InstSize::Size64,
420+
ExtendOp::SXTW | ExtendOp::UXTW => OperandSize::Size32,
421+
_ => OperandSize::Size64,
422422
};
423423
let op = op.show_rru(mb_rru);
424424
format!(
@@ -492,67 +492,98 @@ impl ShowWithRRU for BranchTarget {
492492
}
493493

494494
/// Type used to communicate the operand size of a machine instruction, as AArch64 has 32- and
495-
/// 64-bit variants of many instructions (and integer and floating-point registers) and 128-bit
496-
/// variants of vector instructions.
497-
/// TODO: Create a separate type for SIMD & floating-point operands.
495+
/// 64-bit variants of many instructions (and integer registers).
498496
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
499-
pub enum InstSize {
497+
pub enum OperandSize {
500498
Size32,
501499
Size64,
502-
Size128,
503500
}
504501

505-
impl InstSize {
502+
impl OperandSize {
506503
/// 32-bit case?
507504
pub fn is32(self) -> bool {
508-
self == InstSize::Size32
505+
self == OperandSize::Size32
509506
}
510507
/// 64-bit case?
511508
pub fn is64(self) -> bool {
512-
self == InstSize::Size64
509+
self == OperandSize::Size64
513510
}
514-
/// Convert from an `is32` boolean flag to an `InstSize`.
515-
pub fn from_is32(is32: bool) -> InstSize {
511+
/// Convert from an `is32` boolean flag to an `OperandSize`.
512+
pub fn from_is32(is32: bool) -> OperandSize {
516513
if is32 {
517-
InstSize::Size32
514+
OperandSize::Size32
518515
} else {
519-
InstSize::Size64
516+
OperandSize::Size64
520517
}
521518
}
522519
/// Convert from a needed width to the smallest size that fits.
523-
pub fn from_bits<I: Into<usize>>(bits: I) -> InstSize {
520+
pub fn from_bits<I: Into<usize>>(bits: I) -> OperandSize {
524521
let bits: usize = bits.into();
525-
assert!(bits <= 128);
522+
assert!(bits <= 64);
526523
if bits <= 32 {
527-
InstSize::Size32
528-
} else if bits <= 64 {
529-
InstSize::Size64
524+
OperandSize::Size32
530525
} else {
531-
InstSize::Size128
526+
OperandSize::Size64
532527
}
533528
}
534529

535530
/// Convert from an integer type into the smallest size that fits.
536-
pub fn from_ty(ty: Type) -> InstSize {
531+
pub fn from_ty(ty: Type) -> OperandSize {
537532
Self::from_bits(ty_bits(ty))
538533
}
539534

540535
/// Convert to I32, I64, or I128.
541536
pub fn to_ty(self) -> Type {
542537
match self {
543-
InstSize::Size32 => I32,
544-
InstSize::Size64 => I64,
545-
InstSize::Size128 => I128,
538+
OperandSize::Size32 => I32,
539+
OperandSize::Size64 => I64,
546540
}
547541
}
548542

549543
pub fn sf_bit(&self) -> u32 {
550544
match self {
551-
InstSize::Size32 => 0,
552-
InstSize::Size64 => 1,
553-
_ => {
554-
panic!("Unexpected size");
555-
}
545+
OperandSize::Size32 => 0,
546+
OperandSize::Size64 => 1,
547+
}
548+
}
549+
}
550+
551+
/// Type used to communicate the size of a scalar SIMD & FP operand.
552+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
553+
pub enum ScalarSize {
554+
Size8,
555+
Size16,
556+
Size32,
557+
Size64,
558+
Size128,
559+
}
560+
561+
impl ScalarSize {
562+
/// Convert from a needed width to the smallest size that fits.
563+
pub fn from_bits<I: Into<usize>>(bits: I) -> ScalarSize {
564+
match bits.into().next_power_of_two() {
565+
8 => ScalarSize::Size8,
566+
16 => ScalarSize::Size16,
567+
32 => ScalarSize::Size32,
568+
64 => ScalarSize::Size64,
569+
128 => ScalarSize::Size128,
570+
_ => panic!("Unexpected type width"),
571+
}
572+
}
573+
574+
/// Convert from a type into the smallest size that fits.
575+
pub fn from_ty(ty: Type) -> ScalarSize {
576+
Self::from_bits(ty_bits(ty))
577+
}
578+
579+
/// Return the encoding bits that are used by some scalar FP instructions
580+
/// for a particular operand size.
581+
pub fn ftype(&self) -> u32 {
582+
match self {
583+
ScalarSize::Size16 => 0b11,
584+
ScalarSize::Size32 => 0b00,
585+
ScalarSize::Size64 => 0b01,
586+
_ => panic!("Unexpected scalar FP operand size"),
556587
}
557588
}
558589
}

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

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,13 @@ fn enc_csel(rd: Writable<Reg>, rn: Reg, rm: Reg, cond: Cond) -> u32 {
282282
| (cond.bits() << 12)
283283
}
284284

285-
fn enc_fcsel(rd: Writable<Reg>, rn: Reg, rm: Reg, cond: Cond, size: InstSize) -> u32 {
286-
let ty_bit = if size.is32() { 0 } else { 1 };
285+
fn enc_fcsel(rd: Writable<Reg>, rn: Reg, rm: Reg, cond: Cond, size: ScalarSize) -> u32 {
287286
0b000_11110_00_1_00000_0000_11_00000_00000
287+
| (size.ftype() << 22)
288288
| (machreg_to_vec(rm) << 16)
289289
| (machreg_to_vec(rn) << 5)
290290
| machreg_to_vec(rd.to_reg())
291291
| (cond.bits() << 12)
292-
| (ty_bit << 22)
293292
}
294293

295294
fn enc_cset(rd: Writable<Reg>, cond: Cond) -> u32 {
@@ -298,7 +297,7 @@ fn enc_cset(rd: Writable<Reg>, cond: Cond) -> u32 {
298297
| (cond.invert().bits() << 12)
299298
}
300299

301-
fn enc_ccmp_imm(size: InstSize, rn: Reg, imm: UImm5, nzcv: NZCV, cond: Cond) -> u32 {
300+
fn enc_ccmp_imm(size: OperandSize, rn: Reg, imm: UImm5, nzcv: NZCV, cond: Cond) -> u32 {
302301
0b0_1_1_11010010_00000_0000_10_00000_0_0000
303302
| size.sf_bit() << 31
304303
| imm.bits() << 16
@@ -334,13 +333,11 @@ fn enc_fpurrrr(top17: u32, rd: Writable<Reg>, rn: Reg, rm: Reg, ra: Reg) -> u32
334333
| machreg_to_vec(rd.to_reg())
335334
}
336335

337-
fn enc_fcmp(size: InstSize, rn: Reg, rm: Reg) -> u32 {
338-
let bits = if size.is32() {
339-
0b000_11110_00_1_00000_00_1000_00000_00000
340-
} else {
341-
0b000_11110_01_1_00000_00_1000_00000_00000
342-
};
343-
bits | (machreg_to_vec(rm) << 16) | (machreg_to_vec(rn) << 5)
336+
fn enc_fcmp(size: ScalarSize, rn: Reg, rm: Reg) -> u32 {
337+
0b000_11110_00_1_00000_00_1000_00000_00000
338+
| (size.ftype() << 22)
339+
| (machreg_to_vec(rm) << 16)
340+
| (machreg_to_vec(rn) << 5)
344341
}
345342

346343
fn enc_fputoint(top16: u32, rd: Writable<Reg>, rn: Reg) -> u32 {
@@ -613,7 +610,7 @@ impl MachInstEmit for Inst {
613610
}
614611

615612
&Inst::BitRR { op, rd, rn, .. } => {
616-
let size = if op.inst_size().is32() { 0b0 } else { 0b1 };
613+
let size = if op.operand_size().is32() { 0b0 } else { 0b1 };
617614
let (op1, op2) = match op {
618615
BitOp::RBit32 | BitOp::RBit64 => (0b00000, 0b000000),
619616
BitOp::Clz32 | BitOp::Clz64 => (0b00000, 0b000100),
@@ -979,10 +976,10 @@ impl MachInstEmit for Inst {
979976
&Inst::FpuMove128 { rd, rn } => {
980977
sink.put4(enc_vecmov(/* 16b = */ true, rd, rn));
981978
}
982-
&Inst::FpuMoveFromVec { rd, rn, idx, ty } => {
983-
let (imm5, shift, mask) = match ty {
984-
F32 => (0b00100, 3, 0b011),
985-
F64 => (0b01000, 4, 0b001),
979+
&Inst::FpuMoveFromVec { rd, rn, idx, size } => {
980+
let (imm5, shift, mask) = match size {
981+
ScalarSize::Size32 => (0b00100, 3, 0b011),
982+
ScalarSize::Size64 => (0b01000, 4, 0b001),
986983
_ => unimplemented!(),
987984
};
988985
debug_assert_eq!(idx & mask, idx);
@@ -1108,10 +1105,10 @@ impl MachInstEmit for Inst {
11081105
sink.put4(enc_vec_lanes(q, u, size, opcode, rd, rn));
11091106
}
11101107
&Inst::FpuCmp32 { rn, rm } => {
1111-
sink.put4(enc_fcmp(InstSize::Size32, rn, rm));
1108+
sink.put4(enc_fcmp(ScalarSize::Size32, rn, rm));
11121109
}
11131110
&Inst::FpuCmp64 { rn, rm } => {
1114-
sink.put4(enc_fcmp(InstSize::Size64, rn, rm));
1111+
sink.put4(enc_fcmp(ScalarSize::Size64, rn, rm));
11151112
}
11161113
&Inst::FpuToInt { op, rd, rn } => {
11171114
let top16 = match op {
@@ -1198,10 +1195,10 @@ impl MachInstEmit for Inst {
11981195
}
11991196
}
12001197
&Inst::FpuCSel32 { rd, rn, rm, cond } => {
1201-
sink.put4(enc_fcsel(rd, rn, rm, cond, InstSize::Size32));
1198+
sink.put4(enc_fcsel(rd, rn, rm, cond, ScalarSize::Size32));
12021199
}
12031200
&Inst::FpuCSel64 { rd, rn, rm, cond } => {
1204-
sink.put4(enc_fcsel(rd, rn, rm, cond, InstSize::Size64));
1201+
sink.put4(enc_fcsel(rd, rn, rm, cond, ScalarSize::Size64));
12051202
}
12061203
&Inst::FpuRound { op, rd, rn } => {
12071204
let top22 = match op {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,7 @@ fn test_aarch64_binemit() {
18081808
));
18091809
insns.push((
18101810
Inst::CCmpImm {
1811-
size: InstSize::Size64,
1811+
size: OperandSize::Size64,
18121812
rn: xreg(22),
18131813
imm: UImm5::maybe_from_u8(5).unwrap(),
18141814
nzcv: NZCV::new(false, false, true, true),
@@ -1819,7 +1819,7 @@ fn test_aarch64_binemit() {
18191819
));
18201820
insns.push((
18211821
Inst::CCmpImm {
1822-
size: InstSize::Size32,
1822+
size: OperandSize::Size32,
18231823
rn: xreg(3),
18241824
imm: UImm5::maybe_from_u8(30).unwrap(),
18251825
nzcv: NZCV::new(true, true, true, true),
@@ -3022,7 +3022,7 @@ fn test_aarch64_binemit() {
30223022
rd: writable_vreg(1),
30233023
rn: vreg(30),
30243024
idx: 2,
3025-
ty: F32,
3025+
size: ScalarSize::Size32,
30263026
},
30273027
"C107145E",
30283028
"mov s1, v30.s[2]",
@@ -3033,7 +3033,7 @@ fn test_aarch64_binemit() {
30333033
rd: writable_vreg(23),
30343034
rn: vreg(11),
30353035
idx: 0,
3036-
ty: F64,
3036+
size: ScalarSize::Size64,
30373037
},
30383038
"7705085E",
30393039
"mov d23, v11.d[0]",

0 commit comments

Comments
 (0)