[clang] [KeyInstr][Clang] Ret atom (PR #134652)

Orlando Cazalet-Hyams via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 3 07:39:53 PDT 2025


https://github.com/OCHyams updated https://github.com/llvm/llvm-project/pull/134652

>From a8837383c3289ab1c1e93b5fa00371241fa55fb4 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Fri, 4 Apr 2025 16:28:39 +0100
Subject: [PATCH 01/12] [KeyInstr][Clang] Ret atom

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGCall.cpp                  |  6 +-
 clang/lib/CodeGen/CGStmt.cpp                  | 13 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp         | 15 ++++
 .../DebugInfo/KeyInstructions/return-va-arg.c | 25 ++++++
 clang/test/DebugInfo/KeyInstructions/return.c | 90 +++++++++++++++++++
 5 files changed, 144 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/return-va-arg.c
 create mode 100644 clang/test/DebugInfo/KeyInstructions/return.c

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 056caf64525a5..b422ff6182a0a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -3946,7 +3946,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
 
   // Functions with no result always return void.
   if (!ReturnValue.isValid()) {
-    Builder.CreateRetVoid();
+    auto *I = Builder.CreateRetVoid();
+    addRetToOverrideOrNewSourceAtom(I, nullptr);
     return;
   }
 
@@ -4126,6 +4127,9 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
 
   if (RetDbgLoc)
     Ret->setDebugLoc(std::move(RetDbgLoc));
+
+  llvm::Value *Backup = RV ? Ret->getOperand(0) : nullptr;
+  addRetToOverrideOrNewSourceAtom(cast<llvm::ReturnInst>(Ret), Backup);
 }
 
 void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 205a57cbab31a..35ac2bc95c6ae 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1589,6 +1589,7 @@ static bool isSwiftAsyncCallee(const CallExpr *CE) {
 /// if the function returns void, or may be missing one if the function returns
 /// non-void.  Fun stuff :).
 void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+  ApplyAtomGroup Grp(getDebugInfo());
   if (requiresReturnValueCheck()) {
     llvm::Constant *SLoc = EmitCheckSourceLocation(S.getBeginLoc());
     auto *SLocPtr =
@@ -1598,6 +1599,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
     CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
     assert(ReturnLocation.isValid() && "No valid return location");
     Builder.CreateStore(SLocPtr, ReturnLocation);
+    //*OCH?*//
   }
 
   // Returning from an outlined SEH helper is UB, and we already warn on it.
@@ -1664,16 +1666,19 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
     // If this function returns a reference, take the address of the expression
     // rather than the value.
     RValue Result = EmitReferenceBindingToExpr(RV);
-    Builder.CreateStore(Result.getScalarVal(), ReturnValue);
+    auto *I = Builder.CreateStore(Result.getScalarVal(), ReturnValue);
+    addInstToCurrentSourceAtom(I, I->getValueOperand());
   } else {
     switch (getEvaluationKind(RV->getType())) {
     case TEK_Scalar: {
       llvm::Value *Ret = EmitScalarExpr(RV);
-      if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect)
+      if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
         EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()),
                           /*isInit*/ true);
-      else
-        Builder.CreateStore(Ret, ReturnValue);
+      } else {
+        auto *I = Builder.CreateStore(Ret, ReturnValue);
+        addInstToCurrentSourceAtom(I, I->getValueOperand());
+      }
       break;
     }
     case TEK_Complex:
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 0388c67d0100d..f44fc408cc97f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -342,6 +342,15 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
       // later by the actual 'ret' instruction.
       llvm::DebugLoc Loc = BI->getDebugLoc();
       Builder.SetInsertPoint(BI->getParent());
+
+      // Key Instructions: If there's only one `ret` then we want to put the
+      // instruction in the same source atom group as the store to the ret-value
+      // alloca and unconditional `br` to the return block that we're about to
+      // delete. It all comes from the same source (`return (value)`).
+      if (auto *DI = getDebugInfo(); DI && BI->getDebugLoc())
+        DI->setRetInstSourceAtomOverride(
+            BI->getDebugLoc().get()->getAtomGroup());
+
       BI->eraseFromParent();
       delete ReturnBlock.getBlock();
       ReturnBlock = JumpDest();
@@ -1550,6 +1559,12 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
       Bypasses.Init(CGM, Body);
   }
 
+  // Finalize function debug info on exit.
+  auto Cleanup = llvm::make_scope_exit([this] {
+    if (CGDebugInfo *DI = getDebugInfo())
+      DI->completeFunction();
+  });
+
   // Emit the standard function prologue.
   StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
 
diff --git a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
new file mode 100644
index 0000000000000..2864489afd738
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
@@ -0,0 +1,25 @@
+// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+typedef struct {
+  struct{} a;
+  double b;
+} s1;
+
+s1 f(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+// CHECK: vaarg.end:
+// CHECK-NEXT: %vaarg.addr = phi ptr
+// CHECK-NEXT: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK-NEXT: {{.*}} = getelementptr{{.*}}
+// CHECK-NEXT: [[LOAD:%.*]] = load double{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK-NEXT: ret double [[LOAD]], !dbg [[G1R1]]
+  return __builtin_va_arg(list, s1);
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
diff --git a/clang/test/DebugInfo/KeyInstructions/return.c b/clang/test/DebugInfo/KeyInstructions/return.c
new file mode 100644
index 0000000000000..24c58450d37ed
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/return.c
@@ -0,0 +1,90 @@
+// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
+
+// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// Check the stores to `retval` allocas and branches to `return` block are in
+// the same atom group. They are both rank 1, which could in theory introduce
+// an extra step in some optimized code. This low risk currently feels an
+// acceptable for keeping the code a bit simpler (as opposed to adding
+// scaffolding to make the store rank 2).
+
+// Also check that in the case of a single return (no control flow) the
+// return instruction inherits the atom group of the branch to the return
+// block when the blocks get folded togather.
+
+#ifdef __cplusplus
+#define nomangle extern "C"
+#else
+#define nomangle
+#endif
+
+int g;
+nomangle float a() {
+// CHECK: float @a()
+  if (g)
+// CHECK: if.then:
+// CHECK-NEXT: %1 = load i32, ptr @g{{.*}}, !dbg [[G2R3:!.*]]
+// CHECK-NEXT: %conv = sitofp i32 %1 to float{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store float %conv, ptr %retval{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK-NEXT: br label %return{{.*}}, !dbg [[G2R1]]
+    return g;
+// CHECK: if.end:
+// CHECK-NEXT: store float 1.000000e+00, ptr %retval{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: br label %return, !dbg [[G3R1]]
+
+// CHECK: return:
+// CHECK-NEXT:  %2 = load float, ptr %retval{{.*}}, !dbg [[G4R2:!.*]]
+// CHECK-NEXT:  ret float %2{{.*}}, !dbg [[G4R1:!.*]]
+  return 1;
+}
+
+// CHECK: void @b()
+// CHECK: ret void{{.*}}, !dbg [[B_G1R1:!.*]]
+nomangle void b() { return; }
+
+// CHECK: i32 @c()
+// CHECK: %add = add{{.*}}, !dbg [[C_G1R2:!.*]]
+// CHECK: ret i32 %add{{.*}}, !dbg [[C_G1R1:!.*]]
+nomangle int c() { return g + 1; }
+
+// NOTE: (return) (g = 1) are two separate atoms.
+// CHECK: i32 @d()
+// CHECK: store{{.*}}, !dbg [[D_G2R1:!.*]]
+// CHECK: ret i32 1{{.*}}, !dbg [[D_G1R1:!.*]]
+nomangle int d() { return g = 1; }
+
+// The implicit return here get the line number of the closing brace; make it
+// key to match existing behaviour.
+// CHECK: ret void, !dbg [[E_G1R1:!.*]]
+nomangle void e() {}
+
+#ifdef __cplusplus
+// CHECK-CXX: ptr @_Z1fRi
+int &f(int &r) {
+// Include ctrl-flow to stop ret value store being elided.
+    if (r)
+// CHECK-CXX: if.then:
+// CHECK-CXX-NEXT: %2 = load ptr, ptr %r.addr{{.*}}, !dbg [[F_G2R2:!.*]]
+// CHECK-CXX-NEXT: store ptr %2, ptr %retval{{.*}}, !dbg [[F_G2R1:!.*]]
+// CHECK-CXX-NEXT: br label %return, !dbg [[F_G2R1:!.*]]
+    return r;
+  return g;
+}
+#endif
+
+// CHECK: [[G2R3]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 3)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[B_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[C_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[C_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[D_G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[D_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[E_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK-CXX: [[F_G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK-CXX: [[F_G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)

>From c24cdd73bbae6f57f6f0ff5fcdec52e0bfc6853d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Fri, 4 Apr 2025 16:36:53 +0100
Subject: [PATCH 02/12] [KeyInstr][Clang] Update tests with ret atoms

---
 clang/test/DebugInfo/KeyInstructions/agg.c           | 3 +++
 clang/test/DebugInfo/KeyInstructions/assign-scalar.c | 2 ++
 clang/test/DebugInfo/KeyInstructions/bitfield.cpp    | 3 +++
 clang/test/DebugInfo/KeyInstructions/builtin.c       | 2 ++
 clang/test/DebugInfo/KeyInstructions/complex.c       | 2 ++
 clang/test/DebugInfo/KeyInstructions/do.c            | 3 +++
 clang/test/DebugInfo/KeyInstructions/if.c            | 3 +++
 clang/test/DebugInfo/KeyInstructions/init-agg.c      | 3 +++
 clang/test/DebugInfo/KeyInstructions/init-member.cpp | 2 ++
 clang/test/DebugInfo/KeyInstructions/init-scalar.c   | 2 ++
 clang/test/DebugInfo/KeyInstructions/init-static.cpp | 6 ++++--
 clang/test/DebugInfo/KeyInstructions/try-catch.cpp   | 3 +++
 clang/test/DebugInfo/KeyInstructions/while.c         | 3 +++
 13 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
index 33b3a0141a0f1..f1a406a7bc119 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -24,6 +24,8 @@ void fun(Struct a) {
 // CHECK: %matins = insertelement <25 x float> %3, float 0.000000e+00, i64 0, !dbg [[G4R2:!.*]]
 // CHECK: store <25 x float> %matins, ptr @m{{.*}}, !dbg [[G4R1:!.*]]
   m[0][0] = 0;
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -32,3 +34,4 @@ void fun(Struct a) {
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
 // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index afb0ed8ebdfd7..402bb093b6ba6 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -58,6 +58,7 @@ void fun() {
 // CHECK-NEXT: %inc4 = add i64 %7, 1, !dbg [[G11R2:!.*]]
 // CHECK-NEXT: store i64 %inc4, ptr @i{{.*}}, !dbg [[G11R1:!.*]]
     g = ++h, ++i;
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -83,3 +84,4 @@ void fun() {
 // CHECK: [[load_i_loc]] = !DILocation(line: [[#]], column: [[#]], scope: ![[#]])
 // CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
index a14b4fbaf5854..165546d579b70 100644
--- a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
@@ -10,7 +10,10 @@ void foo(int x, S s) {
 // CHECK: %bf.set = or i8 %bf.clear, %bf.value, !dbg [[G1R2:!.*]]
 // CHECK: store i8 %bf.set, ptr %s, align 4, !dbg [[G1R1:!.*]]
   s.a = x;
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c
index 359d52ca3862e..12b4d74d4af33 100644
--- a/clang/test/DebugInfo/KeyInstructions/builtin.c
+++ b/clang/test/DebugInfo/KeyInstructions/builtin.c
@@ -64,6 +64,7 @@ void fun() {
 // CHECK-NEXT: %4 = trunc i32 %3 to i8, !dbg [[G15R2:!.*]]
 // CHECK-NEXT: call void @llvm.memset{{.*}}, !dbg [[G15R1:!.*]]
     __builtin_memset(f4, v, sizeof(float) * 4);
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
@@ -86,3 +87,4 @@ void fun() {
 // CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3)
 // CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2)
 // CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index 9647d0e4009ee..9673df08cc76b 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -71,6 +71,7 @@ void test() {
 // CHECK-C: store float %mul.rl, ptr @f, align 4, !dbg [[G11R1:!.*]]
   f *= ci;
 #endif
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
@@ -95,3 +96,4 @@ void test() {
 // CHECK-C: [[G10R1]] = !DILocation({{.*}}, atomGroup: 10, atomRank: 1)
 // CHECK-C: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK-C: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/do.c b/clang/test/DebugInfo/KeyInstructions/do.c
index 4f0d388f94047..31624b3a78656 100644
--- a/clang/test/DebugInfo/KeyInstructions/do.c
+++ b/clang/test/DebugInfo/KeyInstructions/do.c
@@ -25,9 +25,12 @@ void a(int A) {
 // CHECK: %tobool = icmp ne i32 %dec, 0, !dbg [[G2R1:!.*]]
 // CHECK: br i1 %tobool, label %do.body, label %do.end, !dbg [[G3R1:!.*]], !llvm.loop
     do { } while (--A);
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/if.c b/clang/test/DebugInfo/KeyInstructions/if.c
index b16dec7b91c4f..48621fb3b1976 100644
--- a/clang/test/DebugInfo/KeyInstructions/if.c
+++ b/clang/test/DebugInfo/KeyInstructions/if.c
@@ -32,6 +32,8 @@ void a(int A) {
     if (int B = A; B)
         ;
 #endif
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
@@ -44,3 +46,4 @@ void a(int A) {
 // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK-CXX: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
 // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
index 1021490bd75b4..ab20acfb70fc1 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -37,6 +37,8 @@ void a() {
 
 // CHECK: store i8 {{.*}}, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
     char uninit; // -ftrivial-auto-var-init=pattern
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -47,3 +49,4 @@ void a() {
 // CHECK: [[big_LINE]] = !DILocation(line: 33, scope: ![[#]])
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
index 4d8e1b9dace3f..99efc4bd49e33 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -17,6 +17,8 @@ void fun() {
 
 // CHECK: store i32 1, ptr %x{{.*}}, !dbg [[G1R1:!.*]]
 // CHECK: store float 5.000000e+00, ptr %y{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
index d4802a709b89a..0d690d82a2025 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -10,8 +10,10 @@ void a() {
 // CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
 // CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
     int B = 2 * A + 1;
+// CHECK: ret{{.*}}, !dbg [[G3R1:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
index 2cac57e1d9fff..58c38a8c55208 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-static.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
@@ -4,10 +4,12 @@
 // CHECK: [[b_addr:@.*]] = {{.*}}global ptr
 
 void g(int *a) {
-    // CHECK: [[v:%.*]] = load ptr, ptr %a.addr{{.*}}, !dbg [[G1R2:!.*]]
-    // CHECK: store ptr [[v]], ptr [[b_addr]]{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: [[v:%.*]] = load ptr, ptr %a.addr{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: store ptr [[v]], ptr [[b_addr]]{{.*}}, !dbg [[G1R1:!.*]]
     static int &b = *a;
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
index 918eb4c97db9a..d53bd52274503 100644
--- a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
@@ -14,7 +14,10 @@ void attempt() {
 // CHECK: store i32 %5, ptr %e{{.*}}, !dbg [[G1R1:!.*]]
 // CHECK: call void @__cxa_end_catch()
   catch (int e) { }
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/while.c b/clang/test/DebugInfo/KeyInstructions/while.c
index 38cdb8433dd27..be4d16207712b 100644
--- a/clang/test/DebugInfo/KeyInstructions/while.c
+++ b/clang/test/DebugInfo/KeyInstructions/while.c
@@ -26,9 +26,12 @@ void a(int A) {
 // CHECK: %tobool = icmp ne i32 %dec, 0, !dbg [[G2R1:!.*]]
 // CHECK: br i1 %tobool, label %while.body, label %while.end, !dbg [[G3R1:!.*]]
     while (--A) { };
+
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])

>From 8dceef18b861499ffbcc5873ed750d0142254ba7 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 17:09:46 +0100
Subject: [PATCH 03/12] fix rebase fallout - use new
 addInstToSpecificSourceAtom function, and fixup some tests

---
 clang/lib/CodeGen/CGCall.cpp                  | 16 ++++--
 clang/lib/CodeGen/CodeGenFunction.cpp         | 17 +++----
 clang/lib/CodeGen/CodeGenFunction.h           |  7 ++-
 clang/test/DebugInfo/KeyInstructions/agg.c    |  2 +-
 .../DebugInfo/KeyInstructions/assign-scalar.c |  1 +
 clang/test/DebugInfo/KeyInstructions/assign.c | 36 +++++++++++++
 .../DebugInfo/KeyInstructions/bitfield.cpp    |  2 +-
 .../test/DebugInfo/KeyInstructions/builtin.c  |  1 +
 .../test/DebugInfo/KeyInstructions/complex.c  |  1 +
 clang/test/DebugInfo/KeyInstructions/do.c     |  2 +-
 clang/test/DebugInfo/KeyInstructions/if.c     |  2 +-
 .../test/DebugInfo/KeyInstructions/init-agg.c |  2 +-
 .../DebugInfo/KeyInstructions/init-agg.cpp    | 50 +++++++++++++++++++
 .../DebugInfo/KeyInstructions/init-member.cpp |  2 +-
 .../DebugInfo/KeyInstructions/init-scalar.c   |  4 +-
 .../DebugInfo/KeyInstructions/init-static.cpp |  2 +-
 .../DebugInfo/KeyInstructions/try-catch.cpp   |  2 +-
 clang/test/DebugInfo/KeyInstructions/while.c  |  2 +-
 18 files changed, 123 insertions(+), 28 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/assign.c
 create mode 100644 clang/test/DebugInfo/KeyInstructions/init-agg.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index b422ff6182a0a..a67b0d8a91afb 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -3929,9 +3929,9 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src,
   return R;
 }
 
-void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
-                                         bool EmitRetDbgLoc,
-                                         SourceLocation EndLoc) {
+void CodeGenFunction::EmitFunctionEpilog(
+    const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc,
+    uint64_t RetKeyInstructionsSourceAtom) {
   if (FI.isNoReturn()) {
     // Noreturn functions don't return.
     EmitUnreachable(EndLoc);
@@ -3947,7 +3947,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
   // Functions with no result always return void.
   if (!ReturnValue.isValid()) {
     auto *I = Builder.CreateRetVoid();
-    addRetToOverrideOrNewSourceAtom(I, nullptr);
+    if (RetKeyInstructionsSourceAtom)
+      addInstToSpecificSourceAtom(I, nullptr, RetKeyInstructionsSourceAtom);
+    else
+      addInstToNewSourceAtom(I, nullptr);
     return;
   }
 
@@ -4129,7 +4132,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
     Ret->setDebugLoc(std::move(RetDbgLoc));
 
   llvm::Value *Backup = RV ? Ret->getOperand(0) : nullptr;
-  addRetToOverrideOrNewSourceAtom(cast<llvm::ReturnInst>(Ret), Backup);
+  if (RetKeyInstructionsSourceAtom)
+    addInstToSpecificSourceAtom(Ret, Backup, RetKeyInstructionsSourceAtom);
+  else
+    addInstToNewSourceAtom(Ret, Backup);
 }
 
 void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index f44fc408cc97f..ea34d29c06108 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -342,15 +342,6 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
       // later by the actual 'ret' instruction.
       llvm::DebugLoc Loc = BI->getDebugLoc();
       Builder.SetInsertPoint(BI->getParent());
-
-      // Key Instructions: If there's only one `ret` then we want to put the
-      // instruction in the same source atom group as the store to the ret-value
-      // alloca and unconditional `br` to the return block that we're about to
-      // delete. It all comes from the same source (`return (value)`).
-      if (auto *DI = getDebugInfo(); DI && BI->getDebugLoc())
-        DI->setRetInstSourceAtomOverride(
-            BI->getDebugLoc().get()->getAtomGroup());
-
       BI->eraseFromParent();
       delete ReturnBlock.getBlock();
       ReturnBlock = JumpDest();
@@ -453,8 +444,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
 
   // Reset the debug location to that of the simple 'return' expression, if any
   // rather than that of the end of the function's scope '}'.
+  uint64_t RetKeyInstructionsAtomGroup = Loc ? Loc->getAtomGroup() : 0;
+  llvm::errs() << "RetKeyInstructionsAtomGroup " << RetKeyInstructionsAtomGroup
+               << "\n";
+  if (Loc)
+    llvm::errs() << *Loc << "\n";
   ApplyDebugLocation AL(*this, Loc);
-  EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc);
+  EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc,
+                     RetKeyInstructionsAtomGroup);
   EmitEndEHSpec(CurCodeDecl);
 
   assert(EHStack.empty() &&
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index f0f051a1d26f5..cecc8c0ade729 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2551,9 +2551,12 @@ class CodeGenFunction : public CodeGenTypeCache {
                           const FunctionArgList &Args);
 
   /// EmitFunctionEpilog - Emit the target specific LLVM code to return the
-  /// given temporary.
+  /// given temporary. Specify the source location atom group (Key Instructions
+  /// debug info feature) for the `ret` using \p RetKeyInstructionsSourceAtom.
+  /// If it's 0, the `ret` will get added to a new source atom group.
   void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc,
-                          SourceLocation EndLoc);
+                          SourceLocation EndLoc,
+                          uint64_t RetKeyInstructionsSourceAtom);
 
   /// Emit a test that checks if the return value \p RV is nonnull.
   void EmitReturnValueCheck(llvm::Value *RV);
diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
index f1a406a7bc119..99f62f28d06b5 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -34,4 +34,4 @@ void fun(Struct a) {
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
 // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index 402bb093b6ba6..05c82448d4a55 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -85,3 +85,4 @@ void fun() {
 // CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
 // CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.c b/clang/test/DebugInfo/KeyInstructions/assign.c
new file mode 100644
index 0000000000000..0e96dc82bb1ab
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/assign.c
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+unsigned long long g;
+void fun() {
+// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+    g = 0;
+
+// Treat the two assignments as two atoms.
+//
+// FIXME: Because of the atomGroup implementation the load can only be
+// associated with one of the two stores, despite being a good backup
+// loction for both.
+// CHECK-NEXT: %0 = load i64, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
+    g = g = g;
+
+// Compound assignment.
+// CHECK: %1 = load i64, ptr @g
+// CHECK: %add = add i64 %1, 50, !dbg [[G4R2:!.*]]
+// CHECK: store i64 %add, ptr @g{{.*}}, !dbg [[G4R1:!.*]]
+    g += 50;
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
index 165546d579b70..b6448d9421a3a 100644
--- a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
@@ -16,4 +16,4 @@ void foo(int x, S s) {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c
index 12b4d74d4af33..68ba1a88bb87b 100644
--- a/clang/test/DebugInfo/KeyInstructions/builtin.c
+++ b/clang/test/DebugInfo/KeyInstructions/builtin.c
@@ -88,3 +88,4 @@ void fun() {
 // CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2)
 // CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1)
 // CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index 9673df08cc76b..bb407cf284b57 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -97,3 +97,4 @@ void test() {
 // CHECK-C: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK-C: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
 // CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/do.c b/clang/test/DebugInfo/KeyInstructions/do.c
index 31624b3a78656..a933acc39febf 100644
--- a/clang/test/DebugInfo/KeyInstructions/do.c
+++ b/clang/test/DebugInfo/KeyInstructions/do.c
@@ -33,4 +33,4 @@ void a(int A) {
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/if.c b/clang/test/DebugInfo/KeyInstructions/if.c
index 48621fb3b1976..d9835d0e9a982 100644
--- a/clang/test/DebugInfo/KeyInstructions/if.c
+++ b/clang/test/DebugInfo/KeyInstructions/if.c
@@ -46,4 +46,4 @@ void a(int A) {
 // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK-CXX: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
 // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
index ab20acfb70fc1..0a756a7006331 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -49,4 +49,4 @@ void a() {
 // CHECK: [[big_LINE]] = !DILocation(line: 33, scope: ![[#]])
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
new file mode 100644
index 0000000000000..daf506b0866ac
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -0,0 +1,50 @@
+
+// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -gno-column-info -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// The implicit-check-not is important; we don't want the GEPs created for the
+// store locations to be included in the atom group.
+
+int g;
+void a() {
+// CHECK: _Z1av()
+// CHECK: call void @llvm.memcpy{{.*}}%A, {{.*}}@__const._Z1av.A{{.*}}, !dbg [[G1R1:!.*]]
+    int A[] = { 1, 2, 3 };
+
+// CHECK:      call void @llvm.memcpy{{.*}}%B, {{.*}}@__const._Z1av.B{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK-NEXT: store i32 1, ptr %B{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK-NEXT: %arrayinit.element = getelementptr {{.*}}, ptr %B, i64 1, !dbg [[B_LINE:!.*]]
+// CHECK-NEXT: store i32 2, ptr %arrayinit.element{{.*}}, !dbg [[G2R1]]
+// CHECK-NEXT: %arrayinit.element1 = getelementptr {{.*}}, ptr %B, i64 2, !dbg [[B_LINE]]
+// CHECK-NEXT: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i32 %0, ptr %arrayinit.element1{{.*}}, !dbg [[G2R1]]
+    int B[] = { 1, 2, g };
+
+// CHECK:      call void @llvm.memset{{.*}}%big{{.*}} !dbg [[G3R1:!.*]]
+// CHECK-NEXT: %1 = getelementptr {{.*}}, ptr %big, i32 0, i32 0, !dbg [[big_LINE:!.*]]
+// CHECK-NEXT: store i8 97, ptr %1{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %2 = getelementptr {{.*}}, ptr %big, i32 0, i32 1, !dbg [[big_LINE]]
+// CHECK-NEXT: store i8 98, ptr %2{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %3 = getelementptr {{.*}}, ptr %big, i32 0, i32 2, !dbg [[big_LINE]]
+// CHECK-NEXT: store i8 99, ptr %3{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %4 = getelementptr {{.*}}, ptr %big, i32 0, i32 3, !dbg [[big_LINE]]
+// CHECK: store i8 100, ptr %4{{.*}} !dbg [[G3R1]]
+    char big[65536] = { 'a', 'b', 'c', 'd' };
+
+// CHECK: call void @llvm.memset{{.*}}%arr{{.*}}, !dbg [[G4R1:!.*]]
+    char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
+
+// CHECK: store i8 -86, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
+    char uninit; // -ftrivial-auto-var-init=pattern
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[B_LINE]] = !DILocation(line: 21, scope: ![[#]])
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[big_LINE]] = !DILocation(line: 32, scope: ![[#]])
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
index 99efc4bd49e33..6873ea6938a52 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -21,4 +21,4 @@ void fun() {
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
index 0d690d82a2025..fba02ff5b1b2e 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -10,10 +10,10 @@ void a() {
 // CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
 // CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
     int B = 2 * A + 1;
-// CHECK: ret{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
index 58c38a8c55208..7153a976d370f 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-static.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
@@ -12,4 +12,4 @@ void g(int *a) {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
index d53bd52274503..2b59dc2f7607f 100644
--- a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
@@ -20,4 +20,4 @@ void attempt() {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/while.c b/clang/test/DebugInfo/KeyInstructions/while.c
index be4d16207712b..8d2f965a639fe 100644
--- a/clang/test/DebugInfo/KeyInstructions/while.c
+++ b/clang/test/DebugInfo/KeyInstructions/while.c
@@ -34,4 +34,4 @@ void a(int A) {
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])

>From 155ef268196e6060dd2a539b8d7ded8ea3f00fde Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 17:12:28 +0100
Subject: [PATCH 04/12] cc1

---
 clang/test/DebugInfo/KeyInstructions/return-va-arg.c | 4 ++--
 clang/test/DebugInfo/KeyInstructions/return.c        | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
index 2864489afd738..12f6e21a166a0 100644
--- a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
+++ b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
 
-// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
 
 typedef struct {
diff --git a/clang/test/DebugInfo/KeyInstructions/return.c b/clang/test/DebugInfo/KeyInstructions/return.c
index 24c58450d37ed..62a361fce08f3 100644
--- a/clang/test/DebugInfo/KeyInstructions/return.c
+++ b/clang/test/DebugInfo/KeyInstructions/return.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
 
-// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s
 
 // Check the stores to `retval` allocas and branches to `return` block are in

>From 33f85854717e985fc47ea37a431f050ed2839c49 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 09:32:28 +0100
Subject: [PATCH 05/12] rm rebase weirdness

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index ea34d29c06108..bf962dbdd2b37 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1556,12 +1556,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
       Bypasses.Init(CGM, Body);
   }
 
-  // Finalize function debug info on exit.
-  auto Cleanup = llvm::make_scope_exit([this] {
-    if (CGDebugInfo *DI = getDebugInfo())
-      DI->completeFunction();
-  });
-
   // Emit the standard function prologue.
   StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
 

>From 855854e5664df71c8056ddfe820465f35aba5750 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 09:35:58 +0100
Subject: [PATCH 06/12] rm cruft

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index bf962dbdd2b37..2ac7e9d498044 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -445,10 +445,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
   // Reset the debug location to that of the simple 'return' expression, if any
   // rather than that of the end of the function's scope '}'.
   uint64_t RetKeyInstructionsAtomGroup = Loc ? Loc->getAtomGroup() : 0;
-  llvm::errs() << "RetKeyInstructionsAtomGroup " << RetKeyInstructionsAtomGroup
-               << "\n";
-  if (Loc)
-    llvm::errs() << *Loc << "\n";
   ApplyDebugLocation AL(*this, Loc);
   EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc,
                      RetKeyInstructionsAtomGroup);

>From 2972ae501a88cfba93ab9e7f8af0f26d6216f090 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 10:05:30 +0100
Subject: [PATCH 07/12] fix tests

---
 .../DebugInfo/KeyInstructions/assign-scalar.c   |  1 -
 clang/test/DebugInfo/KeyInstructions/builtin.c  |  1 -
 clang/test/DebugInfo/KeyInstructions/complex.c  |  1 -
 .../test/DebugInfo/KeyInstructions/multi-func.c |  9 +++++++--
 .../DebugInfo/KeyInstructions/return-va-arg.c   |  4 ++--
 clang/test/DebugInfo/KeyInstructions/return.c   | 17 ++++++++++++++---
 6 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index 05c82448d4a55..4719cbc4af532 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -84,5 +84,4 @@ void fun() {
 // CHECK: [[load_i_loc]] = !DILocation(line: [[#]], column: [[#]], scope: ![[#]])
 // CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
 // CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c
index 68ba1a88bb87b..c67daa612109b 100644
--- a/clang/test/DebugInfo/KeyInstructions/builtin.c
+++ b/clang/test/DebugInfo/KeyInstructions/builtin.c
@@ -87,5 +87,4 @@ void fun() {
 // CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3)
 // CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2)
 // CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
 // CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index bb407cf284b57..86443bf965dfe 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -96,5 +96,4 @@ void test() {
 // CHECK-C: [[G10R1]] = !DILocation({{.*}}, atomGroup: 10, atomRank: 1)
 // CHECK-C: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK-C: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
-// CHECK: [[RET:!.*]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
 // CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/multi-func.c b/clang/test/DebugInfo/KeyInstructions/multi-func.c
index 6e225eed81de8..ce311bad00d16 100644
--- a/clang/test/DebugInfo/KeyInstructions/multi-func.c
+++ b/clang/test/DebugInfo/KeyInstructions/multi-func.c
@@ -8,12 +8,17 @@
 
 int g;
 // CHECK: store{{.*}}, !dbg [[AG:!.*]]
+// CHECK: ret{{.*}}, !dbg [[ARET:!.*]]
 void a() { g = 0; }
 
 // CHECK: store{{.*}}, !dbg [[BG:!.*]]
+// CHECK: ret{{.*}}, !dbg [[BRET:!.*]]
 void b() { g = 0; }
 
 // CHECK: [[A:!.*]] = distinct !DISubprogram(name: "a",
-// CHECK: [[AG]] = !DILocation(line: 11, scope: [[A]], atomGroup: 1, atomRank: 1)
+// CHECK: [[AG]] = !DILocation(line: 12, scope: [[A]], atomGroup: 1, atomRank: 1)
+// CHECK: [[ARET]] = !DILocation(line: 12, scope: [[A]], atomGroup: 2, atomRank: 1)
+
 // CHECK: [[B:!.*]] = distinct !DISubprogram(name: "b",
-// CHECK: [[BG]] = !DILocation(line: 14, scope: [[B]], atomGroup: 1, atomRank: 1)
+// CHECK: [[BG]] = !DILocation(line: 16, scope: [[B]], atomGroup: 1, atomRank: 1)
+// CHECK: [[BRET]] = !DILocation(line: 16, scope: [[B]], atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
index 12f6e21a166a0..0773bf5353177 100644
--- a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
+++ b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
 
-// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
 
 typedef struct {
diff --git a/clang/test/DebugInfo/KeyInstructions/return.c b/clang/test/DebugInfo/KeyInstructions/return.c
index 62a361fce08f3..c79e9d930f317 100644
--- a/clang/test/DebugInfo/KeyInstructions/return.c
+++ b/clang/test/DebugInfo/KeyInstructions/return.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
 
-// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s
 
 // Check the stores to `retval` allocas and branches to `return` block are in
@@ -57,6 +57,7 @@ nomangle int d() { return g = 1; }
 
 // The implicit return here get the line number of the closing brace; make it
 // key to match existing behaviour.
+// CHECK: void @e()
 // CHECK: ret void, !dbg [[E_G1R1:!.*]]
 nomangle void e() {}
 
@@ -66,10 +67,17 @@ int &f(int &r) {
 // Include ctrl-flow to stop ret value store being elided.
     if (r)
 // CHECK-CXX: if.then:
-// CHECK-CXX-NEXT: %2 = load ptr, ptr %r.addr{{.*}}, !dbg [[F_G2R2:!.*]]
+// CHECK-CXX-NEXT: %2 = load ptr, ptr %r.addr{{.*}}, !dbg [[F_G2R2:!.*]], !nonnull
 // CHECK-CXX-NEXT: store ptr %2, ptr %retval{{.*}}, !dbg [[F_G2R1:!.*]]
 // CHECK-CXX-NEXT: br label %return, !dbg [[F_G2R1:!.*]]
     return r;
+
+// CHECK-CXX: if.end:
+// CHECK-CXX-NEXT: store ptr @g, ptr %retval{{.*}}, !dbg [[F_G3R1:!.*]]
+// CHECK-CXX-NEXT: br label %return, !dbg [[F_G3R1:!.*]]
+// CHECK-CXX: return:
+// CHECK-CXX-NEXT: %3 = load ptr, ptr %retval{{.*}}, !dbg [[F_G4R2:!.*]]
+// CHECK-CXX-NEXT: ret ptr %3, !dbg [[F_G4R1:!.*]]
   return g;
 }
 #endif
@@ -88,3 +96,6 @@ int &f(int &r) {
 // CHECK: [[E_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK-CXX: [[F_G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK-CXX: [[F_G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK-CXX: [[F_G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK-CXX: [[F_G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK-CXX: [[F_G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)

>From 1fd0c86a9749ca38b0f1cb8dacfe6a4aac65d83c Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 10:11:31 +0100
Subject: [PATCH 08/12] rm tests introduced in flaky rebase

---
 clang/test/DebugInfo/KeyInstructions/assign.c | 36 -------------
 .../DebugInfo/KeyInstructions/init-agg.cpp    | 50 -------------------
 .../DebugInfo/KeyInstructions/init-member.cpp | 24 ---------
 3 files changed, 110 deletions(-)
 delete mode 100644 clang/test/DebugInfo/KeyInstructions/assign.c
 delete mode 100644 clang/test/DebugInfo/KeyInstructions/init-agg.cpp
 delete mode 100644 clang/test/DebugInfo/KeyInstructions/init-member.cpp

diff --git a/clang/test/DebugInfo/KeyInstructions/assign.c b/clang/test/DebugInfo/KeyInstructions/assign.c
deleted file mode 100644
index 0e96dc82bb1ab..0000000000000
--- a/clang/test/DebugInfo/KeyInstructions/assign.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-
-// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-
-unsigned long long g;
-void fun() {
-// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
-    g = 0;
-
-// Treat the two assignments as two atoms.
-//
-// FIXME: Because of the atomGroup implementation the load can only be
-// associated with one of the two stores, despite being a good backup
-// loction for both.
-// CHECK-NEXT: %0 = load i64, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
-// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
-// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
-    g = g = g;
-
-// Compound assignment.
-// CHECK: %1 = load i64, ptr @g
-// CHECK: %add = add i64 %1, 50, !dbg [[G4R2:!.*]]
-// CHECK: store i64 %add, ptr @g{{.*}}, !dbg [[G4R1:!.*]]
-    g += 50;
-// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
-}
-
-// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
-// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
-// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
deleted file mode 100644
index daf506b0866ac..0000000000000
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-
-// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -gno-column-info -emit-llvm -o - -ftrivial-auto-var-init=pattern \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-
-// The implicit-check-not is important; we don't want the GEPs created for the
-// store locations to be included in the atom group.
-
-int g;
-void a() {
-// CHECK: _Z1av()
-// CHECK: call void @llvm.memcpy{{.*}}%A, {{.*}}@__const._Z1av.A{{.*}}, !dbg [[G1R1:!.*]]
-    int A[] = { 1, 2, 3 };
-
-// CHECK:      call void @llvm.memcpy{{.*}}%B, {{.*}}@__const._Z1av.B{{.*}}, !dbg [[G2R1:!.*]]
-// CHECK-NEXT: store i32 1, ptr %B{{.*}}, !dbg [[G2R1:!.*]]
-// CHECK-NEXT: %arrayinit.element = getelementptr {{.*}}, ptr %B, i64 1, !dbg [[B_LINE:!.*]]
-// CHECK-NEXT: store i32 2, ptr %arrayinit.element{{.*}}, !dbg [[G2R1]]
-// CHECK-NEXT: %arrayinit.element1 = getelementptr {{.*}}, ptr %B, i64 2, !dbg [[B_LINE]]
-// CHECK-NEXT: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
-// CHECK-NEXT: store i32 %0, ptr %arrayinit.element1{{.*}}, !dbg [[G2R1]]
-    int B[] = { 1, 2, g };
-
-// CHECK:      call void @llvm.memset{{.*}}%big{{.*}} !dbg [[G3R1:!.*]]
-// CHECK-NEXT: %1 = getelementptr {{.*}}, ptr %big, i32 0, i32 0, !dbg [[big_LINE:!.*]]
-// CHECK-NEXT: store i8 97, ptr %1{{.*}}, !dbg [[G3R1]]
-// CHECK-NEXT: %2 = getelementptr {{.*}}, ptr %big, i32 0, i32 1, !dbg [[big_LINE]]
-// CHECK-NEXT: store i8 98, ptr %2{{.*}}, !dbg [[G3R1]]
-// CHECK-NEXT: %3 = getelementptr {{.*}}, ptr %big, i32 0, i32 2, !dbg [[big_LINE]]
-// CHECK-NEXT: store i8 99, ptr %3{{.*}}, !dbg [[G3R1]]
-// CHECK-NEXT: %4 = getelementptr {{.*}}, ptr %big, i32 0, i32 3, !dbg [[big_LINE]]
-// CHECK: store i8 100, ptr %4{{.*}} !dbg [[G3R1]]
-    char big[65536] = { 'a', 'b', 'c', 'd' };
-
-// CHECK: call void @llvm.memset{{.*}}%arr{{.*}}, !dbg [[G4R1:!.*]]
-    char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
-
-// CHECK: store i8 -86, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
-    char uninit; // -ftrivial-auto-var-init=pattern
-// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
-}
-
-// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[B_LINE]] = !DILocation(line: 21, scope: ![[#]])
-// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
-// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[big_LINE]] = !DILocation(line: 32, scope: ![[#]])
-// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
-// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
deleted file mode 100644
index 6873ea6938a52..0000000000000
--- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s
-
-struct B {
-  float y;
-};
-
-class Cls {
-  public:
-    int x = 1;
-    B b = {5.f};
-};
-
-void fun() {
-  Cls c;
-}
-
-// CHECK: store i32 1, ptr %x{{.*}}, !dbg [[G1R1:!.*]]
-// CHECK: store float 5.000000e+00, ptr %y{{.*}}, !dbg [[G2R1:!.*]]
-// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
-
-// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])

>From f767dac37bad002d504a53b5f6c1de3f3bf0f0a1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 11:05:27 +0100
Subject: [PATCH 09/12] rm comment - don't need to mark sanitizer stores as key

---
 clang/lib/CodeGen/CGStmt.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 35ac2bc95c6ae..7643cd7357938 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1599,7 +1599,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
     CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
     assert(ReturnLocation.isValid() && "No valid return location");
     Builder.CreateStore(SLocPtr, ReturnLocation);
-    //*OCH?*//
   }
 
   // Returning from an outlined SEH helper is UB, and we already warn on it.

>From 3662b0ec84a41aaf5efac54f5aee13d59f3527af Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 11:08:31 +0100
Subject: [PATCH 10/12] re-add accidentally removed test

---
 .../DebugInfo/KeyInstructions/init-member.cpp | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/init-member.cpp

diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
new file mode 100644
index 0000000000000..6873ea6938a52
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+struct B {
+  float y;
+};
+
+class Cls {
+  public:
+    int x = 1;
+    B b = {5.f};
+};
+
+void fun() {
+  Cls c;
+}
+
+// CHECK: store i32 1, ptr %x{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float 5.000000e+00, ptr %y{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])

>From 3dd3e9c0ce18953267686ba7f3c387eb77351581 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 15:19:08 +0100
Subject: [PATCH 11/12] specify expected ret atomGroup

---
 clang/test/DebugInfo/KeyInstructions/agg.c           | 2 +-
 clang/test/DebugInfo/KeyInstructions/assign-scalar.c | 2 +-
 clang/test/DebugInfo/KeyInstructions/bitfield.cpp    | 2 +-
 clang/test/DebugInfo/KeyInstructions/builtin.c       | 2 +-
 clang/test/DebugInfo/KeyInstructions/complex.c       | 5 +++--
 clang/test/DebugInfo/KeyInstructions/do.c            | 2 +-
 clang/test/DebugInfo/KeyInstructions/if.c            | 5 +++--
 clang/test/DebugInfo/KeyInstructions/init-agg.c      | 2 +-
 clang/test/DebugInfo/KeyInstructions/init-member.cpp | 2 +-
 clang/test/DebugInfo/KeyInstructions/init-scalar.c   | 2 +-
 clang/test/DebugInfo/KeyInstructions/init-static.cpp | 2 +-
 clang/test/DebugInfo/KeyInstructions/try-catch.cpp   | 2 +-
 clang/test/DebugInfo/KeyInstructions/while.c         | 2 +-
 13 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
index 99f62f28d06b5..58d923d1d9328 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -34,4 +34,4 @@ void fun(Struct a) {
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
 // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index 4719cbc4af532..0bba1830e42a3 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -84,4 +84,4 @@ void fun() {
 // CHECK: [[load_i_loc]] = !DILocation(line: [[#]], column: [[#]], scope: ![[#]])
 // CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
index b6448d9421a3a..e1d4c264a426a 100644
--- a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp
@@ -16,4 +16,4 @@ void foo(int x, S s) {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c
index c67daa612109b..ce8c6124fe923 100644
--- a/clang/test/DebugInfo/KeyInstructions/builtin.c
+++ b/clang/test/DebugInfo/KeyInstructions/builtin.c
@@ -87,4 +87,4 @@ void fun() {
 // CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3)
 // CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2)
 // CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 16, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index 86443bf965dfe..d5cb67fed99d6 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
 
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C
@@ -96,4 +96,5 @@ void test() {
 // CHECK-C: [[G10R1]] = !DILocation({{.*}}, atomGroup: 10, atomRank: 1)
 // CHECK-C: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
 // CHECK-C: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1)
+// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 8, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/do.c b/clang/test/DebugInfo/KeyInstructions/do.c
index a933acc39febf..cc3749e6e56c5 100644
--- a/clang/test/DebugInfo/KeyInstructions/do.c
+++ b/clang/test/DebugInfo/KeyInstructions/do.c
@@ -33,4 +33,4 @@ void a(int A) {
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/if.c b/clang/test/DebugInfo/KeyInstructions/if.c
index d9835d0e9a982..edadd04cf0e18 100644
--- a/clang/test/DebugInfo/KeyInstructions/if.c
+++ b/clang/test/DebugInfo/KeyInstructions/if.c
@@ -2,7 +2,7 @@
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
 
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C
 
 int g;
 void a(int A) {
@@ -46,4 +46,5 @@ void a(int A) {
 // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK-CXX: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
 // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1)
+// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
index 0a756a7006331..711d8ad3de57f 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -49,4 +49,4 @@ void a() {
 // CHECK: [[big_LINE]] = !DILocation(line: 33, scope: ![[#]])
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
index 6873ea6938a52..0c45c07886d4f 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -21,4 +21,4 @@ void fun() {
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
index fba02ff5b1b2e..217a2496c6751 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -16,4 +16,4 @@ void a() {
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
index 7153a976d370f..ee73275edb761 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-static.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
@@ -12,4 +12,4 @@ void g(int *a) {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
index 2b59dc2f7607f..c1887bc525187 100644
--- a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
@@ -20,4 +20,4 @@ void attempt() {
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/while.c b/clang/test/DebugInfo/KeyInstructions/while.c
index 8d2f965a639fe..9c9eab399f345 100644
--- a/clang/test/DebugInfo/KeyInstructions/while.c
+++ b/clang/test/DebugInfo/KeyInstructions/while.c
@@ -34,4 +34,4 @@ void a(int A) {
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]])
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)

>From 689c1b14be46cd533163d78f985ed652cedc318e Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 3 Jun 2025 15:31:47 +0100
Subject: [PATCH 12/12] update new tests after rebase too

---
 clang/test/DebugInfo/KeyInstructions/cast.c   |  2 ++
 .../KeyInstructions/coerced-packed.c          |  2 ++
 .../DebugInfo/KeyInstructions/coerced-ptr.c   |  2 ++
 .../KeyInstructions/coerced-through-memory.c  |  2 ++
 .../test/DebugInfo/KeyInstructions/coerced.c  |  4 ++++
 clang/test/DebugInfo/KeyInstructions/for.c    | 20 +++++++++++++------
 clang/test/DebugInfo/KeyInstructions/new.cpp  |  3 +++
 clang/test/DebugInfo/KeyInstructions/switch.c |  5 ++++-
 8 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/cast.c b/clang/test/DebugInfo/KeyInstructions/cast.c
index 927a1f2a704c7..62f2c3d1d3e51 100644
--- a/clang/test/DebugInfo/KeyInstructions/cast.c
+++ b/clang/test/DebugInfo/KeyInstructions/cast.c
@@ -13,8 +13,10 @@ void a() {
 // CHECK: %conv = fptosi float %0 to i32{{.*}}, !dbg [[G1R2:!.*]]
 // CHECK: store i32 %conv, ptr %a{{.*}}, !dbg [[G1R1:!.*]]
     int a = g;
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c
index 90ec8420b0d8c..1bd2760149705 100644
--- a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c
@@ -14,7 +14,9 @@ void f() {
 // CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]]
 // CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]]
     S s = getS();
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
index 0002e9051220b..1205b312e43c4 100644
--- a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
@@ -12,8 +12,10 @@ void f() {
 // CHECK: [[i2p:%.*]] = inttoptr i64 %call to ptr, !dbg [[G1R2:!.*]]
 // CHECK: store ptr [[i2p]], ptr [[gep]], align 8, !dbg [[G1R1:!.*]]
     Ptr p = getPtr();
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
index 98361aa9806ef..f8667b73b111b 100644
--- a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
@@ -18,7 +18,9 @@ void f() {
 // CHECK: store [2 x i64] %call, ptr %tmp.coerce, align 8
 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 8 %tmp.coerce, i64 12, i1 false), !dbg [[G1R1:!.*]]
   S s = getS();
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced.c b/clang/test/DebugInfo/KeyInstructions/coerced.c
index b5a254fb641c9..036f6d66fa670 100644
--- a/clang/test/DebugInfo/KeyInstructions/coerced.c
+++ b/clang/test/DebugInfo/KeyInstructions/coerced.c
@@ -16,6 +16,7 @@ void test() {
 // CHECK: %3 = extractvalue { ptr, ptr } %call, 1, !dbg [[G1R2]]
 // CHECK: store ptr %3, ptr {{.*}}, !dbg [[G1R1:!.*]]
   Struct s = get();
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 typedef struct { int i; } Int;
@@ -27,10 +28,13 @@ void test2() {
 // CHECK: %call = call i32 @{{(_Z6)?}}getInt{{v?}}(), !dbg [[T2_G1R2:!.*]]
 // CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Int, ptr %i, i32 0, i32 0
 // CHECK: store i32 %call, ptr [[gep]]{{.*}}, !dbg [[T2_G1R1:!.*]]
+// CHECK: ret{{.*}}, !dbg [[T2_RET:!.*]]
   Int i = getInt();
 }
 
 // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[T2_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[T2_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[T2_RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/for.c b/clang/test/DebugInfo/KeyInstructions/for.c
index 89345db9fb85f..e7c1567c14d60 100644
--- a/clang/test/DebugInfo/KeyInstructions/for.c
+++ b/clang/test/DebugInfo/KeyInstructions/for.c
@@ -27,6 +27,7 @@ void a(int A) {
 // CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]]
   for (int i = 0; i < A; ++i) {
   }
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 void b(int A) {
@@ -55,6 +56,7 @@ void b(int A) {
     if (A > 1)
       ;
   }
+// CHECK: ret{{.*}}, !dbg [[bRET:!.*]]
 }
 
 void c(int A) {
@@ -111,6 +113,7 @@ void e() {
 // CHECK-NEXT: br label %for.inc, !dbg [[eG4R1:!.*]]
   for (; i < 3; ee())
     x = i;
+// CHECK: ret{{.*}}, !dbg [[eRET:!.*]]
 }
 
 
@@ -138,6 +141,7 @@ void g() {
   {
     break;
   }
+// CHECK: ret{{.*}}, !dbg [[gRET:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -146,30 +150,34 @@ void g() {
 // CHECK: [[G5R1]] = !DILocation(line: 29,{{.*}} atomGroup: 5, atomRank: 1)
 // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1)
 
 // CHECK: [[bG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[bG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[bG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
 // CHECK: [[bG4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[bG4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
-// CHECK: [[bG6R1]] = !DILocation(line: 57,{{.*}} atomGroup: 6, atomRank: 1)
+// CHECK: [[bG6R1]] = !DILocation(line: 58,{{.*}} atomGroup: 6, atomRank: 1)
 // CHECK: [[bG5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
 // CHECK: [[bG5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK: [[bRET]] = !DILocation({{.*}}, atomGroup: 7, atomRank: 1)
 
 // CHECK: [[cG1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
 // CHECK: [[cG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-// CHECK: [[cG3R1]] = !DILocation(line: 81,{{.*}} atomGroup: 3, atomRank: 1)
+// CHECK: [[cG3R1]] = !DILocation(line: 83,{{.*}} atomGroup: 3, atomRank: 1)
 // CHECK: [[cG2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK: [[cG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 
-// CHECK: [[dG1R1]] = !DILocation(line: 91, column: 3, scope: ![[#]], atomGroup: 1, atomRank: 1)
+// CHECK: [[dG1R1]] = !DILocation(line: 93, column: 3, scope: ![[#]], atomGroup: 1, atomRank: 1)
 
 // CHECK: [[eG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[eG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
 // CHECK: [[eG3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
 // CHECK: [[eG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[eG4R1]] = !DILocation(line: 113, column: 5, scope: ![[#]], atomGroup: 4, atomRank: 1)
+// CHECK: [[eG4R1]] = !DILocation(line: 115, column: 5, scope: ![[#]], atomGroup: 4, atomRank: 1)
+// CHECK: [[eRET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
 
-// CHECK: [[fG1R1]] = !DILocation(line: 126, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1)
+// CHECK: [[fG1R1]] = !DILocation(line: 129, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1)
 
-// CHECK: [[gG1R1]] = !DILocation(line: 139, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1)
+// CHECK: [[gG1R1]] = !DILocation(line: 142, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1)
+// CHECK: [[gRET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/new.cpp b/clang/test/DebugInfo/KeyInstructions/new.cpp
index 5ac2cf31d1380..f939e784a4575 100644
--- a/clang/test/DebugInfo/KeyInstructions/new.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/new.cpp
@@ -18,6 +18,7 @@ void f(int x) {
 // CHECK: %3 = load ptr, ptr %n
 // CHECK: store i32 %2, ptr %3{{.*}}, !dbg [[G3R1:!.*]]
   *n = x;
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G1R2_C12]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
@@ -32,3 +33,5 @@ void f(int x) {
 
 // CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
 // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+
+// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/switch.c b/clang/test/DebugInfo/KeyInstructions/switch.c
index 96b18592621d5..cd8fced67eed9 100644
--- a/clang/test/DebugInfo/KeyInstructions/switch.c
+++ b/clang/test/DebugInfo/KeyInstructions/switch.c
@@ -2,7 +2,7 @@
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
 
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
-// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C
 
 int g;
 void a(int A, int B) {
@@ -40,6 +40,7 @@ void a(int A, int B) {
     }
     };
     }
+// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
 
 // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
@@ -49,3 +50,5 @@ void a(int A, int B) {
 // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
 // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
 // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1)
+// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)



More information about the cfe-commits mailing list