Skip to content

Commit d18a70f

Browse files
MrSidimssys-ce-bb
authored andcommitted
Fix BufferLocationINTEL decoration translation (#2335)
There was an assumption, that ptr.annotation encoding buffer_location should be used by load or store instructions. But there is no such restriction in the specification. Signed-off-by: Sidorov, Dmitry <dmitry.sidorov@intel.com> Original commit: KhronosGroup/SPIRV-LLVM-Translator@7a37ea920f730e0
1 parent f7b658f commit d18a70f

File tree

4 files changed

+121
-85
lines changed

4 files changed

+121
-85
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 15 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,65 +1262,6 @@ Value *SPIRVToLLVM::oclTransConstantPipeStorage(
12621262
GlobalValue::NotThreadLocal, SPIRAS_Global);
12631263
}
12641264

1265-
namespace {
1266-
1267-
// A pointer annotation may have been generated for the operand. If the operand
1268-
// is used further in IR, it should be replaced with the intrinsic call result.
1269-
// Otherwise, the generated pointer annotation call is left unused.
1270-
static void replaceOperandWithAnnotationIntrinsicCallResult(Function *F,
1271-
Value *&V) {
1272-
1273-
SPIRVDBG(spvdbgs() << "\n"
1274-
<< "-------- REPLACE --------" << '\n';)
1275-
SPIRVDBG(dbgs() << "value: " << *V << '\n');
1276-
1277-
Value *BaseValue = nullptr;
1278-
IntrinsicInst *CallResult = nullptr;
1279-
1280-
auto SearchPtrAnn = [=](Value *BV, IntrinsicInst *&CR) {
1281-
CR = nullptr;
1282-
for (auto *Use : BV->users()) {
1283-
if (auto *II = dyn_cast<IntrinsicInst>(Use)) {
1284-
if (II->getIntrinsicID() == Intrinsic::ptr_annotation &&
1285-
II->getType() == BV->getType())
1286-
CR = II;
1287-
}
1288-
}
1289-
return CR ? true : false;
1290-
};
1291-
1292-
if (SearchPtrAnn(V, CallResult)) {
1293-
BaseValue = V;
1294-
} else {
1295-
// scan def-use chain, skip bitcast and addrspacecast
1296-
// search for the closest floating ptr.annotation
1297-
auto *Inst = dyn_cast<Instruction>(V);
1298-
while (Inst && (isa<BitCastInst>(Inst) || isa<AddrSpaceCastInst>(Inst))) {
1299-
if ((Inst = dyn_cast<Instruction>(Inst->getOperand(0))) &&
1300-
SearchPtrAnn(Inst, CallResult)) {
1301-
BaseValue = Inst;
1302-
break;
1303-
}
1304-
}
1305-
}
1306-
1307-
// overwrite operand with intrinsic call result
1308-
if (CallResult) {
1309-
SPIRVDBG(dbgs() << "BaseValue: " << *BaseValue << '\n'
1310-
<< "CallResult: " << *CallResult << '\n');
1311-
DominatorTree DT(*F);
1312-
BaseValue->replaceUsesWithIf(CallResult, [&DT, &CallResult](Use &U) {
1313-
return DT.dominates(CallResult, U);
1314-
});
1315-
1316-
// overwrite V
1317-
if (V == BaseValue)
1318-
V = CallResult;
1319-
}
1320-
}
1321-
1322-
} // namespace
1323-
13241265
// Translate aliasing memory access masks for SPIRVLoad and SPIRVStore
13251266
// instructions. These masks are mapped on alias.scope and noalias
13261267
// metadata in LLVM. Translation of optional string operand isn't yet supported
@@ -1798,10 +1739,6 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
17981739
StoreInst *SI = nullptr;
17991740
auto *Src = transValue(BS->getSrc(), F, BB);
18001741
auto *Dst = transValue(BS->getDst(), F, BB);
1801-
// A ptr.annotation may have been generated for the source variable.
1802-
replaceOperandWithAnnotationIntrinsicCallResult(F, Src);
1803-
// A ptr.annotation may have been generated for the destination variable.
1804-
replaceOperandWithAnnotationIntrinsicCallResult(F, Dst);
18051742

18061743
bool isVolatile = BS->SPIRVMemoryAccess::isVolatile();
18071744
uint64_t AlignValue = BS->SPIRVMemoryAccess::getAlignment();
@@ -1818,8 +1755,6 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
18181755
case OpLoad: {
18191756
SPIRVLoad *BL = static_cast<SPIRVLoad *>(BV);
18201757
auto *V = transValue(BL->getSrc(), F, BB);
1821-
// A ptr.annotation may have been generated for the source variable.
1822-
replaceOperandWithAnnotationIntrinsicCallResult(F, V);
18231758

18241759
Type *Ty = transType(BL->getType());
18251760
LoadInst *LI = nullptr;
@@ -1847,14 +1782,8 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
18471782
bool IsVolatile = BC->SPIRVMemoryAccess::isVolatile();
18481783
IRBuilder<> Builder(BB);
18491784

1850-
// A ptr.annotation may have been generated for the destination variable.
1851-
replaceOperandWithAnnotationIntrinsicCallResult(F, Dst);
1852-
18531785
if (!CI) {
18541786
llvm::Value *Src = transValue(BC->getSource(), F, BB);
1855-
1856-
// A ptr.annotation may have been generated for the source variable.
1857-
replaceOperandWithAnnotationIntrinsicCallResult(F, Src);
18581787
CI = Builder.CreateMemCpy(Dst, Align, Src, Align, Size, IsVolatile);
18591788
}
18601789
if (isFuncNoUnwind())
@@ -2401,9 +2330,6 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
24012330
std::vector<Value *> Args = transValue(BC->getArgumentValues(), F, BB);
24022331
auto *Call = CallInst::Create(transFunction(BC->getFunction()), Args,
24032332
BC->getName(), BB);
2404-
for (auto *Arg : Args)
2405-
if (Arg->getType()->isPointerTy())
2406-
replaceOperandWithAnnotationIntrinsicCallResult(F, Arg);
24072333
setCallingConv(Call);
24082334
setAttrByCalledFunc(Call);
24092335
return mapValue(BV, Call);
@@ -3693,6 +3619,7 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
36933619
for (SPIRVWord I = 0; I < STS->getMemberCount(); ++I) {
36943620
std::vector<SmallString<256>> AnnotStrVec;
36953621
generateIntelFPGAAnnotationForStructMember(ST, I, AnnotStrVec);
3622+
CallInst *AnnotationCall = nullptr;
36963623
for (const auto &AnnotStr : AnnotStrVec) {
36973624
auto *GS = Builder.CreateGlobalStringPtr(AnnotStr);
36983625

@@ -3727,14 +3654,17 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
37273654
PtrAnnFirstArg->getName()),
37283655
Builder.CreateBitCast(GS, Int8PtrTyPrivate), UndefInt8Ptr,
37293656
UndefInt32, UndefInt8Ptr};
3730-
auto *PtrAnnotationCall = Builder.CreateCall(AnnotationFn, Args);
3731-
GEPOrUseMap[AL][I] = PtrAnnotationCall;
3657+
AnnotationCall = Builder.CreateCall(AnnotationFn, Args);
3658+
GEPOrUseMap[AL][I] = AnnotationCall;
37323659
}
3660+
if (AnnotationCall)
3661+
ValueMap[BV] = AnnotationCall;
37333662
}
37343663
}
37353664

37363665
std::vector<SmallString<256>> AnnotStrVec;
37373666
generateIntelFPGAAnnotation(BV, AnnotStrVec);
3667+
CallInst *AnnotationCall = nullptr;
37383668
for (const auto &AnnotStr : AnnotStrVec) {
37393669
Constant *GS = nullptr;
37403670
const auto StringAnnotStr = static_cast<std::string>(AnnotStr);
@@ -3746,8 +3676,12 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
37463676
AnnotationsMap.emplace(std::move(StringAnnotStr), GS);
37473677
}
37483678

3749-
Value *BaseInst =
3750-
AL ? Builder.CreateBitCast(V, Int8PtrTyPrivate, V->getName()) : Inst;
3679+
Value *BaseInst = nullptr;
3680+
if (AnnotationCall && !AnnotationCall->getType()->isVoidTy())
3681+
BaseInst = AnnotationCall;
3682+
else
3683+
BaseInst = AL ? Builder.CreateBitCast(V, Int8PtrTyPrivate, V->getName())
3684+
: Inst;
37513685

37523686
// Try to find alloca instruction for statically allocated variables.
37533687
// Alloca might be hidden by a couple of casts.
@@ -3766,8 +3700,10 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
37663700
llvm::Value *Args[] = {BaseInst,
37673701
Builder.CreateBitCast(GS, Int8PtrTyPrivate),
37683702
UndefInt8Ptr, UndefInt32, UndefInt8Ptr};
3769-
Builder.CreateCall(AnnotationFn, Args);
3703+
AnnotationCall = Builder.CreateCall(AnnotationFn, Args);
37703704
}
3705+
if (AnnotationCall && !AnnotationCall->getType()->isVoidTy())
3706+
ValueMap[BV] = AnnotationCall;
37713707
} else if (auto *GV = dyn_cast<GlobalVariable>(V)) {
37723708
std::vector<SmallString<256>> AnnotStrVec;
37733709
generateIntelFPGAAnnotation(BV, AnnotStrVec);

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3930,7 +3930,7 @@ bool checkMemUser(User *User) {
39303930
}
39313931
} // namespace
39323932

3933-
bool allowDecorateWithBufferLocationOrLatencyControlINTEL(IntrinsicInst *II) {
3933+
bool allowDecorateWithLatencyControlINTEL(IntrinsicInst *II) {
39343934
for (auto *Inst : II->users()) {
39353935
// if castInst, check Successors
39363936
if (auto *Cast = dyn_cast<CastInst>(Inst)) {
@@ -4560,8 +4560,8 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
45604560
// different LSU parameters.
45614561
addAnnotationDecorations(DecSubj, Decorations.MemoryAccessesVec);
45624562
addAnnotationDecorations(DecSubj, Decorations.CacheControlVec);
4563-
if (allowDecorateWithBufferLocationOrLatencyControlINTEL(II)) {
4564-
addAnnotationDecorations(DecSubj, Decorations.BufferLocationVec);
4563+
addAnnotationDecorations(DecSubj, Decorations.BufferLocationVec);
4564+
if (allowDecorateWithLatencyControlINTEL(II)) {
45654565
addAnnotationDecorations(DecSubj, Decorations.LatencyControlVec);
45664566
}
45674567
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_fpga_buffer_location -o %t.spv
3+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
4+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
5+
6+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
; CHECK-SPIRV: Decorate [[#Ptr1:]] BufferLocationINTEL 0
10+
; CHECK-SPIRV: Decorate [[#Ptr2:]] BufferLocationINTEL 0
11+
12+
; CHECK-SPIRV: Load [[#]] [[#Ptr1:]]
13+
; CHECK-SPIRV: ReturnValue [[#Ptr1]]
14+
15+
; CHECK-SPIRV: InBoundsPtrAccessChain [[#]] [[#Ptr2]]
16+
; CHECK-SPIRV: Bitcast [[#]] [[#Bitcast:]] [[#Ptr2]]
17+
; CHECK-SPIRV: ReturnValue [[#Bitcast]]
18+
19+
; CHECK-LLVM: %[[#Load:]] = load ptr addrspace(4)
20+
; CHECK-LLVM: %[[#Anno1:]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) %[[#Load]], ptr @0, ptr undef, i32 undef, ptr undef)
21+
; CHECK-LLVM: ret ptr addrspace(4) %[[#Anno1]]
22+
23+
; CHECK-LLVM: %[[#GEP:]] = getelementptr inbounds %struct.MyIP
24+
; CHECK-LLVM: %[[#Anno2:]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) %[[#GEP]]
25+
; CHECK-LLVM: %[[#Bitcast:]] = bitcast ptr addrspace(4) %[[#Anno2]] to ptr addrspace(4)
26+
; CHECK-LLVM: ret ptr addrspace(4) %[[#Bitcast]]
27+
28+
; ModuleID = 'test-sycl-spir64-unknown-unknown.bc'
29+
source_filename = "test.cpp"
30+
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"
31+
target triple = "spir64-unknown-unknown"
32+
33+
%struct.MyIP = type <{ ptr addrspace(4), i32, [4 x i8] }>
34+
35+
$_ZNK4MyIPclEv = comdat any
36+
37+
$_Z8annotateIiEPT_S1_ = comdat any
38+
39+
$_Z9annotate2IiEPT_S1_ = comdat any
40+
41+
@.str = private unnamed_addr addrspace(1) constant [16 x i8] c"sycl-properties\00", section "llvm.metadata"
42+
@.str.1 = private unnamed_addr addrspace(1) constant [9 x i8] c"test.cpp\00", section "llvm.metadata"
43+
@.str.2 = private unnamed_addr addrspace(1) constant [21 x i8] c"sycl-buffer-location\00", section "llvm.metadata"
44+
@.str.3 = private unnamed_addr addrspace(1) constant [2 x i8] c"0\00", section "llvm.metadata"
45+
@.args = private unnamed_addr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) @.str.2, ptr addrspace(1) @.str.3 }, section "llvm.metadata"
46+
@.str.4 = private unnamed_addr addrspace(1) constant [11 x i8] c"{5921:\220\22}\00", section "llvm.metadata"
47+
48+
; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
49+
define linkonce_odr dso_local spir_func void @_ZNK4MyIPclEv(ptr addrspace(4) %this) comdat align 2 !srcloc !8 {
50+
entry:
51+
%call1 = call spir_func noundef ptr addrspace(4) @_Z8annotateIiEPT_S1_(ptr addrspace(4) noundef %this)
52+
%call2 = call spir_func noundef ptr addrspace(4) @_Z9annotate2IiEPT_S1_(ptr addrspace(4) noundef %this)
53+
ret void
54+
}
55+
56+
; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
57+
define linkonce_odr dso_local spir_func noundef ptr addrspace(4) @_Z8annotateIiEPT_S1_(ptr addrspace(4) noundef %ptr) comdat !srcloc !9 {
58+
entry:
59+
%retval = alloca ptr addrspace(4), align 8
60+
%ptr.addr = alloca ptr addrspace(4), align 8
61+
%retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
62+
%ptr.addr.ascast = addrspacecast ptr %ptr.addr to ptr addrspace(4)
63+
store ptr addrspace(4) %ptr, ptr addrspace(4) %ptr.addr.ascast, align 8
64+
%0 = load ptr addrspace(4), ptr addrspace(4) %ptr.addr.ascast, align 8
65+
%1 = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %0, ptr addrspace(1) @.str.4, ptr addrspace(1) @.str.1, i32 25, ptr addrspace(1) null)
66+
ret ptr addrspace(4) %1
67+
}
68+
69+
; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
70+
define linkonce_odr dso_local spir_func noundef ptr addrspace(4) @_Z9annotate2IiEPT_S1_(ptr addrspace(4) noundef %ptr) comdat !srcloc !9 {
71+
entry:
72+
%retval = alloca ptr addrspace(4), align 8
73+
%ptr.addr = alloca ptr addrspace(4), align 8
74+
%retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
75+
%ptr.addr.ascast = addrspacecast ptr %ptr.addr to ptr addrspace(4)
76+
store ptr addrspace(4) %ptr, ptr addrspace(4) %ptr.addr.ascast, align 8
77+
%0 = load ptr addrspace(4), ptr addrspace(4) %ptr.addr.ascast, align 8
78+
%1 = getelementptr inbounds %struct.MyIP, ptr addrspace(4) %0, i32 0, i32 0
79+
%2 = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %1, ptr addrspace(1) @.str.4, ptr addrspace(1) @.str.1, i32 25, ptr addrspace(1) null)
80+
ret ptr addrspace(4) %2
81+
}
82+
83+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
84+
declare ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4), ptr addrspace(1), ptr addrspace(1), i32, ptr addrspace(1))
85+
86+
!llvm.module.flags = !{!0, !1}
87+
!opencl.spir.version = !{!2}
88+
!spirv.Source = !{!3}
89+
!llvm.ident = !{!4}
90+
91+
!0 = !{i32 1, !"wchar_size", i32 4}
92+
!1 = !{i32 7, !"frame-pointer", i32 2}
93+
!2 = !{i32 1, i32 2}
94+
!3 = !{i32 4, i32 100000}
95+
!4 = !{!"Intel(R) oneAPI DPC++/C++ Compiler 2024.2.0 (2024.x.0.YYYYMMDD)"}
96+
!5 = !{i32 717}
97+
!6 = !{i32 -1, i32 -1}
98+
!7 = !{}
99+
!8 = !{i32 1004}
100+
!9 = !{i32 563}

llvm-spirv/test/transcoding/multiple_user_semantic_on_struct.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ define dso_local noundef i32 @main() #0 {
108108
; CHECK-LLVM: %[[#GepMultiDec:]] = getelementptr inbounds %class.A, ptr %[[#ObjClassA]], i32 0, i32 1
109109
; CHECK-LLVM: %[[#PtrAnnMultiDec:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#GepMultiDec]], ptr @[[#Dec1]]
110110
; CHECK-LLVM: %[[#PtrAnn2MultiDec:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#PtrAnnMultiDec]], ptr @[[#Dec2]]
111-
; CHECK-LLVM: %[[#PtrAnn3MultiDec:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#PtrAnnMultiDec]], ptr @[[#Dec3]]
111+
; CHECK-LLVM: %[[#PtrAnn3MultiDec:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#PtrAnn2MultiDec]], ptr @[[#Dec3]]
112112
%15 = load i32, ptr %14, align 4
113-
; CHECK-LLVM: %[[#LoadMultiDec:]] = bitcast ptr %[[#PtrAnnMultiDec]] to ptr
113+
; CHECK-LLVM: %[[#LoadMultiDec:]] = bitcast ptr %[[#PtrAnn3MultiDec]] to ptr
114114
; CHECK-LLVM: %[[#LoadMultiDec2:]] = bitcast ptr %[[#LoadMultiDec]] to ptr
115115
; CHECK-LLVM: %[[#CallClassAMultiDec:]] = load i32, ptr %[[#LoadMultiDec2]], align 4
116116
call void @_Z3fooi(i32 noundef %15)
@@ -120,7 +120,7 @@ define dso_local noundef i32 @main() #0 {
120120
; CHECK-LLVM: %[[#PtrAnnClassAFieldB:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#GepClassAFieldB]], ptr @[[#StrAfieldB]]
121121
%18 = getelementptr inbounds %class.B, ptr %17, i32 0, i32 0
122122
%19 = call ptr @llvm.ptr.annotation.p0.p1(ptr %18, ptr addrspace(1) @.str.6, ptr addrspace(1) @.str.1, i32 5, ptr addrspace(1) null)
123-
; CHECK-LLVM: %[[#CastGepClassAFieldB:]] = bitcast ptr %[[#GepClassAFieldB]] to ptr
123+
; CHECK-LLVM: %[[#CastGepClassAFieldB:]] = bitcast ptr %[[#PtrAnnClassAFieldB]] to ptr
124124
; CHECK-LLVM: %[[#CastGepClassAFieldB2:]] = bitcast ptr %[[#CastGepClassAFieldB]] to ptr
125125
; CHECK-LLVM: %[[#GEPClassB:]] = getelementptr inbounds %class.B, ptr %[[#CastGepClassAFieldB2]], i32 0, i32 0
126126
; CHECK-LLVM: %[[#PtrAnnClassB:]] = call ptr @llvm.ptr.annotation{{.*}}(ptr %[[#GEPClassB]], ptr @[[#StrStructB]]

0 commit comments

Comments
 (0)