[clang] [clang] Emit i32 args for __builtin_prefetch (PR #202111)

via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 7 00:57:03 PDT 2026


https://github.com/mygitljf created https://github.com/llvm/llvm-project/pull/202111

I fixed a Clang CodeGen crash where valid __builtin_prefetch calls using non-int constant expressions, like sizeof or ULL constants, could produce LLVM IR arguments with the wrong type. The optional prefetch arguments are already checked by Sema as small integer constants, so this change lowers them directly as i32 constants to match llvm.prefetch’s immarg signature. I also added a regression test covering sizeof and unsigned long long constants.

Fixes #202061

>From 7e93143f648172ab7f47cca66ea36d37584b6a9f Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Sun, 7 Jun 2026 07:49:54 +0000
Subject: [PATCH] [clang] Emit i32 prefetch args

---
 clang/lib/CodeGen/CGBuiltin.cpp | 19 +++++++++++++------
 clang/test/CodeGen/PR32874.c    | 10 ++++++++++
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 0cb5f95049789..1ce216d115501 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4304,12 +4304,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     return RValue::get(Result);
   }
   case Builtin::BI__builtin_prefetch: {
-    Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
-    // FIXME: Technically these constants should of type 'int', yes?
-    RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) :
-      llvm::ConstantInt::get(Int32Ty, 0);
-    Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) :
-      llvm::ConstantInt::get(Int32Ty, 3);
+    auto EmitI32ConstArg = [&](unsigned ArgNo, uint64_t Default) -> Value * {
+      if (E->getNumArgs() <= ArgNo)
+        return llvm::ConstantInt::get(Int32Ty, Default);
+
+      std::optional<llvm::APSInt> Result =
+          E->getArg(ArgNo)->getIntegerConstantExpr(getContext());
+      assert(Result && "Expected argument to be a constant");
+      return llvm::ConstantInt::get(Int32Ty, Result->getZExtValue());
+    };
+
+    Value *Address = EmitScalarExpr(E->getArg(0));
+    Value *RW = EmitI32ConstArg(1, 0);
+    Value *Locality = EmitI32ConstArg(2, 3);
     Value *Data = llvm::ConstantInt::get(Int32Ty, 1);
     Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());
     Builder.CreateCall(F, {Address, RW, Locality, Data});
diff --git a/clang/test/CodeGen/PR32874.c b/clang/test/CodeGen/PR32874.c
index 234eebcbe4574..665b327528b0a 100644
--- a/clang/test/CodeGen/PR32874.c
+++ b/clang/test/CodeGen/PR32874.c
@@ -23,6 +23,16 @@ void foo(const int *p) {
   __builtin_prefetch(p, 3U % 2U, 3U % 1U);
 }
 
+// CHECK-LABEL: define{{.*}} void @prefetch_non_int_constant_types
+// CHECK: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
+// CHECK: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
+// CHECK: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
+void prefetch_non_int_constant_types(const int *p) {
+  __builtin_prefetch(p, 0 * sizeof(int));
+  __builtin_prefetch(p, 0, 0 * sizeof(int));
+  __builtin_prefetch(p, 1ULL, 3ULL);
+}
+
 // CHECK-LABEL: define{{.*}} void @ub_constant_arithmetic
 void ub_constant_arithmetic(void) {
   // Check that we still instrument unsafe arithmetic, even if it is known to



More information about the cfe-commits mailing list