Skip to content

Commit

Permalink
Support UserSemantic decoration on functions (#666)
Browse files Browse the repository at this point in the history
Added support of SPIR-V -> LLVM IR translation for UserSemantic
decoration applied to functions. Having that decoration on functions
is against SPIR-V spec, but it is useful for prototyping different features:
you can easily propagate custom annotation string through SPIR-V
to see if your idea works or not without adding new code
to the translator

Signed-off-by: amochalo <anastasiya.mochalova@intel.com>
  • Loading branch information
MochalovaAn authored and vladimirlaz committed Aug 17, 2020
1 parent ed7d999 commit 2800b4b
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
36 changes: 35 additions & 1 deletion llvm-spirv/lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3244,7 +3244,6 @@ bool SPIRVToLLVM::translate() {
if (BV->getStorageClass() != StorageClassFunction)
transValue(BV, nullptr, nullptr);
}
transGlobalAnnotations();

// Compile unit might be needed during translation of debug intrinsics.
for (SPIRVExtInst *EI : BM->getDebugInstVec()) {
Expand All @@ -3263,8 +3262,11 @@ bool SPIRVToLLVM::translate() {

for (unsigned I = 0, E = BM->getNumFunctions(); I != E; ++I) {
transFunction(BM->getFunction(I));
transUserSemantic(BM->getFunction(I));
}

transGlobalAnnotations();

if (!transMetadata())
return false;
if (!transFPContractMetadata())
Expand Down Expand Up @@ -3528,6 +3530,38 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
}
}

// Having UserSemantic decoration on Function is against the spec, but we allow
// this for various purposes (like prototyping new features when we need to
// attach some information on function and propagate that through SPIR-V and
// ect.)
void SPIRVToLLVM::transUserSemantic(SPIRV::SPIRVFunction *Fun) {
auto TransFun = transFunction(Fun);
for (auto UsSem : Fun->getDecorationStringLiteral(DecorationUserSemantic)) {
auto V = cast<Value>(TransFun);
Constant *StrConstant =
ConstantDataArray::getString(*Context, StringRef(UsSem));
auto *GS = new GlobalVariable(
*TransFun->getParent(), StrConstant->getType(),
/*IsConstant*/ true, GlobalValue::PrivateLinkage, StrConstant, "");

GS->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GS->setSection("llvm.metadata");

Type *ResType = PointerType::getInt8PtrTy(
V->getContext(), V->getType()->getPointerAddressSpace());
Constant *C =
ConstantExpr::getPointerBitCastOrAddrSpaceCast(TransFun, ResType);

Type *Int8PtrTyPrivate = Type::getInt8PtrTy(*Context, SPIRAS_Private);
IntegerType *Int32Ty = Type::getInt32Ty(*Context);

llvm::Constant *Fields[4] = {
C, ConstantExpr::getBitCast(GS, Int8PtrTyPrivate),
UndefValue::get(Int8PtrTyPrivate), UndefValue::get(Int32Ty)};
GlobalAnnotations.push_back(ConstantStruct::getAnon(Fields));
}
}

void SPIRVToLLVM::transGlobalAnnotations() {
if (!GlobalAnnotations.empty()) {
Constant *Array =
Expand Down
1 change: 1 addition & 0 deletions llvm-spirv/lib/SPIRV/SPIRVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ class SPIRVToLLVM {
Instruction *transOCLAllAny(SPIRVInstruction *BI, BasicBlock *BB);
Instruction *transOCLRelational(SPIRVInstruction *BI, BasicBlock *BB);

void transUserSemantic(SPIRV::SPIRVFunction *Fun);
void transGlobalAnnotations();
void transIntelFPGADecorations(SPIRVValue *BV, Value *V);
}; // class SPIRVToLLVM
Expand Down
37 changes: 37 additions & 0 deletions llvm-spirv/test/transcoding/GlobalFunAnnotate.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
;RUN: llvm-as %s -o %t.bc
;RUN: llvm-spirv %t.bc -o %t.spv
;RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
;RUN: llvm-spirv -r %t.spv -o %t.rev.bc
;RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM

;CHECK-SPIRV: Decorate {{[0-9]+}} UserSemantic "annotation_on_function"

;CHECK-LLVM: @0 = private unnamed_addr constant [23 x i8] c"annotation_on_function\00", section "llvm.metadata"
;CHECK-LLVM: @llvm.global.annotations = appending global [1 x { i8*, i8*, i8*, i32 }] [{ i8*, i8*, i8*, i32 } { i8* bitcast (void ()* @foo to i8*), i8* getelementptr inbounds ([23 x i8], [23 x i8]* @0, i32 0, i32 0), i8* undef, i32 undef }], section "llvm.metadata"

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
target triple = "spir64-unknown-linux-sycldevice"

@.str = private unnamed_addr constant [23 x i8] c"annotation_on_function\00", section "llvm.metadata"
@.str.1 = private unnamed_addr constant [6 x i8] c"an.cl\00", section "llvm.metadata"
@llvm.global.annotations = appending global [1 x { i8*, i8*, i8*, i32 }] [{ i8*, i8*, i8*, i32 } { i8* bitcast (void ()* @foo to i8*), i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0), i32 2 }], section "llvm.metadata"

; Function Attrs: convergent norecurse nounwind
define dso_local spir_func void @foo() #0 {
entry:
ret void
}

attributes #0 = { convergent norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!opencl.ocl.version = !{!1}
!opencl.spir.version = !{!2, !2}
!spirv.Source = !{!3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, i32 0}
!2 = !{i32 1, i32 2}
!3 = !{i32 4, i32 100000}
!4 = !{!"clang version 12.0.0 (https://github.com/c199914007/llvm.git 074e97d48896b959dfc832e2f1dd806796cde390)"}

0 comments on commit 2800b4b

Please sign in to comment.