Skip to content

Commit 3770469

Browse files
authored
Fixing Intrinsic::ptr_annotation (#2235)
There is a fundamental misalignment between when translating llvm.ptr.annotation to SPIRV's OpMemberDecorate. llvm.ptr.annotation is applied onto a pointer. OpMemberDecorate is applied on a type, which means that all variables of this type will have this Decoration. This change fixes this misalignment by translating llvm.ptr.annotation to SPIRV's OpDecorate instead, which instead places the decoration onto the pointer.
1 parent ef0165a commit 3770469

File tree

9 files changed

+185
-288
lines changed

9 files changed

+185
-288
lines changed

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 24 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,8 @@ AnnotationDecorations tryParseAnnotationString(SPIRVModule *BM,
31533153

31543154
std::pair<StringRef, StringRef> Split = AnnotatedDecoration.split(':');
31553155
StringRef Name = Split.first, ValueStr = Split.second;
3156+
SPIRVDBG(spvdbgs() << "[tryParseAnnotationString]: AnnotationString: "
3157+
<< Name.str() << "\n");
31563158

31573159
unsigned DecorationKind = 0;
31583160
if (!Name.getAsInteger(10, DecorationKind)) {
@@ -4303,19 +4305,17 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
43034305
// i8* <ptr> is a pointer on a GV, which can carry optinal variadic
43044306
// clang::annotation attribute expression arguments.
43054307
case Intrinsic::ptr_annotation: {
4306-
// Strip all bitcast and addrspace casts from the pointer argument:
4307-
// llvm annotation intrinsic only takes i8*, so the original pointer
4308-
// probably had to loose its addrspace and its original type.
4309-
Value *AnnotSubj = II->getArgOperand(0);
4310-
while (isa<BitCastInst>(AnnotSubj) || isa<AddrSpaceCastInst>(AnnotSubj)) {
4311-
AnnotSubj = cast<CastInst>(AnnotSubj)->getOperand(0);
4308+
Value *AnnotSubj = nullptr;
4309+
if (auto *BI = dyn_cast<BitCastInst>(II->getArgOperand(0))) {
4310+
AnnotSubj = BI->getOperand(0);
4311+
} else {
4312+
AnnotSubj = II->getOperand(0);
43124313
}
43134314

43144315
std::string AnnotationString;
43154316
processAnnotationString(II, AnnotationString);
43164317
AnnotationDecorations Decorations =
43174318
tryParseAnnotationString(BM, AnnotationString);
4318-
43194319
// Translate FPGARegIntel annotations to OpFPGARegINTEL.
43204320
if (AnnotationString == kOCLBuiltinName::FPGARegIntel) {
43214321
auto *Ty = transScavengedType(II);
@@ -4325,76 +4325,26 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
43254325
return transValue(BI, BB);
43264326
}
43274327

4328-
// If the pointer is a GEP on a struct, then we have to emit a member
4329-
// decoration for the GEP-accessed struct, or a memory access decoration
4330-
// for the GEP itself. There may not be a GEP in this case if the access is
4331-
// to the first member of the struct; if so, attempt to get a struct type
4332-
// from an alloca instead.
4333-
SPIRVType *StructTy = nullptr;
4334-
[[maybe_unused]] SPIRVValue *ResPtr = nullptr;
4335-
[[maybe_unused]] SPIRVWord MemberNumber = 0;
4336-
if (auto *const GI = dyn_cast<GetElementPtrInst>(AnnotSubj)) {
4337-
if (auto *const STy = dyn_cast<StructType>(GI->getSourceElementType())) {
4338-
StructTy = transType(STy);
4339-
ResPtr = transValue(GI, BB);
4340-
MemberNumber = dyn_cast<ConstantInt>(GI->getOperand(2))->getZExtValue();
4341-
}
4342-
} else if (auto *const AI = dyn_cast<AllocaInst>(AnnotSubj)) {
4343-
if (auto *const STy = dyn_cast<StructType>(AI->getAllocatedType())) {
4344-
StructTy = transType(STy);
4345-
ResPtr = transValue(AI, BB);
4346-
MemberNumber = 0;
4347-
}
4348-
}
4349-
if (StructTy) {
4350-
4351-
// If we didn't find any IntelFPGA-specific decorations, let's add the
4352-
// whole annotation string as UserSemantic Decoration
4353-
if (Decorations.empty()) {
4354-
// TODO: Is there a way to detect that the annotation belongs solely
4355-
// to struct member memory atributes or struct member memory access
4356-
// controls? This would allow emitting just the necessary decoration.
4357-
StructTy->addMemberDecorate(new SPIRVMemberDecorateUserSemanticAttr(
4358-
StructTy, MemberNumber, AnnotationString.c_str()));
4359-
ResPtr->addDecorate(new SPIRVDecorateUserSemanticAttr(
4360-
ResPtr, AnnotationString.c_str()));
4361-
} else {
4362-
addAnnotationDecorationsForStructMember(
4363-
StructTy, MemberNumber, Decorations.MemoryAttributesVec);
4364-
// Apply the LSU parameter decoration to the pointer result of a GEP
4365-
// to the given struct member (InBoundsPtrAccessChain in SPIR-V).
4366-
// Decorating the member itself with a MemberDecoration is not feasible,
4367-
// because multiple accesses to the struct-held memory can require
4368-
// different LSU parameters.
4369-
addAnnotationDecorations(ResPtr, Decorations.MemoryAccessesVec);
4370-
if (allowDecorateWithBufferLocationOrLatencyControlINTEL(II)) {
4371-
addAnnotationDecorations(ResPtr, Decorations.BufferLocationVec);
4372-
addAnnotationDecorations(ResPtr, Decorations.LatencyControlVec);
4373-
}
4374-
}
4375-
II->replaceAllUsesWith(II->getOperand(0));
4328+
SPIRVValue *DecSubj = transValue(AnnotSubj, BB);
4329+
if (Decorations.empty()) {
4330+
DecSubj->addDecorate(
4331+
new SPIRVDecorateUserSemanticAttr(DecSubj, AnnotationString.c_str()));
43764332
} else {
4377-
// Memory accesses to a standalone pointer variable
4378-
auto *DecSubj = transValue(II->getArgOperand(0), BB);
4379-
if (Decorations.empty())
4380-
DecSubj->addDecorate(new SPIRVDecorateUserSemanticAttr(
4381-
DecSubj, AnnotationString.c_str()));
4382-
else {
4383-
// Apply the LSU parameter decoration to the pointer result of an
4384-
// instruction. Note it's the address to the accessed memory that's
4385-
// loaded from the original pointer variable, and not the value
4386-
// accessed by the latter.
4387-
addAnnotationDecorations(DecSubj, Decorations.MemoryAccessesVec);
4388-
if (allowDecorateWithBufferLocationOrLatencyControlINTEL(II)) {
4389-
addAnnotationDecorations(DecSubj, Decorations.BufferLocationVec);
4390-
addAnnotationDecorations(DecSubj, Decorations.LatencyControlVec);
4391-
}
4392-
4393-
addAnnotationDecorations(DecSubj, Decorations.CacheControlVec);
4333+
addAnnotationDecorations(DecSubj, Decorations.MemoryAttributesVec);
4334+
// Apply the LSU parameter decoration to the pointer result of a GEP
4335+
// to the given struct member (InBoundsPtrAccessChain in SPIR-V).
4336+
// Decorating the member itself with a MemberDecoration is not feasible,
4337+
// because multiple accesses to the struct-held memory can require
4338+
// different LSU parameters.
4339+
addAnnotationDecorations(DecSubj, Decorations.MemoryAccessesVec);
4340+
addAnnotationDecorations(DecSubj, Decorations.CacheControlVec);
4341+
if (allowDecorateWithBufferLocationOrLatencyControlINTEL(II)) {
4342+
addAnnotationDecorations(DecSubj, Decorations.BufferLocationVec);
4343+
addAnnotationDecorations(DecSubj, Decorations.LatencyControlVec);
43944344
}
4395-
II->replaceAllUsesWith(II->getOperand(0));
43964345
}
4397-
return nullptr;
4346+
II->replaceAllUsesWith(II->getOperand(0));
4347+
return DecSubj;
43984348
}
43994349
case Intrinsic::stacksave: {
44004350
if (BM->isAllowedToUseExtension(

test/extensions/INTEL/SPV_INTEL_fpga_memory_accesses/IntelFPGAMemoryAccesses.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,9 @@ entry:
204204
%15 = bitcast double addrspace(4)** %t to i8*
205205
call void @llvm.lifetime.start.p0i8(i64 8, i8* %15) #5
206206
; CHECK-LLVM: %[[FLOAT_FUNC_PARAM_LOAD:[[:alnum:].]+]] = load ptr addrspace(4), ptr %[[FLOAT_FUNC_PARAM]]
207-
; CHECK-LLVM: %[[BITCAST_FLOAT_TO_DOUBLE:[[:alnum:].]+]] = bitcast ptr addrspace(4) %[[FLOAT_FUNC_PARAM_LOAD]] to ptr addrspace(4)
208-
; CHECK-LLVM: %[[INTRINSIC_CALL:[[:alnum:].]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) %[[BITCAST_FLOAT_TO_DOUBLE]], ptr [[PARAM_3_CACHE_0]]
209-
; CHECK-LLVM: store ptr addrspace(4) %[[INTRINSIC_CALL]], ptr %[[DOUBLE_VAR]]
207+
; CHECK-LLVM: %[[INTRINSIC_CALL:[[:alnum:].]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) %[[FLOAT_FUNC_PARAM_LOAD]], ptr [[PARAM_3_CACHE_0]]
208+
; CHECK-LLVM: %[[BITCAST_FLOAT_TO_DOUBLE:[[:alnum:].]+]] = bitcast ptr addrspace(4) %[[INTRINSIC_CALL]] to ptr addrspace(4)
209+
; CHECK-LLVM: store ptr addrspace(4) %[[BITCAST_FLOAT_TO_DOUBLE]], ptr %[[DOUBLE_VAR]]
210210
%16 = load float addrspace(4)*, float addrspace(4)** %A.addr, align 8, !tbaa !5
211211
%17 = bitcast float addrspace(4)* %16 to double addrspace(4)*
212212
%18 = call double addrspace(4)* @llvm.ptr.annotation.p4f64(double addrspace(4)* %17, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.1, i32 0, i32 0), i32 0, i8* null) #6

test/extensions/INTEL/SPV_INTEL_fpga_memory_accesses/intel_fpga_lsu_optimized.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,38 +90,38 @@ entry:
9090
; CHECK-LLVM: [[PTR_i27:[%0-9a-z.]+]] = getelementptr inbounds i32, ptr addrspace(1) {{[%0-9a-z._]+}}, i64 {{[%0-9a-z.]+}}
9191
; CHECK-LLVM: [[PTR_i:[%0-9a-z.]+]] = getelementptr inbounds i32, ptr addrspace(1) {{[%0-9a-z._]+}}, i64 {{[%0-9a-z.]+}}
9292
; CHECK-LLVM: [[PTR_i27_AS_CAST:[%0-9a-z.]+]] = addrspacecast ptr addrspace(1) [[PTR_i27]] to ptr addrspace(4)
93-
; CHECK-LLVM: [[PTR_i27_BIT_CAST:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_i27_AS_CAST]] to ptr addrspace(4)
94-
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i27_BIT_CAST]], ptr [[PTR_i27_ANNOT_STR]]
93+
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i27_AS_CAST]], ptr [[PTR_i27_ANNOT_STR]]
9594
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL]] to ptr addrspace(4)
96-
; CHECK-LLVM: [[PTR_RESULT_LOAD:[%0-9a-z.]+]] = load i32, ptr addrspace(4) [[PTR_ANNOT_CALL_BC]]
95+
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC2:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL_BC]] to ptr addrspace(4)
96+
; CHECK-LLVM: [[PTR_RESULT_LOAD:[%0-9a-z.]+]] = load i32, ptr addrspace(4) [[PTR_ANNOT_CALL_BC2]]
9797
%add.ptr.i15.i = getelementptr inbounds i32, i32 addrspace(1)* %add.ptr.i27, i64 1
9898
%7 = addrspacecast i32 addrspace(1)* %add.ptr.i15.i to i32 addrspace(4)*
9999
%8 = tail call dereferenceable(4) i32 addrspace(4)* @llvm.ptr.annotation.p4i32(i32 addrspace(4)* %7, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.1, i64 0, i64 0), i32 0, i8* null) #2
100100
%9 = load i32, i32 addrspace(4)* %8, align 4, !tbaa !9
101101
; CHECK-LLVM: [[PTR_i15_i:[%0-9a-z.]+]] = getelementptr inbounds i32, ptr addrspace(1) {{[%0-9a-z._]+}}, i64 {{[%0-9a-z.]+}}
102102
; CHECK-LLVM: [[PTR_i15_i_AS_CAST:[%0-9a-z.]+]] = addrspacecast ptr addrspace(1) [[PTR_i15_i]] to ptr addrspace(4)
103-
; CHECK-LLVM: [[PTR_i15_i_BIT_CAST:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_i15_i_AS_CAST]] to ptr addrspace(4)
104-
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i15_i_BIT_CAST]], ptr [[PTR_i15_i_ANNOT_STR]]
103+
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i15_i_AS_CAST]], ptr [[PTR_i15_i_ANNOT_STR]]
105104
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL]] to ptr addrspace(4)
106-
; CHECK-LLVM: [[PTR_RESULT_LOAD_1:[%0-9a-z.]+]] = load i32, ptr addrspace(4) [[PTR_ANNOT_CALL_BC]]
105+
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC2:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL_BC]] to ptr addrspace(4)
106+
; CHECK-LLVM: [[PTR_RESULT_LOAD_1:[%0-9a-z.]+]] = load i32, ptr addrspace(4) [[PTR_ANNOT_CALL_BC2]]
107107
%10 = addrspacecast i32 addrspace(1)* %add.ptr.i to i32 addrspace(4)*
108108
%11 = tail call i32 addrspace(4)* @llvm.ptr.annotation.p4i32(i32 addrspace(4)* %10, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.1, i64 0, i64 0), i32 0, i8* null) #2
109109
store i32 %6, i32 addrspace(4)* %11, align 4, !tbaa !9
110110
; CHECK-LLVM: [[PTR_i_AS_CAST:[%0-9a-z.]+]] = addrspacecast ptr addrspace(1) [[PTR_i]] to ptr addrspace(4)
111-
; CHECK-LLVM: [[PTR_i_BIT_CAST:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_i_AS_CAST]] to ptr addrspace(4)
112-
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i_BIT_CAST]], ptr [[PTR_i_ANNOT_STR]]
111+
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i_AS_CAST]], ptr [[PTR_i_ANNOT_STR]]
113112
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL]] to ptr addrspace(4)
114-
; CHECK-LLVM: store i32 [[PTR_RESULT_LOAD]], ptr addrspace(4) [[PTR_ANNOT_CALL_BC]]
113+
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC2:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL_BC]] to ptr addrspace(4)
114+
; CHECK-LLVM: store i32 [[PTR_RESULT_LOAD]], ptr addrspace(4) [[PTR_ANNOT_CALL_BC2]]
115115
%add.ptr.i.i = getelementptr inbounds i32, i32 addrspace(1)* %add.ptr.i, i64 1
116116
%12 = addrspacecast i32 addrspace(1)* %add.ptr.i.i to i32 addrspace(4)*
117117
%13 = tail call i32 addrspace(4)* @llvm.ptr.annotation.p4i32(i32 addrspace(4)* %12, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.4, i64 0, i64 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.1, i64 0, i64 0), i32 0, i8* null) #2
118118
store i32 %9, i32 addrspace(4)* %13, align 4, !tbaa !9
119119
; CHECK-LLVM: [[PTR_i_i:[%0-9a-z.]+]] = getelementptr inbounds i32, ptr addrspace(1) {{[%0-9a-z._]+}}, i64 {{[%0-9a-z.]+}}
120120
; CHECK-LLVM: [[PTR_i_i_AS_CAST:[%0-9a-z.]+]] = addrspacecast ptr addrspace(1) [[PTR_i_i]] to ptr addrspace(4)
121-
; CHECK-LLVM: [[PTR_i_i_BIT_CAST:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_i_i_AS_CAST]] to ptr addrspace(4)
122-
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i_i_BIT_CAST]], ptr [[PTR_i_i_ANNOT_STR]]
121+
; CHECK-LLVM: [[PTR_ANNOT_CALL:[%0-9a-z.]+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p0(ptr addrspace(4) [[PTR_i_i_AS_CAST]], ptr [[PTR_i_i_ANNOT_STR]]
123122
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL]] to ptr addrspace(4)
124-
; CHECK-LLVM: store i32 [[PTR_RESULT_LOAD_1]], ptr addrspace(4) [[PTR_ANNOT_CALL_BC]]
123+
; CHECK-LLVM: [[PTR_ANNOT_CALL_BC2:[%0-9a-z.]+]] = bitcast ptr addrspace(4) [[PTR_ANNOT_CALL_BC]] to ptr addrspace(4)
124+
; CHECK-LLVM: store i32 [[PTR_RESULT_LOAD_1]], ptr addrspace(4) [[PTR_ANNOT_CALL_BC2]]
125125
ret void
126126
}
127127

0 commit comments

Comments
 (0)