Skip to content

Commit

Permalink
[Backport to 15] [SPIR-V 1.2] SPIRVReader: Add AlignmentId support (K…
Browse files Browse the repository at this point in the history
…hronosGroup#2869) (KhronosGroup#2886)

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)
  • Loading branch information
svenvh authored Nov 28, 2024
1 parent 426abe8 commit 556ffe7
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
43 changes: 32 additions & 11 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,29 @@ Value *SPIRVToLLVM::mapFunction(SPIRVFunction *BF, Function *F) {
return F;
}

llvm::Optional<uint64_t> SPIRVToLLVM::transIdAsConstant(SPIRVId Id) {
auto *V = BM->get<SPIRVValue>(Id);
const auto *ConstValue =
dyn_cast<ConstantInt>(transValue(V, nullptr, nullptr));
if (!ConstValue)
return {};
return ConstValue->getZExtValue();
}

llvm::Optional<uint64_t> SPIRVToLLVM::getAlignment(SPIRVValue *V) {
SPIRVWord AlignmentBytes = 0;
if (V->hasAlignment(&AlignmentBytes)) {
return AlignmentBytes;
}

// If there was no Alignment decoration, look for AlignmentId instead.
SPIRVId AlignId;
if (V->hasDecorateId(DecorationAlignmentId, 0, &AlignId)) {
return transIdAsConstant(AlignId);
}
return {};
}

Type *SPIRVToLLVM::transFPType(SPIRVType *T) {
switch (T->getFloatBitWidth()) {
case 16:
Expand Down Expand Up @@ -3114,9 +3137,9 @@ void SPIRVToLLVM::transFunctionAttrs(SPIRVFunction *BF, Function *F) {
SPIRVWord MaxOffset = 0;
if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset))
Builder.addDereferenceableAttr(MaxOffset);
SPIRVWord AlignmentBytes = 0;
if (BA->hasAlignment(&AlignmentBytes))
Builder.addAlignmentAttr(AlignmentBytes);
if (auto Alignment = getAlignment(BA)) {
Builder.addAlignmentAttr(*Alignment);
}
I->addAttrs(Builder);
}
BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) {
Expand Down Expand Up @@ -4757,16 +4780,14 @@ bool SPIRVToLLVM::transFPGAFunctionMetadata(SPIRVFunction *BF, Function *F) {
}

bool SPIRVToLLVM::transAlign(SPIRVValue *BV, Value *V) {
if (auto AL = dyn_cast<AllocaInst>(V)) {
SPIRVWord Align = 0;
if (BV->hasAlignment(&Align))
AL->setAlignment(llvm::Align(Align));
if (auto *AL = dyn_cast<AllocaInst>(V)) {
if (auto Align = getAlignment(BV))
AL->setAlignment(llvm::Align(*Align));
return true;
}
if (auto GV = dyn_cast<GlobalVariable>(V)) {
SPIRVWord Align = 0;
if (BV->hasAlignment(&Align))
GV->setAlignment(MaybeAlign(Align));
if (auto *GV = dyn_cast<GlobalVariable>(V)) {
if (auto Align = getAlignment(BV))
GV->setAlignment(MaybeAlign(*Align));
return true;
}
return true;
Expand Down
7 changes: 7 additions & 0 deletions lib/SPIRV/SPIRVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ class SPIRVToLLVM {

bool isDirectlyTranslatedToOCL(Op OpCode) const;
MDString *transOCLKernelArgTypeName(SPIRVFunctionParameter *);

// Attempt to translate Id as a (specialization) constant.
llvm::Optional<uint64_t> transIdAsConstant(SPIRVId Id);

// Return the value of an Alignment or AlignmentId decoration for V.
llvm::Optional<uint64_t> getAlignment(SPIRVValue *V);

Value *mapFunction(SPIRVFunction *BF, Function *F);
Value *getTranslatedValue(SPIRVValue *BV);
IntrinsicInst *getLifetimeStartIntrinsic(Instruction *I);
Expand Down
34 changes: 34 additions & 0 deletions test/AlignmentId.spvasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; REQUIRES: spirv-as

; RUN: spirv-as %s --target-env spv1.2 -o %t.spv
; RUN: spirv-val %t.spv
; RUN: llvm-spirv -r -o %t.rev.bc %t.spv
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s

OpCapability Addresses
OpCapability Linkage
OpCapability Kernel
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %fn "testAlignmentId"
OpName %p "p"
OpDecorate %x LinkageAttributes "x" Export
OpDecorateId %x AlignmentId %al
OpDecorateId %p AlignmentId %al_spec
%void = OpTypeVoid
%uint = OpTypeInt 32 0
%ptr = OpTypePointer CrossWorkgroup %uint
%fnTy = OpTypeFunction %void %ptr
%al = OpConstant %uint 16
%al_spec = OpSpecConstantOp %uint IAdd %al %al
%uint_42 = OpConstant %uint 42
; Verify alignment of variable.
; CHECK: @x = addrspace(1) global i32 42, align 16
%x = OpVariable %ptr CrossWorkgroup %uint_42

%fn = OpFunction %void None %fnTy
; Verify alignment of function parameter.
; CHECK: define spir_kernel void @testAlignmentId(i32 addrspace(1)* align 32 %p)
%p = OpFunctionParameter %ptr
%entry = OpLabel
OpReturn
OpFunctionEnd

0 comments on commit 556ffe7

Please sign in to comment.