Skip to content

Commit 4edd165

Browse files
authored
Merge pull request #1992 from akirilov-arm/InstSize
Refactor the InstSize enum in the AArch64 backend
2 parents 85ffc8f + 79dfac5 commit 4edd165

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)