Skip to content

Commit 308daff

Browse files
authored
Fix reverse translation of ptr.annotation for multiple UserSemantic decorations (#1723)
It was found that the decorated variables (results of ptr.annotation intrinsic) are not used in further instructions unlike the input source. The issue is present for the reverse translation of multiple UserSemantic decorations. This change fixes the reverse translation of multiple ptr.annotation intrinsics on the same class field. With this, the result of intrinsic is not lost and actually reused in further intrinsics and instructions.
1 parent adb62c1 commit 308daff

File tree

5 files changed

+237
-13
lines changed

5 files changed

+237
-13
lines changed

lib/SPIRV/SPIRVReader.cpp

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,28 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
20902090
Index.insert(Index.begin(), getInt32(M, 0));
20912091
auto IsInbound = AC->isInBounds();
20922092
Value *V = nullptr;
2093+
2094+
if (GEPOrUseMap.count(Base)) {
2095+
auto IdxToInstMap = GEPOrUseMap[Base];
2096+
auto Idx = AC->getIndices();
2097+
2098+
// In transIntelFPGADecorations we generated GEPs only for the fields of
2099+
// structure, meaning that GEP to `0` accesses the Structure itself, and
2100+
// the second `Id` is a Key in the map.
2101+
if (Idx.size() == 2) {
2102+
unsigned Idx1 = static_cast<ConstantInt *>(getTranslatedValue(Idx[0]))
2103+
->getZExtValue();
2104+
if (Idx1 == 0) {
2105+
unsigned Idx2 = static_cast<ConstantInt *>(getTranslatedValue(Idx[1]))
2106+
->getZExtValue();
2107+
2108+
// If we already have the instruction in a map, use it.
2109+
if (IdxToInstMap.count(Idx2))
2110+
return mapValue(BV, IdxToInstMap[Idx2]);
2111+
}
2112+
}
2113+
}
2114+
20932115
if (BB) {
20942116
auto GEP =
20952117
GetElementPtrInst::Create(BaseTy, Base, Index, BV->getName(), BB);
@@ -3475,21 +3497,39 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
34753497
for (const auto &AnnotStr : AnnotStrVec) {
34763498
auto *GS = Builder.CreateGlobalStringPtr(AnnotStr);
34773499

3478-
auto *GEP = cast<GetElementPtrInst>(
3479-
Builder.CreateConstInBoundsGEP2_32(AllocatedTy, AL, 0, I));
3500+
Instruction *PtrAnnFirstArg = nullptr;
34803501

3481-
Type *IntTy = GEP->getResultElementType()->isIntegerTy()
3482-
? GEP->getType()
3483-
: Int8PtrTyPrivate;
3502+
if (GEPOrUseMap.count(AL)) {
3503+
auto IdxToInstMap = GEPOrUseMap[AL];
3504+
if (IdxToInstMap.count(I)) {
3505+
PtrAnnFirstArg = IdxToInstMap[I];
3506+
}
3507+
}
3508+
3509+
Type *IntTy = nullptr;
3510+
3511+
if (!PtrAnnFirstArg) {
3512+
GetElementPtrInst *GEP = cast<GetElementPtrInst>(
3513+
Builder.CreateConstInBoundsGEP2_32(AllocatedTy, AL, 0, I));
3514+
3515+
IntTy = GEP->getResultElementType()->isIntegerTy()
3516+
? GEP->getType()
3517+
: Int8PtrTyPrivate;
3518+
PtrAnnFirstArg = GEP;
3519+
} else {
3520+
IntTy = PtrAnnFirstArg->getType();
3521+
}
34843522

34853523
auto *AnnotationFn = llvm::Intrinsic::getDeclaration(
34863524
M, Intrinsic::ptr_annotation, {IntTy, Int8PtrTyPrivate});
34873525

34883526
llvm::Value *Args[] = {
3489-
Builder.CreateBitCast(GEP, IntTy, GEP->getName()),
3527+
Builder.CreateBitCast(PtrAnnFirstArg, IntTy,
3528+
PtrAnnFirstArg->getName()),
34903529
Builder.CreateBitCast(GS, Int8PtrTyPrivate), UndefInt8Ptr,
34913530
UndefInt32, UndefInt8Ptr};
3492-
Builder.CreateCall(AnnotationFn, Args);
3531+
auto *PtrAnnotationCall = Builder.CreateCall(AnnotationFn, Args);
3532+
GEPOrUseMap[AL][I] = PtrAnnotationCall;
34933533
}
34943534
}
34953535
}

lib/SPIRV/SPIRVReader.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ class SPIRVToLLVM : private BuiltinCallHelper {
155155
typedef std::map<const BasicBlock *, const SPIRVValue *>
156156
SPIRVToLLVMLoopMetadataMap;
157157

158+
// Store all the allocations to Struct Types that are further
159+
// accessed inside GetElementPtr instruction or in ptr.annotation intrinsics.
160+
// For every structure we save the accessed structure field index and the
161+
// last corresponding translated LLVM instruction.
162+
typedef std::unordered_map<Value *,
163+
std::unordered_map<SPIRVWord, Instruction *>>
164+
TypeToGEPOrUseMap;
165+
158166
private:
159167
Module *M;
160168
LLVMContext *Context;
@@ -186,6 +194,8 @@ class SPIRVToLLVM : private BuiltinCallHelper {
186194
SPIRVToLLVMMDAliasInstMap MDAliasScopeMap;
187195
SPIRVToLLVMMDAliasInstMap MDAliasListMap;
188196

197+
TypeToGEPOrUseMap GEPOrUseMap;
198+
189199
Type *mapType(SPIRVType *BT, Type *T);
190200

191201
// If a value is mapped twice, the existing mapped value is a placeholder,

test/transcoding/multiple_user_semantic.ll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,19 @@
2323
; CHECK-LLVM: @[[StrB:[0-9_.]+]] = {{.*}}"var_annotation_b2\00"
2424
; CHECK-LLVM: %[[#StructMember:]] = alloca %class.Sample, align 4
2525
; CHECK-LLVM: %[[#GEP1:]] = getelementptr inbounds %class.Sample, %class.Sample* %[[#StructMember]], i32 0, i32 0
26-
; CHECK-LLVM: call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP1:]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructA]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
27-
; CHECK-LLVM: %[[#GEP2:]] = getelementptr inbounds %class.Sample, %class.Sample* %[[#StructMember]], i32 0, i32 0
28-
; CHECK-LLVM: call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP2]], i8* getelementptr inbounds ([20 x i8], [20 x i8]* @[[StrStructB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
26+
; CHECK-LLVM: %[[#PtrAnn1:]] = call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP1:]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructA]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
27+
; CHECK-LLVM: %[[#PtrAnn2:]] = call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#PtrAnn1]], i8* getelementptr inbounds ([20 x i8], [20 x i8]* @[[StrStructB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
2928
; CHECK-LLVM: [[#Var:]] = alloca i32, align 4
3029
; CHECK-LLVM: [[#Bitcast1:]] = bitcast i32* %[[#Var]] to i8*
3130
; CHECK-LLVM: call void @llvm.var.annotation.p0i8.p0i8(i8* %[[#Bitcast1]], i8* getelementptr inbounds ([17 x i8], [17 x i8]* @[[StrA]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
3231
; CHECK-LLVM: [[#Bitcast2:]] = bitcast i32* %[[#Var]] to i8*
3332
; CHECK-LLVM: call void @llvm.var.annotation.p0i8.p0i8(i8* %[[#Bitcast2]], i8* getelementptr inbounds ([18 x i8], [18 x i8]* @[[StrB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
33+
; CHECK-LLVM: [[#Bitcast3:]] = bitcast i32* %[[#PtrAnn2]] to i8*
34+
; CHECK-LLVM: [[#Bitcast4:]] = bitcast i8* %[[#Bitcast3]] to i32*
35+
; CHECK-LLVM: [[#Load1:]] = load i32, i32* %[[#Bitcast4]], align 4
36+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#Load1]])
37+
; CHECK-LLVM: [[#Load2:]] = load i32, i32* %[[#Var]], align 4
38+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#Load2]])
3439

3540

3641
source_filename = "llvm-link"

test/transcoding/multiple_user_semantic_nonopaque.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@
2828
; CHECK-LLVM: call void @llvm.var.annotation.p0i8.p0i8(i8* %[[#Bitcast2]], i8* getelementptr inbounds ([17 x i8], [17 x i8]* @[[StrB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
2929
; CHECK-LLVM: %[[#StructMember:]] = alloca %class.Sample, align 4
3030
; CHECK-LLVM: %[[#GEP1:]] = getelementptr inbounds %class.Sample, %class.Sample* %[[#StructMember]], i32 0, i32 0
31-
; CHECK-LLVM: call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP1:]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructA]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
32-
; CHECK-LLVM: %[[#GEP2:]] = getelementptr inbounds %class.Sample, %class.Sample* %[[#StructMember]], i32 0, i32 0
33-
; CHECK-LLVM: call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP2]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
31+
; CHECK-LLVM: %[[#PtrAnn:]] = call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#GEP1:]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructA]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
32+
; CHECK-LLVM: call i32* @llvm.ptr.annotation.p0i32.p0i8(i32* %[[#PtrAnn]], i8* getelementptr inbounds ([19 x i8], [19 x i8]* @[[StrStructB]], i32 0, i32 0), i8* undef, i32 undef, i8* undef)
3433

3534

3635
source_filename = "llvm-link"
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
; This test is intended to check that we are actually using the
2+
; ptr.annotation intrinsic call results during the reverse translation.
3+
4+
; Source (https://godbolt.org/z/qzhsKfPeq):
5+
; class B {
6+
; public:
7+
; int Val [[clang::annotate("ClassB")]];
8+
; };
9+
; class A {
10+
; public:
11+
; int Val [[clang::annotate("ClassA")]];
12+
; int MultiDec [[clang::annotate("Dec1"), clang::annotate("Dec2"), clang::annotate("Dec3")]];
13+
; [[clang::annotate("ClassAfieldB")]]class B b;
14+
; };
15+
; void foo(int);
16+
; int main() {
17+
; A a;
18+
; B b;
19+
; A c;
20+
; foo(a.Val); // ClassA
21+
; foo(c.Val); // Obj2ClassA
22+
; foo(a.MultiDec); // ClassAMultiDec
23+
; foo(a.b.Val); // ClassAFieldB
24+
; foo(b.Val); // ClassB
25+
; return 0;
26+
; }
27+
28+
29+
; RUN: llvm-as %s -o %t.bc
30+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
31+
32+
; RUN: llvm-spirv %t.bc -o %t.spv
33+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
34+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
35+
36+
; Check that even when FPGA memory extensions are enabled - yet we have
37+
; UserSemantic decoration be generated
38+
; RUN: llvm-as %s -o %t.bc
39+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_fpga_memory_accesses,+SPV_INTEL_fpga_memory_attributes -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
40+
41+
; CHECK-SPIRV: Name [[#ClassA:]] "class.A"
42+
; CHECK-SPIRV: Name [[#ClassB:]] "class.B"
43+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 0 UserSemantic "ClassA"
44+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 0 UserSemantic "ClassA"
45+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 1 UserSemantic "Dec1"
46+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 1 UserSemantic "Dec2"
47+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 1 UserSemantic "Dec3"
48+
; CHECK-SPIRV: MemberDecorate [[#ClassA]] 2 UserSemantic "ClassAfieldB"
49+
; CHECK-SPIRV: MemberDecorate [[#ClassB]] 0 UserSemantic "ClassB"
50+
; CHECK-SPIRV: MemberDecorate [[#ClassB]] 0 UserSemantic "ClassB"
51+
52+
; CHECK-LLVM: @[[#StrStructA:]] = {{.*}}"ClassA\00"
53+
; CHECK-LLVM: @[[#StrStructA2:]] = {{.*}}"ClassA\00"
54+
; CHECK-LLVM: @[[#Dec1:]] = {{.*}}"Dec1\00"
55+
; CHECK-LLVM: @[[#Dec2:]] = {{.*}}"Dec2\00"
56+
; CHECK-LLVM: @[[#Dec3:]] = {{.*}}"Dec3\00"
57+
; CHECK-LLVM: @[[#StrAfieldB:]] = {{.*}}"ClassAfieldB\00"
58+
; CHECK-LLVM: @[[#StrStructB:]] = {{.*}}"ClassB\00"
59+
; CHECK-LLVM: @[[#StrStructB2:]] = {{.*}}"ClassB\00"
60+
; CHECK-LLVM: @[[#StrObj2StructA:]] = {{.*}}"ClassA\00"
61+
; CHECK-LLVM: @[[#StrObj2StructA2:]] = {{.*}}"ClassA\00"
62+
63+
; CHECK-LLVM: %[[#ObjClassA:]] = alloca %class.A, align 4
64+
; CHECK-LLVM: %[[#GepClassAVal:]] = getelementptr inbounds %class.A, ptr %[[#ObjClassA]], i32 0, i32 0
65+
; CHECK-LLVM: %[[#PtrAnnClassAVal:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#GepClassAVal]], ptr @[[#StrStructA]], ptr undef, i32 undef, ptr undef)
66+
; CHECK-LLVM: %[[#PtrAnn2ClassAVal:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#PtrAnnClassAVal]], ptr @[[#StrStructA2]], ptr undef, i32 undef, ptr undef)
67+
68+
; CHECK-LLVM: %[[#GepMultiDec:]] = getelementptr inbounds %class.A, ptr %[[#ObjClassA]], i32 0, i32 1
69+
; CHECK-LLVM: %[[#PtrAnnMultiDec:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#GepMultiDec]], ptr @[[#Dec1]], ptr undef, i32 undef, ptr undef)
70+
; CHECK-LLVM: %[[#PtrAnn2MultiDec:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#PtrAnnMultiDec]], ptr @[[#Dec2]], ptr undef, i32 undef, ptr undef)
71+
; CHECK-LLVM: %[[#PtrAnn3MultiDec:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#PtrAnn2MultiDec]], ptr @[[#Dec3]], ptr undef, i32 undef, ptr undef)
72+
73+
; CHECK-LLVM: %[[#GepClassAFieldB:]] = getelementptr inbounds %class.A, ptr %[[#ObjClassA]], i32 0, i32 2
74+
; CHECK-LLVM: %[[#CastClassAFieldB:]] = bitcast ptr %[[#GepClassAFieldB]] to ptr
75+
; CHECK-LLVM: %[[#PtrAnnClassAFieldB:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#CastClassAFieldB]], ptr @[[#StrAfieldB]], ptr undef, i32 undef, ptr undef)
76+
77+
; CHECK-LLVM: %[[#ObjClassB:]] = alloca %class.B, align 4
78+
; CHECK-LLVM: %[[#GEPClassB:]] = getelementptr inbounds %class.B, ptr %[[#ObjClassB]], i32 0, i32 0
79+
; CHECK-LLVM: %[[#PtrAnnClassB:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#GEPClassB]], ptr @[[#StrStructB]], ptr undef, i32 undef, ptr undef)
80+
; CHECK-LLVM: %[[#PtrAnn2ClassB:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#PtrAnnClassB]], ptr @[[#StrStructB2]], ptr undef, i32 undef, ptr undef)
81+
82+
; CHECK-LLVM: %[[#Obj2ClassA:]] = alloca %class.A, align 4
83+
; CHECK-LLVM: %[[#GepObj2ClassA:]] = getelementptr inbounds %class.A, ptr %[[#Obj2ClassA]], i32 0, i32 0
84+
; CHECK-LLVM: %[[#PtrAnnObj2ClassA:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#GepObj2ClassA]], ptr @[[#StrObj2StructA]], ptr undef, i32 undef, ptr undef)
85+
; CHECK-LLVM: %[[#PtrAnn2Obj2ClassA:]] = call ptr @llvm.ptr.annotation.p0.p0(ptr %[[#PtrAnnObj2ClassA]], ptr @[[#StrObj2StructA2]], ptr undef, i32 undef, ptr undef)
86+
87+
88+
; CHECK-LLVM: %[[#CastClassAVal:]] = bitcast ptr %[[#PtrAnn2ClassAVal]] to ptr
89+
; CHECK-LLVM: %[[#LoadClassAVal:]] = bitcast ptr %[[#CastClassAVal]] to ptr
90+
; CHECK-LLVM: %[[#CallClassA:]] = load i32, ptr %[[#LoadClassAVal]], align 4
91+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#CallClassA]])
92+
93+
; CHECK-LLVM: %[[#CastObj2ClassA:]] = bitcast ptr %[[#PtrAnn2Obj2ClassA]] to ptr
94+
; CHECK-LLVM: %[[#LoadObj2ClassA:]] = bitcast ptr %[[#CastObj2ClassA]] to ptr
95+
; CHECK-LLVM: %[[#CallObj2ClassA:]] = load i32, ptr %[[#LoadObj2ClassA]], align 4
96+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#CallObj2ClassA]])
97+
98+
; CHECK-LLVM: %[[#CastMultiDec:]] = bitcast ptr %[[#PtrAnn3MultiDec]] to ptr
99+
; CHECK-LLVM: %[[#LoadMultiDec:]] = bitcast ptr %[[#CastMultiDec]] to ptr
100+
; CHECK-LLVM: %[[#CallClassAMultiDec:]] = load i32, ptr %[[#LoadMultiDec]], align 4
101+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#CallClassAMultiDec]])
102+
103+
; CHECK-LLVM: %[[#CastClassAFieldB:]] = bitcast ptr %[[#PtrAnnClassAFieldB]] to ptr
104+
; CHECK-LLVM: %[[#Cast2ClassAFieldB:]] = bitcast ptr %[[#CastClassAFieldB]] to ptr
105+
; CHECK-LLVM: %[[#GEPClassB:]] = getelementptr inbounds %class.B, ptr %[[#Cast2ClassAFieldB]], i32 0, i32 0
106+
; CHECK-LLVM: %[[#CastClassB:]] = bitcast ptr %[[#GEPClassB]] to ptr
107+
; CHECK-LLVM: %[[#Cast2ClassB:]] = bitcast ptr %[[#CastClassB]] to ptr
108+
; CHECK-LLVM: %[[#CallClassAFieldB:]] = load i32, ptr %[[#Cast2ClassB]], align 4
109+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#CallClassAFieldB]])
110+
111+
; CHECK-LLVM: %[[#CastClassB:]] = bitcast ptr %[[#PtrAnn2ClassB]] to ptr
112+
; CHECK-LLVM: %[[#Cast2ClassB:]] = bitcast ptr %[[#CastClassB]] to ptr
113+
; CHECK-LLVM: %[[#CallClassB:]] = load i32, ptr %[[#Cast2ClassB]], align 4
114+
; CHECK-LLVM: call spir_func void @_Z3fooi(i32 %[[#CallClassB]])
115+
116+
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"
117+
target triple = "spir64"
118+
119+
%class.A = type { i32, i32, %class.B }
120+
%class.B = type { i32 }
121+
122+
@.str = private unnamed_addr constant [7 x i8] c"ClassA\00", section "llvm.metadata"
123+
@.str.1 = private unnamed_addr constant [17 x i8] c"/app/example.cpp\00", section "llvm.metadata"
124+
@.str.2 = private unnamed_addr constant [5 x i8] c"Dec1\00", section "llvm.metadata"
125+
@.str.3 = private unnamed_addr constant [5 x i8] c"Dec2\00", section "llvm.metadata"
126+
@.str.4 = private unnamed_addr constant [5 x i8] c"Dec3\00", section "llvm.metadata"
127+
@.str.5 = private unnamed_addr constant [13 x i8] c"ClassAfieldB\00", section "llvm.metadata"
128+
@.str.6 = private unnamed_addr constant [7 x i8] c"ClassB\00", section "llvm.metadata"
129+
130+
define dso_local noundef i32 @main() #0 {
131+
%1 = alloca i32, align 4
132+
%2 = alloca %class.A, align 4
133+
%3 = alloca %class.B, align 4
134+
%4 = alloca %class.A, align 4
135+
store i32 0, ptr %1, align 4
136+
%5 = getelementptr inbounds %class.A, ptr %2, i32 0, i32 0
137+
%6 = call ptr @llvm.ptr.annotation.p0.p0(ptr %5, ptr @.str, ptr @.str.1, i32 11, ptr null)
138+
%7 = load i32, ptr %6, align 4
139+
call void @_Z3fooi(i32 noundef %7)
140+
%8 = getelementptr inbounds %class.A, ptr %4, i32 0, i32 0
141+
%9 = call ptr @llvm.ptr.annotation.p0.p0(ptr %8, ptr @.str, ptr @.str.1, i32 11, ptr null)
142+
%10 = load i32, ptr %9, align 4
143+
call void @_Z3fooi(i32 noundef %10)
144+
%11 = getelementptr inbounds %class.A, ptr %2, i32 0, i32 1
145+
%12 = call ptr @llvm.ptr.annotation.p0.p0(ptr %11, ptr @.str.2, ptr @.str.1, i32 12, ptr null)
146+
%13 = call ptr @llvm.ptr.annotation.p0.p0(ptr %12, ptr @.str.3, ptr @.str.1, i32 12, ptr null)
147+
%14 = call ptr @llvm.ptr.annotation.p0.p0(ptr %13, ptr @.str.4, ptr @.str.1, i32 12, ptr null)
148+
%15 = load i32, ptr %14, align 4
149+
call void @_Z3fooi(i32 noundef %15)
150+
%16 = getelementptr inbounds %class.A, ptr %2, i32 0, i32 2
151+
%17 = call ptr @llvm.ptr.annotation.p0.p0(ptr %16, ptr @.str.5, ptr @.str.1, i32 13, ptr null)
152+
%18 = getelementptr inbounds %class.B, ptr %17, i32 0, i32 0
153+
%19 = call ptr @llvm.ptr.annotation.p0.p0(ptr %18, ptr @.str.6, ptr @.str.1, i32 5, ptr null)
154+
%20 = load i32, ptr %19, align 4
155+
call void @_Z3fooi(i32 noundef %20)
156+
%21 = getelementptr inbounds %class.B, ptr %3, i32 0, i32 0
157+
%22 = call ptr @llvm.ptr.annotation.p0.p0(ptr %21, ptr @.str.6, ptr @.str.1, i32 5, ptr null)
158+
%23 = load i32, ptr %22, align 4
159+
call void @_Z3fooi(i32 noundef %23)
160+
ret i32 0
161+
}
162+
163+
declare void @_Z3fooi(i32 noundef) #2
164+
165+
declare ptr @llvm.ptr.annotation.p0.p0(ptr, ptr, ptr, i32, ptr) #3
166+
167+
attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
168+
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
169+
attributes #2 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
170+
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }

0 commit comments

Comments
 (0)