[clang] be75ded - [KeyInstr][Clang] Copy ctor/assignment operator source atoms (#144346)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 30 04:27:48 PDT 2025


Author: Orlando Cazalet-Hyams
Date: 2025-06-30T12:27:44+01:00
New Revision: be75ded3fea900718a72298276d2428ea227ceaf

URL: https://github.com/llvm/llvm-project/commit/be75ded3fea900718a72298276d2428ea227ceaf
DIFF: https://github.com/llvm/llvm-project/commit/be75ded3fea900718a72298276d2428ea227ceaf.diff

LOG: [KeyInstr][Clang] Copy ctor/assignment operator source atoms (#144346)

Added: 
    clang/test/DebugInfo/KeyInstructions/init-member-memcopyable-2.cpp
    clang/test/DebugInfo/KeyInstructions/init-member-memcopyable.cpp

Modified: 
    clang/lib/CodeGen/CGClass.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 13792c1042046..4a465e6526da0 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -627,6 +627,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
                                   CXXCtorInitializer *MemberInit,
                                   const CXXConstructorDecl *Constructor,
                                   FunctionArgList &Args) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation());
   assert(MemberInit->isAnyMemberInitializer() &&
          "Must have member initializer!");
@@ -1000,7 +1001,8 @@ namespace {
     void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
       DestPtr = DestPtr.withElementType(CGF.Int8Ty);
       SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
-      CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
+      auto *I = CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
+      CGF.addInstToCurrentSourceAtom(I, nullptr);
     }
 
     void addInitialField(FieldDecl *F) {
@@ -1113,6 +1115,7 @@ namespace {
       }
 
       pushEHDestructors();
+      ApplyAtomGroup Grp(CGF.getDebugInfo());
       emitMemcpy();
       AggregatedInits.clear();
     }
@@ -1248,6 +1251,7 @@ namespace {
         reset();
       }
 
+      ApplyAtomGroup Grp(CGF.getDebugInfo());
       emitMemcpy();
       AggregatedStmts.clear();
     }
@@ -1338,9 +1342,9 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
     assert(!Member->isBaseInitializer());
     assert(Member->isAnyMemberInitializer() &&
            "Delegating initializer on non-delegating constructor");
-    ApplyAtomGroup Grp(getDebugInfo());
     CM.addMemberInitializer(Member);
   }
+
   CM.finish();
 }
 
@@ -1563,6 +1567,7 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
   AssignmentMemcpyizer AM(*this, AssignOp, Args);
   for (auto *I : RootCS->body())
     AM.emitAssignment(I);
+
   AM.finish();
 }
 

diff  --git a/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable-2.cpp b/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable-2.cpp
new file mode 100644
index 0000000000000..c94fc588bf13b
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable-2.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -gno-column-info -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// g::h and i can be memcpy'd, check the assignment gets Key Instructions metadata.
+
+struct e {
+  e(e &);
+  e& operator=(const e&);
+};
+
+struct g {
+  e f;
+  int h;
+  int i;
+};
+
+// Copy assignment operator.
+// CHECK: define{{.*}}ptr @_ZN1gaSERKS_
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %.addr = alloca ptr, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %call = call {{.*}}ptr @_ZN1eaSERKS_(ptr {{.*}}%this1, ptr {{.*}}%1)
+// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
+// CHECK-NEXT: call void @llvm.memcpy{{.*}}(ptr align 4 %h, ptr align 4 %h2, i64 8, i1 false), !dbg [[S1_G1R1:!.*]]
+// CHECK-NEXT: ret ptr %this1, !dbg
+
+// Copy ctor.
+// CHECK: define{{.*}}void @_ZN1gC2ERS_
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %.addr = alloca ptr, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: call void @_ZN1eC1ERS_
+// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
+// CHECK-NEXT: call void @llvm.memcpy{{.*}}(ptr align 4 %h, ptr align 4 %h2, i64 8, i1 false), !dbg [[S2_G1R1:!.*]]
+// CHECK-NEXT: ret void, !dbg
+
+// CHECK: [[S1:!.*]] = distinct !DISubprogram(name: "operator=",
+// CHECK: [[S1_G1R1]] = !DILocation(line: 11, scope: [[S1]], atomGroup: 1, atomRank: 1)
+
+// CHECK: [[S2:!.*]] = distinct !DISubprogram(name: "g",
+// CHECK: [[S2_G1R1]] = !DILocation(line: 11, scope: [[S2]], atomGroup: 1, atomRank: 1)
+
+[[gnu::nodebug]]
+void fun(g *x) {
+  g y = g(*x);
+  y = *x;
+}

diff  --git a/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable.cpp b/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable.cpp
new file mode 100644
index 0000000000000..cd3807735fa32
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-member-memcopyable.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -gno-column-info -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// g::h can be memcpy'd (in this case emitted as load/stored), check the
+// assignment gets Key Instructions metadata.
+
+struct e {
+  e(e&);
+  e& operator=(const e&);
+};
+
+struct g {
+  e f;
+  int h;
+};
+
+// Copy assignment operator.
+// CHECK: define{{.*}}ptr @_ZN1gaSERKS_
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %.addr = alloca ptr, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %call = call {{.*}}ptr @_ZN1eaSERKS_(ptr {{.*}}%this1, ptr {{.*}}%1)
+// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
+// CHECK-NEXT: %3 = load i32, ptr %h, align 4, !dbg [[S1_G1R2:!.*]]
+// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: store i32 %3, ptr %h2, align 4, !dbg [[S1_G1R1:!.*]]
+// CHECK-NEXT: ret ptr %this1, !dbg
+
+// Copy ctor.
+// CHECK: define{{.*}}void @_ZN1gC2ERS_
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %.addr = alloca ptr, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: store ptr %0, ptr %.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: call void @_ZN1eC1ERS_
+// CHECK-NEXT: %h = getelementptr inbounds nuw %struct.g, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %2 = load ptr, ptr %.addr, align 8
+// CHECK-NEXT: %h2 = getelementptr inbounds nuw %struct.g, ptr %2, i32 0, i32 1
+// CHECK-NEXT: %3 = load i32, ptr %h2, align 4, !dbg [[S2_G1R2:!.*]]
+// CHECK-NEXT: store i32 %3, ptr %h, align 4, !dbg [[S2_G1R1:!.*]]
+// CHECK-NEXT: ret void, !dbg
+
+// CHECK: [[S1:!.*]] = distinct !DISubprogram(name: "operator=",
+// CHECK: [[S1_G1R2]] = !DILocation(line: 12, scope: [[S1]], atomGroup: 1, atomRank: 2)
+// CHECK: [[S1_G1R1]] = !DILocation(line: 12, scope: [[S1]], atomGroup: 1, atomRank: 1)
+
+// CHECK: [[S2:!.*]] = distinct !DISubprogram(name: "g",
+// CHECK: [[S2_G1R2]] = !DILocation(line: 12, scope: [[S2]], atomGroup: 1, atomRank: 2)
+// CHECK: [[S2_G1R1]] = !DILocation(line: 12, scope: [[S2]], atomGroup: 1, atomRank: 1)
+
+void fun(g *x) {
+  g y = g(*x);
+  y = *x;
+}


        


More information about the cfe-commits mailing list