Skip to content

Commit 0a39b96

Browse files
authored
[Backport to 16] [SPIR-V 1.2] SPIRVReader: Add AlignmentId support (#2869) (#2887)
If there is no `OpDecorate .. Alignment` in the input, see if there is an `OpDecorateId .. AlignmentId` and take the alignment from the referenced constant instead. Once `AlignmentId` has been translated to LLVM IR, it is indistinguishable from an (non-ID) `Alignment` decoration. (cherry picked from commit da1731b)
1 parent 0fbe7f6 commit 0a39b96

File tree

3 files changed

+73
-11
lines changed

3 files changed

+73
-11
lines changed

lib/SPIRV/SPIRVReader.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,29 @@ Value *SPIRVToLLVM::mapFunction(SPIRVFunction *BF, Function *F) {
285285
return F;
286286
}
287287

288+
std::optional<uint64_t> SPIRVToLLVM::transIdAsConstant(SPIRVId Id) {
289+
auto *V = BM->get<SPIRVValue>(Id);
290+
const auto *ConstValue =
291+
dyn_cast<ConstantInt>(transValue(V, nullptr, nullptr));
292+
if (!ConstValue)
293+
return {};
294+
return ConstValue->getZExtValue();
295+
}
296+
297+
std::optional<uint64_t> SPIRVToLLVM::getAlignment(SPIRVValue *V) {
298+
SPIRVWord AlignmentBytes = 0;
299+
if (V->hasAlignment(&AlignmentBytes)) {
300+
return AlignmentBytes;
301+
}
302+
303+
// If there was no Alignment decoration, look for AlignmentId instead.
304+
SPIRVId AlignId;
305+
if (V->hasDecorateId(DecorationAlignmentId, 0, &AlignId)) {
306+
return transIdAsConstant(AlignId);
307+
}
308+
return {};
309+
}
310+
288311
Type *SPIRVToLLVM::transFPType(SPIRVType *T) {
289312
switch (T->getFloatBitWidth()) {
290313
case 16:
@@ -3011,9 +3034,9 @@ void SPIRVToLLVM::transFunctionAttrs(SPIRVFunction *BF, Function *F) {
30113034
SPIRVWord MaxOffset = 0;
30123035
if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset))
30133036
Builder.addDereferenceableAttr(MaxOffset);
3014-
SPIRVWord AlignmentBytes = 0;
3015-
if (BA->hasAlignment(&AlignmentBytes))
3016-
Builder.addAlignmentAttr(AlignmentBytes);
3037+
if (auto Alignment = getAlignment(BA)) {
3038+
Builder.addAlignmentAttr(*Alignment);
3039+
}
30173040
I->addAttrs(Builder);
30183041
}
30193042
BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) {
@@ -4691,16 +4714,14 @@ bool SPIRVToLLVM::transFPGAFunctionMetadata(SPIRVFunction *BF, Function *F) {
46914714
}
46924715

46934716
bool SPIRVToLLVM::transAlign(SPIRVValue *BV, Value *V) {
4694-
if (auto AL = dyn_cast<AllocaInst>(V)) {
4695-
SPIRVWord Align = 0;
4696-
if (BV->hasAlignment(&Align))
4697-
AL->setAlignment(llvm::Align(Align));
4717+
if (auto *AL = dyn_cast<AllocaInst>(V)) {
4718+
if (auto Align = getAlignment(BV))
4719+
AL->setAlignment(llvm::Align(*Align));
46984720
return true;
46994721
}
4700-
if (auto GV = dyn_cast<GlobalVariable>(V)) {
4701-
SPIRVWord Align = 0;
4702-
if (BV->hasAlignment(&Align))
4703-
GV->setAlignment(MaybeAlign(Align));
4722+
if (auto *GV = dyn_cast<GlobalVariable>(V)) {
4723+
if (auto Align = getAlignment(BV))
4724+
GV->setAlignment(MaybeAlign(*Align));
47044725
return true;
47054726
}
47064727
return true;

lib/SPIRV/SPIRVReader.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ class SPIRVToLLVM : private BuiltinCallHelper {
214214

215215
bool isDirectlyTranslatedToOCL(Op OpCode) const;
216216
MDString *transOCLKernelArgTypeName(SPIRVFunctionParameter *);
217+
218+
// Attempt to translate Id as a (specialization) constant.
219+
std::optional<uint64_t> transIdAsConstant(SPIRVId Id);
220+
221+
// Return the value of an Alignment or AlignmentId decoration for V.
222+
std::optional<uint64_t> getAlignment(SPIRVValue *V);
223+
217224
Value *mapFunction(SPIRVFunction *BF, Function *F);
218225
Value *getTranslatedValue(SPIRVValue *BV);
219226
IntrinsicInst *getLifetimeStartIntrinsic(Instruction *I);

test/AlignmentId.spvasm

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; REQUIRES: spirv-as
2+
3+
; RUN: spirv-as %s --target-env spv1.2 -o %t.spv
4+
; RUN: spirv-val %t.spv
5+
; RUN: llvm-spirv -r -o %t.rev.bc %t.spv
6+
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s
7+
8+
OpCapability Addresses
9+
OpCapability Linkage
10+
OpCapability Kernel
11+
OpMemoryModel Physical64 OpenCL
12+
OpEntryPoint Kernel %fn "testAlignmentId"
13+
OpName %p "p"
14+
OpDecorate %x LinkageAttributes "x" Export
15+
OpDecorateId %x AlignmentId %al
16+
OpDecorateId %p AlignmentId %al_spec
17+
%void = OpTypeVoid
18+
%uint = OpTypeInt 32 0
19+
%ptr = OpTypePointer CrossWorkgroup %uint
20+
%fnTy = OpTypeFunction %void %ptr
21+
%al = OpConstant %uint 16
22+
%al_spec = OpSpecConstantOp %uint IAdd %al %al
23+
%uint_42 = OpConstant %uint 42
24+
; Verify alignment of variable.
25+
; CHECK: @x = addrspace(1) global i32 42, align 16
26+
%x = OpVariable %ptr CrossWorkgroup %uint_42
27+
28+
%fn = OpFunction %void None %fnTy
29+
; Verify alignment of function parameter.
30+
; CHECK: define spir_kernel void @testAlignmentId(ptr addrspace(1) align 32 %p)
31+
%p = OpFunctionParameter %ptr
32+
%entry = OpLabel
33+
OpReturn
34+
OpFunctionEnd

0 commit comments

Comments
 (0)