Skip to content

[SPIR-V] Fix out-of-range value for NumWorkgroups builtin #127198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 18, 2025

Conversation

svenvh
Copy link
Member

@svenvh svenvh commented Feb 14, 2025

The OpenCL C specification states that for out-of-range dimension indices, get_num_groups must return 1 instead of 0.

The OpenCL C specification states that for out-of-range dimension
indices, `get_num_groups` must return 1 instead of 0.
@llvmbot
Copy link
Member

llvmbot commented Feb 14, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Sven van Haastregt (svenvh)

Changes

The OpenCL C specification states that for out-of-range dimension indices, get_num_groups must return 1 instead of 0.


Full diff: https://github.com/llvm/llvm-project/pull/127198.diff

2 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+1)
  • (added) llvm/test/CodeGen/SPIRV/opencl/get_num_groups.ll (+55)
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index a7a34e0439ab1..aec2aaccb33a8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1779,6 +1779,7 @@ static bool generateGetQueryInst(const SPIRV::IncomingCall *Call,
   SPIRV::BuiltIn::BuiltIn Value =
       SPIRV::lookupGetBuiltin(Call->Builtin->Name, Call->Builtin->Set)->Value;
   uint64_t IsDefault = (Value == SPIRV::BuiltIn::GlobalSize ||
+                        Value == SPIRV::BuiltIn::NumWorkgroups ||
                         Value == SPIRV::BuiltIn::WorkgroupSize ||
                         Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
   return genWorkgroupQuery(Call, MIRBuilder, GR, Value, IsDefault ? 1 : 0);
diff --git a/llvm/test/CodeGen/SPIRV/opencl/get_num_groups.ll b/llvm/test/CodeGen/SPIRV/opencl/get_num_groups.ll
new file mode 100644
index 0000000000000..3f1d1dc248fc4
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl/get_num_groups.ll
@@ -0,0 +1,55 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+;; The set of valid inputs for get_num_groups depends on the runtime NDRange,
+;; but inputs outside of [0, 2] always return 1.
+;; Here we assume Itanium mangling for function name.
+declare i64 @_Z14get_num_groupsj(i32)
+
+define i64 @foo(i32 %dim) {
+  %x = call i64 @_Z14get_num_groupsj(i32 0)
+  %y = call i64 @_Z14get_num_groupsj(i32 5)
+  %acc = add i64 %x, %y
+  %unknown = call i64 @_Z14get_num_groupsj(i32 %dim)
+  %ret = add i64 %acc, %unknown
+  ret i64 %ret
+}
+
+;; Capabilities:
+; CHECK-DAG: OpCapability Kernel
+; CHECK-DAG: OpCapability Int64
+
+; CHECK-NOT: DAG-FENCE
+
+;; Decorations:
+; CHECK-DAG: OpDecorate %[[#GET_NUM_GROUPS:]] BuiltIn NumWorkgroups
+; CHECK-DAG: OpDecorate %[[#GET_NUM_GROUPS]] Constant
+
+; CHECK-NOT: DAG-FENCE
+
+;; Types, Constants and Variables:
+; CHECK-DAG: %[[#BOOL:]] = OpTypeBool
+; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#VEC:]] = OpTypeVector %[[#I64]] 3
+; CHECK-DAG: %[[#PTR:]] = OpTypePointer Input %[[#VEC]]
+; CHECK-DAG: %[[#FN:]] = OpTypeFunction %[[#I64]] %[[#I32]]
+; CHECK-DAG: %[[#GET_NUM_GROUPS]] = OpVariable %[[#PTR]] Input
+; CHECK-DAG: %[[#ONE:]] = OpConstant %[[#I64]] 1
+; CHECK-DAG: %[[#THREE:]] = OpConstant %[[#I32]] 3
+
+;; Functions:
+; CHECK:     OpFunction %[[#I64]] None %[[#FN]]
+; CHECK:     %[[#DIM:]] = OpFunctionParameter %[[#I32]]
+
+;; get_num_groups(0): OpLoad + OpCompositeExtract.
+; CHECK:     %[[#TMP1:]] = OpLoad %[[#VEC]] %[[#GET_NUM_GROUPS]]
+; CHECK:     %[[#X:]] = OpCompositeExtract %[[#I64]] %[[#TMP1]] 0
+
+;; get_num_groups(5): OpConstant of one.
+; CHECK:     OpIAdd %[[#I64]] %[[#X]] %[[#ONE]]
+
+;; get_num_groups(dim): Implementation using OpSelect.
+; CHECK-DAG: %[[#TMP2:]] = OpLoad %[[#VEC]] %[[#GET_NUM_GROUPS]]
+; CHECK-DAG: %[[#TMP3:]] = OpVectorExtractDynamic %[[#I64]] %[[#TMP2]] %[[#DIM]]
+; CHECK-DAG: %[[#COND:]] = OpULessThan %[[#BOOL]] %[[#DIM]] %[[#THREE]]
+; CHECK:     %[[#UNKNOWN:]] = OpSelect %[[#I64]] %[[#COND]] %[[#TMP3]] %[[#ONE]]

@svenvh svenvh merged commit 61ab476 into llvm:main Feb 18, 2025
12 checks passed
@svenvh svenvh deleted the get_num_groups-range branch February 18, 2025 09:24
wldfngrs pushed a commit to wldfngrs/llvm-project that referenced this pull request Feb 19, 2025
The OpenCL C specification states that for out-of-range dimension
indices, `get_num_groups` must return 1 instead of 0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants