Skip to content

Commit 1d53bf4

Browse files
svenvhsys-ce-bb
authored andcommitted
Fix OpGroupNonUniformBroadcast version requirement (#2378)
undefinedFor SPIR-V 1.4 and earlier, the Id operand of OpGroupNonUniformBroadcast must come from a constant instruction. Ensure that any emitted SPIR-V module using a non-constant Id operand declares SPIR-V version 1.5. Bail out if the maximum SPIR-V version was restricted to < 1.5, to avoid producing invalid SPIR-V. Original commit: KhronosGroup/SPIRV-LLVM-Translator@64fe75e388dc3b7
1 parent 3d89fc6 commit 1d53bf4

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ class SPIRVInstTemplateBase : public SPIRVInstruction {
276276
} else
277277
SPIRVEntry::setWordCount(WC);
278278
Ops = TheOps;
279+
// The required SPIR-V version depends on the operands for some
280+
// instructions.
281+
updateModuleVersion();
279282
}
280283
void setWordCount(SPIRVWord TheWordCount) override {
281284
SPIRVEntry::setWordCount(TheWordCount);
@@ -295,6 +298,11 @@ class SPIRVInstTemplateBase : public SPIRVInstruction {
295298

296299
/// Get operand as value.
297300
/// If the operand is a literal, return it as a uint32 constant.
301+
const SPIRVValue *getOpValue(int I) const {
302+
return isOperandLiteral(I) ? Module->getLiteralAsConstant(Ops[I])
303+
: getValue(Ops[I]);
304+
}
305+
298306
SPIRVValue *getOpValue(int I) {
299307
return isOperandLiteral(I) ? Module->getLiteralAsConstant(Ops[I])
300308
: getValue(Ops[I]);
@@ -315,6 +323,10 @@ class SPIRVInstTemplateBase : public SPIRVInstruction {
315323
return Operands;
316324
}
317325

326+
virtual const SPIRVValue *getOperand(unsigned I) const {
327+
return getOpValue(I);
328+
}
329+
318330
virtual SPIRVValue *getOperand(unsigned I) {
319331
return getOpValue(I);
320332
}
@@ -2503,6 +2515,22 @@ class SPIRVGroupNonUniformBallotInst : public SPIRVInstTemplateBase {
25032515
SPIRVCapVec getRequiredCapability() const override {
25042516
return getVec(CapabilityGroupNonUniformBallot);
25052517
}
2518+
2519+
SPIRVWord getRequiredSPIRVVersion() const override {
2520+
switch (OpCode) {
2521+
case OpGroupNonUniformBroadcast: {
2522+
assert(Ops.size() == 3 && "Expecting (Execution, Value, Id) operands");
2523+
if (!isConstantOpCode(getOperand(2)->getOpCode())) {
2524+
// Before version 1.5, Id must come from a constant instruction.
2525+
return static_cast<SPIRVWord>(VersionNumber::SPIRV_1_5);
2526+
}
2527+
break;
2528+
}
2529+
default:
2530+
break;
2531+
}
2532+
return static_cast<SPIRVWord>(VersionNumber::SPIRV_1_3);
2533+
}
25062534
};
25072535

25082536
#define _SPIRV_OP(x, ...) \
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -triple spir-unknown-unknown -O1 -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header -emit-llvm-bc %s -o %t.bc
2+
// RUN: not llvm-spirv --spirv-max-version=1.4 %t.bc 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
3+
// RUN: llvm-spirv %t.bc -o %t.spv
4+
// RUN: spirv-val %t.spv
5+
// RUN: llvm-spirv -r %t.spv -o %t.rev.bc
6+
// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
7+
8+
// Before SPIR-V 1.5, the Id operand of OpGroupNonUniformBroadcast must come from a constant instruction.
9+
// CHECK-ERROR: RequiresVersion: Cannot fulfill SPIR-V version restriction:
10+
// CHECK-ERROR-NEXT: SPIR-V version was restricted to at most 1.4 (66560) but a construct from the input requires SPIR-V version 1.5 (66816) or above
11+
12+
// CHECK-LLVM-LABEL: @test
13+
// CHECK-LLVM: call spir_func i16 @_Z31sub_group_non_uniform_broadcasttj(i16 %a, i32 %id)
14+
15+
kernel void test(short a, uint id, global short *res) {
16+
res[0] = sub_group_non_uniform_broadcast(a, id);
17+
}

0 commit comments

Comments
 (0)