Skip to content

Commit 12fa608

Browse files
committed
[X86] Add CRC32 feature.
d8faf03 implemented general-regs-only for X86 by disabling all features with vector instructions. But the CRC32 instruction in SSE4.2 ISA, which uses only GPRs, also becomes unavailable. This patch adds a CRC32 feature for this instruction and allows it to be used with general-regs-only. Reviewed By: pengfei Differential Revision: https://reviews.llvm.org/D105462
1 parent cc9260a commit 12fa608

35 files changed

+484
-248
lines changed

clang/docs/ClangCommandLineReference.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3590,6 +3590,8 @@ X86
35903590

35913591
.. option:: -mclzero, -mno-clzero
35923592

3593+
.. option:: -mcrc32, -mno-crc32
3594+
35933595
.. option:: -mcx16, -mno-cx16
35943596

35953597
.. option:: -menqcmd, -mno-enqcmd

clang/include/clang/Basic/BuiltinsX86.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,9 @@ TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","ncV:128:", "sse4.2
421421
TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
422422
TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","ncV:128:", "sse4.2")
423423

424-
TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "nc", "sse4.2")
425-
TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "nc", "sse4.2")
426-
TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "nc", "sse4.2")
424+
TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "nc", "crc32")
425+
TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "nc", "crc32")
426+
TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "nc", "crc32")
427427

428428
// SSE4a
429429
TARGET_BUILTIN(__builtin_ia32_extrqi, "V2OiV2OiIcIc", "ncV:128:", "sse4a")

clang/include/clang/Basic/BuiltinsX86_64.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "OiV2d", "ncV:128:", "sse2")
4444
TARGET_BUILTIN(__builtin_ia32_movnti64, "vOi*Oi", "n", "sse2")
4545
TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "OiV2OiIi", "ncV:128:", "sse2")
4646
TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2OiV2OiOiIi", "ncV:128:", "sse4.1")
47-
TARGET_BUILTIN(__builtin_ia32_crc32di, "UOiUOiUOi", "nc", "sse4.2")
47+
TARGET_BUILTIN(__builtin_ia32_crc32di, "UOiUOiUOi", "nc", "crc32")
4848
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "OiV4OiIi", "ncV:256:", "avx")
4949
TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4OiV4OiOiIi", "ncV:256:", "avx")
5050
TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "n", "fsgsbase")

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4206,6 +4206,8 @@ def mwbnoinvd : Flag<["-"], "mwbnoinvd">, Group<m_x86_Features_Group>;
42064206
def mno_wbnoinvd : Flag<["-"], "mno-wbnoinvd">, Group<m_x86_Features_Group>;
42074207
def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>;
42084208
def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>;
4209+
def mcrc32 : Flag<["-"], "mcrc32">, Group<m_x86_Features_Group>;
4210+
def mno_crc32 : Flag<["-"], "mno-crc32">, Group<m_x86_Features_Group>;
42094211
def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
42104212
def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>;
42114213
def menqcmd : Flag<["-"], "menqcmd">, Group<m_x86_Features_Group>;

clang/lib/Basic/Targets/X86.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ bool X86TargetInfo::initFeatureMap(
155155
llvm::find(UpdatedFeaturesVec, "-xsave") == UpdatedFeaturesVec.end())
156156
Features["xsave"] = true;
157157

158+
// Enable CRC32 if SSE4.2 is enabled and CRC32 is not explicitly disabled.
159+
I = Features.find("sse4.2");
160+
if (I != Features.end() && I->getValue() &&
161+
llvm::find(UpdatedFeaturesVec, "-crc32") == UpdatedFeaturesVec.end())
162+
Features["crc32"] = true;
163+
158164
return true;
159165
}
160166

@@ -330,6 +336,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
330336
HasTSXLDTRK = true;
331337
} else if (Feature == "+uintr") {
332338
HasUINTR = true;
339+
} else if (Feature == "+crc32") {
340+
HasCRC32 = true;
333341
}
334342

335343
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
@@ -758,6 +766,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
758766
Builder.defineMacro("__TSXLDTRK__");
759767
if (HasUINTR)
760768
Builder.defineMacro("__UINTR__");
769+
if (HasCRC32)
770+
Builder.defineMacro("__CRC32__");
761771

762772
// Each case falls through to the previous one here.
763773
switch (SSELevel) {
@@ -878,6 +888,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
878888
.Case("clflushopt", true)
879889
.Case("clwb", true)
880890
.Case("clzero", true)
891+
.Case("crc32", true)
881892
.Case("cx16", true)
882893
.Case("enqcmd", true)
883894
.Case("f16c", true)
@@ -970,6 +981,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
970981
.Case("clflushopt", HasCLFLUSHOPT)
971982
.Case("clwb", HasCLWB)
972983
.Case("clzero", HasCLZERO)
984+
.Case("crc32", HasCRC32)
973985
.Case("cx8", HasCX8)
974986
.Case("cx16", HasCX16)
975987
.Case("enqcmd", HasENQCMD)

clang/lib/Basic/Targets/X86.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
143143
bool HasSERIALIZE = false;
144144
bool HasTSXLDTRK = false;
145145
bool HasUINTR = false;
146+
bool HasCRC32 = false;
146147

147148
protected:
148149
llvm::X86::CPUKind CPU = llvm::X86::CK_None;

clang/lib/Headers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ set(files
5858
cet.h
5959
cldemoteintrin.h
6060
clzerointrin.h
61+
crc32intrin.h
6162
cpuid.h
6263
clflushoptintrin.h
6364
clwbintrin.h

clang/lib/Headers/crc32intrin.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*===---- crc32intrin.h - SSE4.2 Accumulate CRC32 intrinsics ---------------===
2+
*
3+
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
* See https://llvm.org/LICENSE.txt for license information.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*
7+
*===-----------------------------------------------------------------------===
8+
*/
9+
10+
#ifndef __CRC32INTRIN_H
11+
#define __CRC32INTRIN_H
12+
13+
#define __DEFAULT_FN_ATTRS \
14+
__attribute__((__always_inline__, __nodebug__, __target__("crc32")))
15+
16+
/// Adds the unsigned integer operand to the CRC-32C checksum of the
17+
/// unsigned char operand.
18+
///
19+
/// \headerfile <x86intrin.h>
20+
///
21+
/// This intrinsic corresponds to the <c> CRC32B </c> instruction.
22+
///
23+
/// \param __C
24+
/// An unsigned integer operand to add to the CRC-32C checksum of operand
25+
/// \a __D.
26+
/// \param __D
27+
/// An unsigned 8-bit integer operand used to compute the CRC-32C checksum.
28+
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
29+
/// operand \a __D.
30+
static __inline__ unsigned int __DEFAULT_FN_ATTRS
31+
_mm_crc32_u8(unsigned int __C, unsigned char __D)
32+
{
33+
return __builtin_ia32_crc32qi(__C, __D);
34+
}
35+
36+
/// Adds the unsigned integer operand to the CRC-32C checksum of the
37+
/// unsigned short operand.
38+
///
39+
/// \headerfile <x86intrin.h>
40+
///
41+
/// This intrinsic corresponds to the <c> CRC32W </c> instruction.
42+
///
43+
/// \param __C
44+
/// An unsigned integer operand to add to the CRC-32C checksum of operand
45+
/// \a __D.
46+
/// \param __D
47+
/// An unsigned 16-bit integer operand used to compute the CRC-32C checksum.
48+
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
49+
/// operand \a __D.
50+
static __inline__ unsigned int __DEFAULT_FN_ATTRS
51+
_mm_crc32_u16(unsigned int __C, unsigned short __D)
52+
{
53+
return __builtin_ia32_crc32hi(__C, __D);
54+
}
55+
56+
/// Adds the first unsigned integer operand to the CRC-32C checksum of
57+
/// the second unsigned integer operand.
58+
///
59+
/// \headerfile <x86intrin.h>
60+
///
61+
/// This intrinsic corresponds to the <c> CRC32L </c> instruction.
62+
///
63+
/// \param __C
64+
/// An unsigned integer operand to add to the CRC-32C checksum of operand
65+
/// \a __D.
66+
/// \param __D
67+
/// An unsigned 32-bit integer operand used to compute the CRC-32C checksum.
68+
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
69+
/// operand \a __D.
70+
static __inline__ unsigned int __DEFAULT_FN_ATTRS
71+
_mm_crc32_u32(unsigned int __C, unsigned int __D)
72+
{
73+
return __builtin_ia32_crc32si(__C, __D);
74+
}
75+
76+
#ifdef __x86_64__
77+
/// Adds the unsigned integer operand to the CRC-32C checksum of the
78+
/// unsigned 64-bit integer operand.
79+
///
80+
/// \headerfile <x86intrin.h>
81+
///
82+
/// This intrinsic corresponds to the <c> CRC32Q </c> instruction.
83+
///
84+
/// \param __C
85+
/// An unsigned integer operand to add to the CRC-32C checksum of operand
86+
/// \a __D.
87+
/// \param __D
88+
/// An unsigned 64-bit integer operand used to compute the CRC-32C checksum.
89+
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
90+
/// operand \a __D.
91+
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
92+
_mm_crc32_u64(unsigned long long __C, unsigned long long __D)
93+
{
94+
return __builtin_ia32_crc32di(__C, __D);
95+
}
96+
#endif /* __x86_64__ */
97+
98+
#undef __DEFAULT_FN_ATTRS
99+
100+
#endif /* __CRC32INTRIN_H */

clang/lib/Headers/ia32intrin.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* Define the default attributes for the functions in this file. */
1818
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
19-
#define __DEFAULT_FN_ATTRS_SSE42 __attribute__((__always_inline__, __nodebug__, __target__("sse4.2")))
19+
#define __DEFAULT_FN_ATTRS_CRC32 __attribute__((__always_inline__, __nodebug__, __target__("crc32")))
2020

2121
#if defined(__cplusplus) && (__cplusplus >= 201103L)
2222
#define __DEFAULT_FN_ATTRS_CAST __attribute__((__always_inline__)) constexpr
@@ -282,7 +282,7 @@ _castu64_f64(unsigned long long __A) {
282282
* \returns The result of adding operand \a __C to the CRC-32C checksum of
283283
* operand \a __D.
284284
*/
285-
static __inline__ unsigned int __DEFAULT_FN_ATTRS_SSE42
285+
static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32
286286
__crc32b(unsigned int __C, unsigned char __D)
287287
{
288288
return __builtin_ia32_crc32qi(__C, __D);
@@ -303,7 +303,7 @@ __crc32b(unsigned int __C, unsigned char __D)
303303
* \returns The result of adding operand \a __C to the CRC-32C checksum of
304304
* operand \a __D.
305305
*/
306-
static __inline__ unsigned int __DEFAULT_FN_ATTRS_SSE42
306+
static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32
307307
__crc32w(unsigned int __C, unsigned short __D)
308308
{
309309
return __builtin_ia32_crc32hi(__C, __D);
@@ -324,7 +324,7 @@ __crc32w(unsigned int __C, unsigned short __D)
324324
* \returns The result of adding operand \a __C to the CRC-32C checksum of
325325
* operand \a __D.
326326
*/
327-
static __inline__ unsigned int __DEFAULT_FN_ATTRS_SSE42
327+
static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32
328328
__crc32d(unsigned int __C, unsigned int __D)
329329
{
330330
return __builtin_ia32_crc32si(__C, __D);
@@ -346,7 +346,7 @@ __crc32d(unsigned int __C, unsigned int __D)
346346
* \returns The result of adding operand \a __C to the CRC-32C checksum of
347347
* operand \a __D.
348348
*/
349-
static __inline__ unsigned long long __DEFAULT_FN_ATTRS_SSE42
349+
static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CRC32
350350
__crc32q(unsigned long long __C, unsigned long long __D)
351351
{
352352
return __builtin_ia32_crc32di(__C, __D);
@@ -435,7 +435,7 @@ __rorq(unsigned long long __X, int __C) {
435435

436436
#undef __DEFAULT_FN_ATTRS
437437
#undef __DEFAULT_FN_ATTRS_CAST
438-
#undef __DEFAULT_FN_ATTRS_SSE42
438+
#undef __DEFAULT_FN_ATTRS_CRC32
439439
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
440440

441441
#endif /* __IA32INTRIN_H */

clang/lib/Headers/smmintrin.h

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,91 +2338,10 @@ _mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
23382338
return (__m128i)((__v2di)__V1 > (__v2di)__V2);
23392339
}
23402340

2341-
/* SSE4.2 Accumulate CRC32. */
2342-
/// Adds the unsigned integer operand to the CRC-32C checksum of the
2343-
/// unsigned char operand.
2344-
///
2345-
/// \headerfile <x86intrin.h>
2346-
///
2347-
/// This intrinsic corresponds to the <c> CRC32B </c> instruction.
2348-
///
2349-
/// \param __C
2350-
/// An unsigned integer operand to add to the CRC-32C checksum of operand
2351-
/// \a __D.
2352-
/// \param __D
2353-
/// An unsigned 8-bit integer operand used to compute the CRC-32C checksum.
2354-
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
2355-
/// operand \a __D.
2356-
static __inline__ unsigned int __DEFAULT_FN_ATTRS
2357-
_mm_crc32_u8(unsigned int __C, unsigned char __D)
2358-
{
2359-
return __builtin_ia32_crc32qi(__C, __D);
2360-
}
2361-
2362-
/// Adds the unsigned integer operand to the CRC-32C checksum of the
2363-
/// unsigned short operand.
2364-
///
2365-
/// \headerfile <x86intrin.h>
2366-
///
2367-
/// This intrinsic corresponds to the <c> CRC32W </c> instruction.
2368-
///
2369-
/// \param __C
2370-
/// An unsigned integer operand to add to the CRC-32C checksum of operand
2371-
/// \a __D.
2372-
/// \param __D
2373-
/// An unsigned 16-bit integer operand used to compute the CRC-32C checksum.
2374-
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
2375-
/// operand \a __D.
2376-
static __inline__ unsigned int __DEFAULT_FN_ATTRS
2377-
_mm_crc32_u16(unsigned int __C, unsigned short __D)
2378-
{
2379-
return __builtin_ia32_crc32hi(__C, __D);
2380-
}
2381-
2382-
/// Adds the first unsigned integer operand to the CRC-32C checksum of
2383-
/// the second unsigned integer operand.
2384-
///
2385-
/// \headerfile <x86intrin.h>
2386-
///
2387-
/// This intrinsic corresponds to the <c> CRC32L </c> instruction.
2388-
///
2389-
/// \param __C
2390-
/// An unsigned integer operand to add to the CRC-32C checksum of operand
2391-
/// \a __D.
2392-
/// \param __D
2393-
/// An unsigned 32-bit integer operand used to compute the CRC-32C checksum.
2394-
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
2395-
/// operand \a __D.
2396-
static __inline__ unsigned int __DEFAULT_FN_ATTRS
2397-
_mm_crc32_u32(unsigned int __C, unsigned int __D)
2398-
{
2399-
return __builtin_ia32_crc32si(__C, __D);
2400-
}
2401-
2402-
#ifdef __x86_64__
2403-
/// Adds the unsigned integer operand to the CRC-32C checksum of the
2404-
/// unsigned 64-bit integer operand.
2405-
///
2406-
/// \headerfile <x86intrin.h>
2407-
///
2408-
/// This intrinsic corresponds to the <c> CRC32Q </c> instruction.
2409-
///
2410-
/// \param __C
2411-
/// An unsigned integer operand to add to the CRC-32C checksum of operand
2412-
/// \a __D.
2413-
/// \param __D
2414-
/// An unsigned 64-bit integer operand used to compute the CRC-32C checksum.
2415-
/// \returns The result of adding operand \a __C to the CRC-32C checksum of
2416-
/// operand \a __D.
2417-
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
2418-
_mm_crc32_u64(unsigned long long __C, unsigned long long __D)
2419-
{
2420-
return __builtin_ia32_crc32di(__C, __D);
2421-
}
2422-
#endif /* __x86_64__ */
2423-
24242341
#undef __DEFAULT_FN_ATTRS
24252342

24262343
#include <popcntintrin.h>
24272344

2345+
#include <crc32intrin.h>
2346+
24282347
#endif /* __SMMINTRIN_H */

clang/lib/Headers/x86gprintrin.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include <uintrintrin.h>
2121
#endif
2222

23+
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
24+
defined(__CRC32__)
25+
#include <crc32intrin.h>
26+
#endif
27+
2328
#define __SSC_MARK(Tag) \
2429
__asm__ __volatile__("movl %%ebx, %%eax; movl %0, %%ebx; .byte 0x64, 0x67, " \
2530
"0x90; movl %%eax, %%ebx;" ::"i"(Tag) \

0 commit comments

Comments
 (0)