[clang] [llvm] [Clang][Lexer] Reland "Detect SSE4.2 availability at runtime in fastParseASCIIIdentifier" (PR #180631)
Thibault Monnier via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 10 07:50:30 PST 2026
https://github.com/Thibault-Monnier updated https://github.com/llvm/llvm-project/pull/180631
>From 285a93c2644cace2eedc7cafde5be9fbfdddca4e Mon Sep 17 00:00:00 2001
From: Thibault-Monnier <thibaultmonni at gmail.com>
Date: Mon, 9 Feb 2026 22:18:00 +0100
Subject: [PATCH 1/2] Detect sse4.2 availability at runtime to use it on modern
processors
---
clang/lib/Lex/Lexer.cpp | 43 +++++++++++++++++++---------
llvm/include/llvm/Support/Compiler.h | 31 ++++++++++++++++++++
2 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 1498657047bd6..a129e036f82d1 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/NativeFormatting.h"
#include "llvm/Support/Unicode.h"
#include "llvm/Support/UnicodeCharRanges.h"
+
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -45,7 +46,7 @@
#include <optional>
#include <string>
-#ifdef __SSE4_2__
+#if LLVM_IS_X86
#include <nmmintrin.h>
#endif
@@ -1930,35 +1931,49 @@ bool Lexer::LexUnicodeIdentifierStart(Token &Result, uint32_t C,
return true;
}
-static const char *
-fastParseASCIIIdentifier(const char *CurPtr,
- [[maybe_unused]] const char *BufferEnd) {
-#ifdef __SSE4_2__
+static const char *fastParseASCIIIdentifierScalar(const char *CurPtr) {
+ unsigned char C = *CurPtr;
+ while (isAsciiIdentifierContinue(C))
+ C = *++CurPtr;
+ return CurPtr;
+}
+
+#if LLVM_IS_X86
+// Fast path for lexing ASCII identifiers using SSE4.2 instructions.
+LLVM_TARGET_SSE42 static const char *
+fastParseASCIIIdentifierSSE42(const char *CurPtr, const char *BufferEnd) {
alignas(16) static constexpr char AsciiIdentifierRange[16] = {
'_', '_', 'A', 'Z', 'a', 'z', '0', '9',
};
constexpr ssize_t BytesPerRegister = 16;
__m128i AsciiIdentifierRangeV =
- _mm_load_si128((const __m128i *)AsciiIdentifierRange);
+ _mm_load_si128(reinterpret_cast<const __m128i *>(AsciiIdentifierRange));
while (LLVM_LIKELY(BufferEnd - CurPtr >= BytesPerRegister)) {
- __m128i Cv = _mm_loadu_si128((const __m128i *)(CurPtr));
+ __m128i Cv = _mm_loadu_si128(reinterpret_cast<const __m128i *>(CurPtr));
- int Consumed = _mm_cmpistri(AsciiIdentifierRangeV, Cv,
- _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES |
- _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY);
+ const int Consumed =
+ _mm_cmpistri(AsciiIdentifierRangeV, Cv,
+ _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES |
+ _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY);
CurPtr += Consumed;
if (Consumed == BytesPerRegister)
continue;
return CurPtr;
}
+
+ return fastParseASCIIIdentifierScalar(CurPtr);
+}
#endif
- unsigned char C = *CurPtr;
- while (isAsciiIdentifierContinue(C))
- C = *++CurPtr;
- return CurPtr;
+static const char *fastParseASCIIIdentifier(const char *CurPtr,
+ const char *BufferEnd) {
+#if LLVM_IS_X86
+ if (LLVM_LIKELY(LLVM_CPU_SUPPORTS_SSE42))
+ return fastParseASCIIIdentifierSSE42(CurPtr, BufferEnd);
+#endif
+ return fastParseASCIIIdentifierScalar(CurPtr);
}
bool Lexer::LexIdentifierContinue(Token &Result, const char *CurPtr) {
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index f4bd894021097..6b1ea3d32dc90 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -762,4 +762,35 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#endif
// clang-format on
+/// \macro LLVM_IS_X86
+/// Whether the target architecture is x86 / x86-64.
+#if defined(__x86_64__) || defined(__i386__)
+#define LLVM_IS_X86 1
+#else
+#define LLVM_IS_X86 0
+#endif
+
+/// \macro LLVM_TARGET_SSE42
+/// Function attribute to compile a function with SSE4.2 enabled.
+#if defined(__has_attribute) && __has_attribute(target)
+#define LLVM_TARGET_SSE42 __attribute__((target("sse4.2")))
+#else
+#define LLVM_TARGET_SSE42
+#endif
+
+#if __has_builtin(__builtin_cpu_supports)
+#define LLVM_CPU_SUPPORTS(feature) __builtin_cpu_supports(feature)
+#else
+#define LLVM_CPU_SUPPORTS(feature) 0
+#endif
+
+/// \macro LLVM_CPU_SUPPORTS_SSE42
+/// Expands to true if the runtime cpu supports SSE4.2, or if compiled with
+/// SSE4.2 enabled.
+#if defined(__SSE4_2__)
+#define LLVM_CPU_SUPPORTS_SSE42 1
+#else
+#define LLVM_CPU_SUPPORTS_SSE42 LLVM_CPU_SUPPORTS("sse4.2")
+#endif
+
#endif
>From 08778ea84aa7c27dc236f1005c0297dee9df329e Mon Sep 17 00:00:00 2001
From: Thibault-Monnier <thibaultmonni at gmail.com>
Date: Tue, 10 Feb 2026 16:50:17 +0100
Subject: [PATCH 2/2] Fix windows compilation
---
llvm/include/llvm/Support/Compiler.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index 6b1ea3d32dc90..2e72adb686858 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -780,6 +780,9 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#if __has_builtin(__builtin_cpu_supports)
#define LLVM_CPU_SUPPORTS(feature) __builtin_cpu_supports(feature)
+#if defined(_MSC_VER) && defined(__clang__)
+#pragma comment(lib, "clang_rt.builtins.lib")
+#endif
#else
#define LLVM_CPU_SUPPORTS(feature) 0
#endif
More information about the llvm-commits
mailing list