Skip to content

Commit 7557ed7

Browse files
OCHyamsrlavaee
authored andcommitted
[KeyInstr][Clang] Copy ctor/assignment operator source atoms (llvm#144346)
1 parent e36aae0 commit 7557ed7

File tree

3 files changed

+128
-2
lines changed

3 files changed

+128
-2
lines changed

clang/lib/CodeGen/CGClass.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
627627
CXXCtorInitializer *MemberInit,
628628
const CXXConstructorDecl *Constructor,
629629
FunctionArgList &Args) {
630+
ApplyAtomGroup Grp(CGF.getDebugInfo());
630631
ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation());
631632
assert(MemberInit->isAnyMemberInitializer() &&
632633
"Must have member initializer!");
@@ -1000,7 +1001,8 @@ namespace {
10001001
void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
10011002
DestPtr = DestPtr.withElementType(CGF.Int8Ty);
10021003
SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
1003-
CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
1004+
auto *I = CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
1005+
CGF.addInstToCurrentSourceAtom(I, nullptr);
10041006
}
10051007

10061008
void addInitialField(FieldDecl *F) {
@@ -1113,6 +1115,7 @@ namespace {
11131115
}
11141116

11151117
pushEHDestructors();
1118+
ApplyAtomGroup Grp(CGF.getDebugInfo());
11161119
emitMemcpy();
11171120
AggregatedInits.clear();
11181121
}
@@ -1248,6 +1251,7 @@ namespace {
12481251
reset();
12491252
}
12501253

1254+
ApplyAtomGroup Grp(CGF.getDebugInfo());
12511255
emitMemcpy();
12521256
AggregatedStmts.clear();
12531257
}
@@ -1338,9 +1342,9 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
13381342
assert(!Member->isBaseInitializer());
13391343
assert(Member->isAnyMemberInitializer() &&
13401344
"Delegating initializer on non-delegating constructor");
1341-
ApplyAtomGroup Grp(getDebugInfo());
13421345
CM.addMemberInitializer(Member);
13431346
}
1347+
13441348
CM.finish();
13451349
}
13461350

@@ -1563,6 +1567,7 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
15631567
AssignmentMemcpyizer AM(*this, AssignOp, Args);
15641568
for (auto *I : RootCS->body())
15651569
AM.emitAssignment(I);
1570+
15661571
AM.finish();
15671572
}
15681573

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -gno-column-info -debug-info-kind=line-tables-only -emit-llvm -o - \
2+
// RUN: | FileCheck %s
3+
4+
// g::h and i can be memcpy'd, check the assignment gets Key Instructions metadata.
5+
6+
struct e {
7+
e(e &);
8+
e& operator=(const e&);
9+
};
10+
11+
struct g {
12+
e f;
13+
int h;
14+
int i;
15+
};
16+
17+
// Copy assignment operator.
18+
// CHECK: define{{.*}}ptr @_ZN1gaSERKS_
19+
// CHECK-NEXT: entry:
20+
// CHECK-NEXT: %this.addr = alloca ptr, align 8
21+
// CHECK-NEXT: %.addr = alloca ptr, align 8
22+
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
23+
// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
24+
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
25+
// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
26+
// CHECK-NEXT: %call = call {{.*}}ptr @_ZN1eaSERKS_(ptr {{.*}}%this1, ptr {{.*}}%1)
27+
// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
28+
// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
29+
// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
30+
// CHECK-NEXT: call void @llvm.memcpy{{.*}}(ptr align 4 %h, ptr align 4 %h2, i64 8, i1 false), !dbg [[S1_G1R1:!.*]]
31+
// CHECK-NEXT: ret ptr %this1, !dbg
32+
33+
// Copy ctor.
34+
// CHECK: define{{.*}}void @_ZN1gC2ERS_
35+
// CHECK-NEXT: entry:
36+
// CHECK-NEXT: %this.addr = alloca ptr, align 8
37+
// CHECK-NEXT: %.addr = alloca ptr, align 8
38+
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
39+
// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
40+
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
41+
// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
42+
// CHECK-NEXT: call void @_ZN1eC1ERS_
43+
// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
44+
// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
45+
// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
46+
// CHECK-NEXT: call void @llvm.memcpy{{.*}}(ptr align 4 %h, ptr align 4 %h2, i64 8, i1 false), !dbg [[S2_G1R1:!.*]]
47+
// CHECK-NEXT: ret void, !dbg
48+
49+
// CHECK: [[S1:!.*]] = distinct !DISubprogram(name: "operator=",
50+
// CHECK: [[S1_G1R1]] = !DILocation(line: 11, scope: [[S1]], atomGroup: 1, atomRank: 1)
51+
52+
// CHECK: [[S2:!.*]] = distinct !DISubprogram(name: "g",
53+
// CHECK: [[S2_G1R1]] = !DILocation(line: 11, scope: [[S2]], atomGroup: 1, atomRank: 1)
54+
55+
[[gnu::nodebug]]
56+
void fun(g *x) {
57+
g y = g(*x);
58+
y = *x;
59+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -gno-column-info -debug-info-kind=line-tables-only -emit-llvm -o - \
2+
// RUN: | FileCheck %s
3+
4+
// g::h can be memcpy'd (in this case emitted as load/stored), check the
5+
// assignment gets Key Instructions metadata.
6+
7+
struct e {
8+
e(e&);
9+
e& operator=(const e&);
10+
};
11+
12+
struct g {
13+
e f;
14+
int h;
15+
};
16+
17+
// Copy assignment operator.
18+
// CHECK: define{{.*}}ptr @_ZN1gaSERKS_
19+
// CHECK-NEXT: entry:
20+
// CHECK-NEXT: %this.addr = alloca ptr, align 8
21+
// CHECK-NEXT: %.addr = alloca ptr, align 8
22+
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
23+
// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
24+
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
25+
// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
26+
// CHECK-NEXT: %call = call {{.*}}ptr @_ZN1eaSERKS_(ptr {{.*}}%this1, ptr {{.*}}%1)
27+
// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
28+
// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
29+
// CHECK-NEXT: %3 = load i32, ptr %h, align 4, !dbg [[S1_G1R2:!.*]]
30+
// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
31+
// CHECK-NEXT: store i32 %3, ptr %h2, align 4, !dbg [[S1_G1R1:!.*]]
32+
// CHECK-NEXT: ret ptr %this1, !dbg
33+
34+
// Copy ctor.
35+
// CHECK: define{{.*}}void @_ZN1gC2ERS_
36+
// CHECK-NEXT: entry:
37+
// CHECK-NEXT: %this.addr = alloca ptr, align 8
38+
// CHECK-NEXT: %.addr = alloca ptr, align 8
39+
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
40+
// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
41+
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
42+
// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
43+
// CHECK-NEXT: call void @_ZN1eC1ERS_
44+
// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
45+
// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
46+
// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
47+
// CHECK-NEXT: %3 = load i32, ptr %h2, align 4, !dbg [[S2_G1R2:!.*]]
48+
// CHECK-NEXT: store i32 %3, ptr %h, align 4, !dbg [[S2_G1R1:!.*]]
49+
// CHECK-NEXT: ret void, !dbg
50+
51+
// CHECK: [[S1:!.*]] = distinct !DISubprogram(name: "operator=",
52+
// CHECK: [[S1_G1R2]] = !DILocation(line: 12, scope: [[S1]], atomGroup: 1, atomRank: 2)
53+
// CHECK: [[S1_G1R1]] = !DILocation(line: 12, scope: [[S1]], atomGroup: 1, atomRank: 1)
54+
55+
// CHECK: [[S2:!.*]] = distinct !DISubprogram(name: "g",
56+
// CHECK: [[S2_G1R2]] = !DILocation(line: 12, scope: [[S2]], atomGroup: 1, atomRank: 2)
57+
// CHECK: [[S2_G1R1]] = !DILocation(line: 12, scope: [[S2]], atomGroup: 1, atomRank: 1)
58+
59+
void fun(g *x) {
60+
g y = g(*x);
61+
y = *x;
62+
}

0 commit comments

Comments
 (0)