Skip to content

Commit 3aee9f5

Browse files
authored
Merge pull request #1651 from bryancostanich/aarch64-crc32-intrinsics
Implement aarch64 CRC32 LLVM intrinsics
2 parents aa9af34 + 7bc02ad commit 3aee9f5

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

example/neon.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ use std::mem::transmute;
99
#[cfg(target_arch = "aarch64")]
1010
use std::simd::*;
1111

12+
#[cfg(target_arch = "aarch64")]
13+
#[target_feature(enable = "crc")]
14+
unsafe fn test_crc32() {
15+
assert!(std::arch::is_aarch64_feature_detected!("crc"));
16+
17+
let a: u32 = 42;
18+
let b: u64 = 0xdeadbeef;
19+
20+
assert_eq!(__crc32b(a, b as u8), 0xEB0E363F);
21+
assert_eq!(__crc32h(a, b as u16), 0x9A54BD80);
22+
assert_eq!(__crc32w(a, b as u32), 0xF491F059);
23+
assert_eq!(__crc32d(a, b as u64), 0xD14BBEA6);
24+
25+
assert_eq!(__crc32cb(a, b as u8), 0xF67C32D8);
26+
assert_eq!(__crc32ch(a, b as u16), 0x479108B8);
27+
assert_eq!(__crc32cw(a, b as u32), 0x979F49F8);
28+
assert_eq!(__crc32cd(a, b as u64), 0x0E6BE593);
29+
}
30+
1231
#[cfg(target_arch = "aarch64")]
1332
unsafe fn test_vpmin_s8() {
1433
let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]);
@@ -272,6 +291,8 @@ fn main() {
272291
test_vminq_f32();
273292
test_vaddvq_f32();
274293
test_vrndnq_f32();
294+
295+
test_crc32();
275296
}
276297
}
277298

src/intrinsics/llvm_aarch64.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,56 @@ pub(super) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
494494
});
495495
}
496496
*/
497+
"llvm.aarch64.crc32b"
498+
| "llvm.aarch64.crc32h"
499+
| "llvm.aarch64.crc32w"
500+
| "llvm.aarch64.crc32x"
501+
| "llvm.aarch64.crc32cb"
502+
| "llvm.aarch64.crc32ch"
503+
| "llvm.aarch64.crc32cw"
504+
| "llvm.aarch64.crc32cx" => {
505+
// ARM ARM v8-A: CRC32{,C}{B,H,W,X}.
506+
// Backs core::arch::aarch64::__crc32{,c}{b,h,w,d}.
507+
intrinsic_args!(fx, args => (crc, v); intrinsic);
508+
509+
let crc = crc.load_scalar(fx);
510+
let v = v.load_scalar(fx);
511+
512+
let asm = match intrinsic {
513+
"llvm.aarch64.crc32b" => "crc32b w0, w0, w1",
514+
"llvm.aarch64.crc32h" => "crc32h w0, w0, w1",
515+
"llvm.aarch64.crc32w" => "crc32w w0, w0, w1",
516+
"llvm.aarch64.crc32x" => "crc32x w0, w0, x1",
517+
"llvm.aarch64.crc32cb" => "crc32cb w0, w0, w1",
518+
"llvm.aarch64.crc32ch" => "crc32ch w0, w0, w1",
519+
"llvm.aarch64.crc32cw" => "crc32cw w0, w0, w1",
520+
"llvm.aarch64.crc32cx" => "crc32cx w0, w0, x1",
521+
_ => unreachable!(),
522+
};
523+
524+
codegen_inline_asm_inner(
525+
fx,
526+
&[InlineAsmTemplatePiece::String(asm.into())],
527+
&[
528+
CInlineAsmOperand::InOut {
529+
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
530+
AArch64InlineAsmReg::x0,
531+
)),
532+
_late: true,
533+
in_value: crc,
534+
out_place: Some(ret),
535+
},
536+
CInlineAsmOperand::In {
537+
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
538+
AArch64InlineAsmReg::x1,
539+
)),
540+
value: v,
541+
},
542+
],
543+
InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
544+
);
545+
}
546+
497547
_ => {
498548
fx.tcx.dcx().warn(format!(
499549
"unsupported AArch64 llvm intrinsic {}; replacing with trap",

0 commit comments

Comments
 (0)