Skip to content

Commit ab21bea

Browse files
committed
[AArch64][FastISel] Handle CRC32 intrinsics
With a similar reason as D148023; some applications make heavy use of the CRC32 intrinsic (e.g., as part of a hash function) and therefore benefit from avoiding frequent SelectionDAG fallbacks. In our application, we get a 2% compile-time improvement. Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D148917
1 parent 8ead003 commit ab21bea

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "llvm/IR/Instructions.h"
5454
#include "llvm/IR/IntrinsicInst.h"
5555
#include "llvm/IR/Intrinsics.h"
56+
#include "llvm/IR/IntrinsicsAArch64.h"
5657
#include "llvm/IR/Operator.h"
5758
#include "llvm/IR/Type.h"
5859
#include "llvm/IR/User.h"
@@ -3776,6 +3777,57 @@ bool AArch64FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
37763777
updateValueMap(II, ResultReg1, 2);
37773778
return true;
37783779
}
3780+
case Intrinsic::aarch64_crc32b:
3781+
case Intrinsic::aarch64_crc32h:
3782+
case Intrinsic::aarch64_crc32w:
3783+
case Intrinsic::aarch64_crc32x:
3784+
case Intrinsic::aarch64_crc32cb:
3785+
case Intrinsic::aarch64_crc32ch:
3786+
case Intrinsic::aarch64_crc32cw:
3787+
case Intrinsic::aarch64_crc32cx: {
3788+
if (!Subtarget->hasCRC())
3789+
return false;
3790+
3791+
unsigned Opc;
3792+
switch (II->getIntrinsicID()) {
3793+
default:
3794+
llvm_unreachable("Unexpected intrinsic!");
3795+
case Intrinsic::aarch64_crc32b:
3796+
Opc = AArch64::CRC32Brr;
3797+
break;
3798+
case Intrinsic::aarch64_crc32h:
3799+
Opc = AArch64::CRC32Hrr;
3800+
break;
3801+
case Intrinsic::aarch64_crc32w:
3802+
Opc = AArch64::CRC32Wrr;
3803+
break;
3804+
case Intrinsic::aarch64_crc32x:
3805+
Opc = AArch64::CRC32Xrr;
3806+
break;
3807+
case Intrinsic::aarch64_crc32cb:
3808+
Opc = AArch64::CRC32CBrr;
3809+
break;
3810+
case Intrinsic::aarch64_crc32ch:
3811+
Opc = AArch64::CRC32CHrr;
3812+
break;
3813+
case Intrinsic::aarch64_crc32cw:
3814+
Opc = AArch64::CRC32CWrr;
3815+
break;
3816+
case Intrinsic::aarch64_crc32cx:
3817+
Opc = AArch64::CRC32CXrr;
3818+
break;
3819+
}
3820+
3821+
Register LHSReg = getRegForValue(II->getArgOperand(0));
3822+
Register RHSReg = getRegForValue(II->getArgOperand(1));
3823+
if (!LHSReg || !RHSReg)
3824+
return false;
3825+
3826+
Register ResultReg =
3827+
fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3828+
updateValueMap(II, ResultReg);
3829+
return true;
3830+
}
37793831
}
37803832
return false;
37813833
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
; RUN: llc -mtriple=arm64-eabi -fast-isel -fast-isel-abort=3 -mattr=+crc -o - %s | FileCheck %s
2+
; RUN: llc -mtriple=arm64-eabi -fast-isel -fast-isel-abort=3 -mattr=+v8r -o - %s | FileCheck %s
3+
; RUN: llc -mtriple=arm64-eabi -fast-isel -fast-isel-abort=3 -mcpu=cortex-a53 -mattr=+crc -o - %s | FileCheck %s
4+
5+
; Note: tests are a copy of arm64-crc32.ll
6+
7+
define i32 @test_crc32b(i32 %cur, i32 %next) {
8+
; CHECK-LABEL: test_crc32b:
9+
; CHECK: crc32b w0, w0, w1
10+
%val = call i32 @llvm.aarch64.crc32b(i32 %cur, i32 %next)
11+
ret i32 %val
12+
}
13+
14+
define i32 @test_crc32h(i32 %cur, i32 %next) {
15+
; CHECK-LABEL: test_crc32h:
16+
; CHECK: crc32h w0, w0, w1
17+
%val = call i32 @llvm.aarch64.crc32h(i32 %cur, i32 %next)
18+
ret i32 %val
19+
}
20+
21+
define i32 @test_crc32w(i32 %cur, i32 %next) {
22+
; CHECK-LABEL: test_crc32w:
23+
; CHECK: crc32w w0, w0, w1
24+
%val = call i32 @llvm.aarch64.crc32w(i32 %cur, i32 %next)
25+
ret i32 %val
26+
}
27+
28+
define i32 @test_crc32x(i32 %cur, i64 %next) {
29+
; CHECK-LABEL: test_crc32x:
30+
; CHECK: crc32x w0, w0, x1
31+
%val = call i32 @llvm.aarch64.crc32x(i32 %cur, i64 %next)
32+
ret i32 %val
33+
}
34+
35+
define i32 @test_crc32cb(i32 %cur, i32 %next) {
36+
; CHECK-LABEL: test_crc32cb:
37+
; CHECK: crc32cb w0, w0, w1
38+
%val = call i32 @llvm.aarch64.crc32cb(i32 %cur, i32 %next)
39+
ret i32 %val
40+
}
41+
42+
define i32 @test_crc32ch(i32 %cur, i32 %next) {
43+
; CHECK-LABEL: test_crc32ch:
44+
; CHECK: crc32ch w0, w0, w1
45+
%val = call i32 @llvm.aarch64.crc32ch(i32 %cur, i32 %next)
46+
ret i32 %val
47+
}
48+
49+
define i32 @test_crc32cw(i32 %cur, i32 %next) {
50+
; CHECK-LABEL: test_crc32cw:
51+
; CHECK: crc32cw w0, w0, w1
52+
%val = call i32 @llvm.aarch64.crc32cw(i32 %cur, i32 %next)
53+
ret i32 %val
54+
}
55+
56+
define i32 @test_crc32cx(i32 %cur, i64 %next) {
57+
; CHECK-LABEL: test_crc32cx:
58+
; CHECK: crc32cx w0, w0, x1
59+
%val = call i32 @llvm.aarch64.crc32cx(i32 %cur, i64 %next)
60+
ret i32 %val
61+
}
62+
63+
declare i32 @llvm.aarch64.crc32b(i32, i32)
64+
declare i32 @llvm.aarch64.crc32h(i32, i32)
65+
declare i32 @llvm.aarch64.crc32w(i32, i32)
66+
declare i32 @llvm.aarch64.crc32x(i32, i64)
67+
68+
declare i32 @llvm.aarch64.crc32cb(i32, i32)
69+
declare i32 @llvm.aarch64.crc32ch(i32, i32)
70+
declare i32 @llvm.aarch64.crc32cw(i32, i32)
71+
declare i32 @llvm.aarch64.crc32cx(i32, i64)

0 commit comments

Comments
 (0)