[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