Skip to content

Commit 61ab476

Browse files
authored
[SPIR-V] Fix out-of-range value for NumWorkgroups builtin (#127198)
The OpenCL C specification states that for out-of-range dimension indices, `get_num_groups` must return 1 instead of 0.
1 parent b805410 commit 61ab476

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,7 @@ static bool generateGetQueryInst(const SPIRV::IncomingCall *Call,
17791779
SPIRV::BuiltIn::BuiltIn Value =
17801780
SPIRV::lookupGetBuiltin(Call->Builtin->Name, Call->Builtin->Set)->Value;
17811781
uint64_t IsDefault = (Value == SPIRV::BuiltIn::GlobalSize ||
1782+
Value == SPIRV::BuiltIn::NumWorkgroups ||
17821783
Value == SPIRV::BuiltIn::WorkgroupSize ||
17831784
Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
17841785
return genWorkgroupQuery(Call, MIRBuilder, GR, Value, IsDefault ? 1 : 0);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
3+
;; The set of valid inputs for get_num_groups depends on the runtime NDRange,
4+
;; but inputs outside of [0, 2] always return 1.
5+
;; Here we assume Itanium mangling for function name.
6+
declare i64 @_Z14get_num_groupsj(i32)
7+
8+
define i64 @foo(i32 %dim) {
9+
%x = call i64 @_Z14get_num_groupsj(i32 0)
10+
%y = call i64 @_Z14get_num_groupsj(i32 5)
11+
%acc = add i64 %x, %y
12+
%unknown = call i64 @_Z14get_num_groupsj(i32 %dim)
13+
%ret = add i64 %acc, %unknown
14+
ret i64 %ret
15+
}
16+
17+
;; Capabilities:
18+
; CHECK-DAG: OpCapability Kernel
19+
; CHECK-DAG: OpCapability Int64
20+
21+
; CHECK-NOT: DAG-FENCE
22+
23+
;; Decorations:
24+
; CHECK-DAG: OpDecorate %[[#GET_NUM_GROUPS:]] BuiltIn NumWorkgroups
25+
; CHECK-DAG: OpDecorate %[[#GET_NUM_GROUPS]] Constant
26+
27+
; CHECK-NOT: DAG-FENCE
28+
29+
;; Types, Constants and Variables:
30+
; CHECK-DAG: %[[#BOOL:]] = OpTypeBool
31+
; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0
32+
; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0
33+
; CHECK-DAG: %[[#VEC:]] = OpTypeVector %[[#I64]] 3
34+
; CHECK-DAG: %[[#PTR:]] = OpTypePointer Input %[[#VEC]]
35+
; CHECK-DAG: %[[#FN:]] = OpTypeFunction %[[#I64]] %[[#I32]]
36+
; CHECK-DAG: %[[#GET_NUM_GROUPS]] = OpVariable %[[#PTR]] Input
37+
; CHECK-DAG: %[[#ONE:]] = OpConstant %[[#I64]] 1
38+
; CHECK-DAG: %[[#THREE:]] = OpConstant %[[#I32]] 3
39+
40+
;; Functions:
41+
; CHECK: OpFunction %[[#I64]] None %[[#FN]]
42+
; CHECK: %[[#DIM:]] = OpFunctionParameter %[[#I32]]
43+
44+
;; get_num_groups(0): OpLoad + OpCompositeExtract.
45+
; CHECK: %[[#TMP1:]] = OpLoad %[[#VEC]] %[[#GET_NUM_GROUPS]]
46+
; CHECK: %[[#X:]] = OpCompositeExtract %[[#I64]] %[[#TMP1]] 0
47+
48+
;; get_num_groups(5): OpConstant of one.
49+
; CHECK: OpIAdd %[[#I64]] %[[#X]] %[[#ONE]]
50+
51+
;; get_num_groups(dim): Implementation using OpSelect.
52+
; CHECK-DAG: %[[#TMP2:]] = OpLoad %[[#VEC]] %[[#GET_NUM_GROUPS]]
53+
; CHECK-DAG: %[[#TMP3:]] = OpVectorExtractDynamic %[[#I64]] %[[#TMP2]] %[[#DIM]]
54+
; CHECK-DAG: %[[#COND:]] = OpULessThan %[[#BOOL]] %[[#DIM]] %[[#THREE]]
55+
; CHECK: %[[#UNKNOWN:]] = OpSelect %[[#I64]] %[[#COND]] %[[#TMP3]] %[[#ONE]]

0 commit comments

Comments
 (0)