[clang] [CIR] Add X86 prefetch builtins (PR #168051)
Hendrik Hübner via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 17 04:56:16 PST 2026
https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/168051
>From 047407bde1b792da1c927ffb64f71384e12669bb Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Fri, 19 Dec 2025 22:23:57 +0100
Subject: [PATCH 1/2] Prefetch builtin
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 35 ++++++++++++++++++
.../test/CIR/CodeGen/X86/prefetchw-builtin.c | 36 +++++++++++++++++++
.../CIR/CodeGenBuiltins/X86/sse-builtins.c | 30 ++++++++++++++++
3 files changed, 101 insertions(+)
create mode 100644 clang/test/CIR/CodeGen/X86/prefetchw-builtin.c
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 1c87e945de846..5122284f87104 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -31,6 +31,11 @@
using namespace clang;
using namespace clang::CIRGen;
+/// Get integer from a mlir::Value that is an int constant or a constant op.
+static int64_t getIntValueFromConstOp(mlir::Value val) {
+ return val.getDefiningOp<cir::ConstantOp>().getIntValue().getSExtValue();
+}
+
template <typename... Operands>
static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
mlir::Location loc, const StringRef str,
@@ -158,6 +163,33 @@ computeFullLaneShuffleMask(CIRGenFunction &cgf, const mlir::Value vec,
outIndices.resize(numElts);
}
+
+static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
+ const CallExpr *e,
+ const SmallVector<mlir::Value> &ops) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location location = cgf.getLoc(e->getExprLoc());
+ mlir::Type voidTy = builder.getVoidTy();
+ mlir::Value address = builder.createPtrBitcast(ops[0], voidTy);
+ bool isWrite{};
+ int locality{};
+
+ assert(builtinID == X86::BI_mm_prefetch || builtinID == X86::BI_m_prefetchw ||
+ builtinID == X86::BI_m_prefetch && "Expected prefetch builtin");
+
+ if (builtinID == X86::BI_mm_prefetch) {
+ int hint = getIntValueFromConstOp(ops[1]);
+ isWrite = (hint >> 2) & 0x1;
+ locality = hint & 0x3;
+ } else {
+ isWrite = (builtinID == X86::BI_m_prefetchw);
+ locality = 0x3;
+ }
+
+ cir::PrefetchOp::create(builder, location, address, locality, isWrite);
+ return {};
+}
+
static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder,
mlir::Location loc, mlir::Value source,
mlir::Value mask,
@@ -558,6 +590,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
"x86.sse.sfence", voidTy);
case X86::BI_mm_prefetch:
+ case X86::BI_m_prefetch:
+ case X86::BI_m_prefetchw:
+ return emitPrefetch(*this, builtinID, expr, ops);
case X86::BI__rdtsc:
case X86::BI__builtin_ia32_rdtscp: {
cgm.errorNYI(expr->getSourceRange(),
diff --git a/clang/test/CIR/CodeGen/X86/prefetchw-builtin.c b/clang/test/CIR/CodeGen/X86/prefetchw-builtin.c
new file mode 100644
index 0000000000000..7d7ce348b8d88
--- /dev/null
+++ b/clang/test/CIR/CodeGen/X86/prefetchw-builtin.c
@@ -0,0 +1,36 @@
+
+// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-cir -o %t.cir -Wall -Werror
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror
+// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
+
+// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror
+// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
+
+// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG
+// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG
+
+
+#include <x86intrin.h>
+
+void test_m_prefetch_w(void *p) {
+ // CIR-LABEL: test_m_prefetch_w
+ // LLVM-LABEL: test_m_prefetch_w
+ // OGCG-LABEL: test_m_prefetch_w
+ return _m_prefetchw(p);
+ // CIR: cir.prefetch write locality(3) %{{.*}} : !cir.ptr<!void>
+ // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
+ // OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
+}
+
+void test_m_prefetch(void *p) {
+ // CIR-LABEL: test_m_prefetch
+ // LLVM-LABEL: test_m_prefetch
+ // OGCG-LABEL: test_m_prefetch
+ return _m_prefetch(p);
+ // CIR: cir.prefetch read locality(3) %{{.*}} : !cir.ptr<!void>
+ // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
+ // OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/sse-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/sse-builtins.c
index db52021d1aa9f..9d01203aefc7a 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/sse-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/sse-builtins.c
@@ -56,6 +56,36 @@ void test_mm_sfence(void) {
// OGCG: call void @llvm.x86.sse.sfence()
}
+void test_mm_prefetch(char const* p) {
+ // CIR-LABEL: test_mm_prefetch
+ // LLVM-LABEL: test_mm_prefetch
+ // OGCG-LABEL: test_mm_prefetch
+ _mm_prefetch(p, 0);
+ // CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr<!void>
+ // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
+ // OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
+}
+
+void test_mm_prefetch_local(char const* p) {
+ // CIR-LABEL: test_mm_prefetch_local
+ // LLVM-LABEL: test_mm_prefetch_local
+ // OGCG-LABEL: test_mm_prefetch_local
+ _mm_prefetch(p, 3);
+ // CIR: cir.prefetch read locality(3) %{{.*}} : !cir.ptr<!void>
+ // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
+ // OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
+}
+
+void test_mm_prefetch_write(char const* p) {
+ // CIR-LABEL: test_mm_prefetch_write
+ // LLVM-LABEL: test_mm_prefetch_write
+ // OGCG-LABEL: test_mm_prefetch_write
+ _mm_prefetch(p, 7);
+ // CIR: cir.prefetch write locality(3) %{{.*}} : !cir.ptr<!void>
+ // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
+ // OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
+}
+
__m128 test_mm_undefined_ps(void) {
// CIR-LABEL: _mm_undefined_ps
// CIR: %[[A:.*]] = cir.const #cir.zero : !cir.vector<2 x !cir.double>
>From c0fd37179ace921ca203aee7b1f11d38817df6ca Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Sat, 17 Jan 2026 13:55:55 +0100
Subject: [PATCH 2/2] feedback
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 5122284f87104..1e1a47eed0d42 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -31,11 +31,6 @@
using namespace clang;
using namespace clang::CIRGen;
-/// Get integer from a mlir::Value that is an int constant or a constant op.
-static int64_t getIntValueFromConstOp(mlir::Value val) {
- return val.getDefiningOp<cir::ConstantOp>().getIntValue().getSExtValue();
-}
-
template <typename... Operands>
static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
mlir::Location loc, const StringRef str,
@@ -164,9 +159,9 @@ computeFullLaneShuffleMask(CIRGenFunction &cgf, const mlir::Value vec,
outIndices.resize(numElts);
}
-static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
- const CallExpr *e,
- const SmallVector<mlir::Value> &ops) {
+static void emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
+ const CallExpr *e,
+ const SmallVector<mlir::Value> &ops) {
CIRGenBuilderTy &builder = cgf.getBuilder();
mlir::Location location = cgf.getLoc(e->getExprLoc());
mlir::Type voidTy = builder.getVoidTy();
@@ -178,7 +173,7 @@ static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
builtinID == X86::BI_m_prefetch && "Expected prefetch builtin");
if (builtinID == X86::BI_mm_prefetch) {
- int hint = getIntValueFromConstOp(ops[1]);
+ int hint = cgf.getSExtIntValueFromConstOp(ops[1]);
isWrite = (hint >> 2) & 0x1;
locality = hint & 0x3;
} else {
@@ -187,7 +182,6 @@ static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
}
cir::PrefetchOp::create(builder, location, address, locality, isWrite);
- return {};
}
static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder,
@@ -592,7 +586,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI_mm_prefetch:
case X86::BI_m_prefetch:
case X86::BI_m_prefetchw:
- return emitPrefetch(*this, builtinID, expr, ops);
+ emitPrefetch(*this, builtinID, expr, ops);
+ return {};
case X86::BI__rdtsc:
case X86::BI__builtin_ia32_rdtscp: {
cgm.errorNYI(expr->getSourceRange(),
More information about the cfe-commits
mailing list