[llvm] [Verifier] Use size_t width for reqd_work_group_size check (PR #206214)
Wenju He via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 26 19:56:18 PDT 2026
https://github.com/wenju-he created https://github.com/llvm/llvm-project/pull/206214
SYCL 2020 spec (Secion 4.9.1.1, Table 79) defines range::size() as product of its dimensions and return type is size_t.
Replace the hardcoded 64-bit limit with
DL.getIndexSizeInBits(DL.getProgramAddressSpace()) to match with target size_t width. Use APInt umul_ov for overflow detection.
Assisted-by: Claude
>From d07301ff574b20479e04eadc82bbc479f365d90e Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Fri, 26 Jun 2026 19:48:24 -0700
Subject: [PATCH] [Verifier] Use size_t width for reqd_work_group_size check
SYCL 2020 spec (Secion 4.9.1.1, Table 79) defines range::size() as
product of its dimensions and return type is size_t.
Replace the hardcoded 64-bit limit with
DL.getIndexSizeInBits(DL.getProgramAddressSpace()) to match with target
size_t width. Use APInt umul_ov for overflow detection.
Assisted-by: Claude
---
llvm/lib/IR/Verifier.cpp | 22 ++++---
llvm/test/Verifier/reqd_work_group_size.ll | 76 ++++++++++++++++++++++
2 files changed, 88 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/Verifier/reqd_work_group_size.ll
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 648446555793b..6f029c3ba9795 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2637,7 +2637,9 @@ void Verifier::verifyFunctionMetadata(
if (MD->getNumOperands() != 3)
continue;
- uint64_t Product = 1;
+ unsigned SizeTBits = DL.getIndexSizeInBits(DL.getProgramAddressSpace());
+ APInt Product(SizeTBits, 1);
+ bool Overflow = false;
for (unsigned I = 0; I != 3; ++I) {
ConstantInt *C = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
Check(C, "reqd_work_group_size operands must be integer constants", MD);
@@ -2645,17 +2647,17 @@ void Verifier::verifyFunctionMetadata(
break;
const APInt &Value = C->getValue();
- Check(Value.getActiveBits() <= 64,
- "reqd_work_group_size operands must fit in 64 bits", MD);
- if (Value.getActiveBits() > 64)
+ Check(Value.getActiveBits() <= SizeTBits,
+ "reqd_work_group_size operands must fit in size_t", MD);
+ if (Value.getActiveBits() > SizeTBits)
break;
- uint64_t Dim = Value.getZExtValue();
- Check(Dim == 0 || Product <= std::numeric_limits<uint64_t>::max() / Dim,
- "reqd_work_group_size product must fit in 64 bits", MD);
- if (Dim != 0 && Product > std::numeric_limits<uint64_t>::max() / Dim)
- break;
- Product *= Dim;
+ APInt Dim = Value.zextOrTrunc(SizeTBits);
+ if (!Dim.isZero() && !Overflow) {
+ Product = Product.umul_ov(Dim, Overflow);
+ Check(!Overflow, "reqd_work_group_size product must fit in size_t",
+ MD);
+ }
}
}
}
diff --git a/llvm/test/Verifier/reqd_work_group_size.ll b/llvm/test/Verifier/reqd_work_group_size.ll
new file mode 100644
index 0000000000000..5d397024e9bf2
--- /dev/null
+++ b/llvm/test/Verifier/reqd_work_group_size.ll
@@ -0,0 +1,76 @@
+; RUN: split-file %s %t
+; RUN: llvm-as %t/valid64.ll --disable-output 2>&1 | count 0
+; RUN: not llvm-as %t/overflow64.ll --disable-output 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+; RUN: llvm-as %t/valid32.ll --disable-output 2>&1 | count 0
+; RUN: not llvm-as %t/overflow32.ll --disable-output 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+; RUN: not llvm-as %t/operand-too-large32.ll --disable-output 2>&1 | FileCheck %s --check-prefix=OPERAND
+; RUN: not llvm-as %t/operand-too-large64.ll --disable-output 2>&1 | FileCheck %s --check-prefix=OPERAND
+
+; OVERFLOW: reqd_work_group_size product must fit in size_t
+; OPERAND: reqd_work_group_size operands must fit in size_t
+
+;--- valid64.ll
+; UINT64_MAX * 1 * 1: product fits in 64-bit size_t.
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64-unknown-unknown"
+
+define spir_kernel void @large_dim() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i64 -1, i32 1, i32 1}
+
+;--- overflow64.ll
+; UINT64_MAX * 2 * 1: product overflows 64-bit size_t.
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64-unknown-unknown"
+
+define spir_kernel void @overflow_product() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i64 -1, i64 2, i32 1}
+
+;--- valid32.ll
+; UINT32_MAX * 1 * 1: product fits in 32-bit size_t.
+target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv32-unknown-unknown"
+
+define spir_kernel void @large_dim() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i32 -1, i32 1, i32 1}
+
+;--- overflow32.ll
+; UINT32_MAX * 2 * 1: product overflows 32-bit size_t.
+target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv32-unknown-unknown"
+
+define spir_kernel void @overflow_product() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i32 -1, i32 2, i32 1}
+
+;--- operand-too-large32.ll
+; i64 value > UINT32_MAX: operand does not fit in 32-bit size_t.
+target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv32-unknown-unknown"
+
+define spir_kernel void @operand_too_large() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i64 4294967296, i32 1, i32 1}
+
+;--- operand-too-large64.ll
+; i128 value > UINT64_MAX: operand does not fit in 64-bit size_t.
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
+target triple = "spirv64-unknown-unknown"
+
+define spir_kernel void @operand_too_large() !reqd_work_group_size !0 {
+ ret void
+}
+
+!0 = !{i128 18446744073709551616, i32 1, i32 1}
More information about the llvm-commits
mailing list