https://github.com/OCHyams updated https://github.com/llvm/llvm-project/pull/134652
>From fc97db31e40af460d2d6a2ba6df94f932cb1c8cb Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Fri, 4 Apr 2025 16:28:39 +0100 Subject: [PATCH 01/11] [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/CGCleanup.cpp | 2 + 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 +++++++++++++++++++ 6 files changed, 146 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 bd920a2e3f2dd..36f02b262385a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3938,7 +3938,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; } @@ -4118,6 +4119,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/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 7e1c5b7da9552..7292dcd47172c 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -1118,6 +1118,8 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Create the branch. llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock()); + // This is the primary instruction for this atom, acting in place of a ret. + addInstToCurrentSourceAtom(BI, nullptr); // Calculate the innermost active normal cleanup. EHScopeStack::stable_iterator diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 31d64a5a788ee..e819c17f367e1 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1571,6 +1571,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 = @@ -1580,6 +1581,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. @@ -1646,16 +1648,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 4193f0a1b278f..043d89bb9cd85 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -341,6 +341,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(); @@ -1549,6 +1558,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 e692b9a3e6d76b19e666005704ba29be64efdb57 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Fri, 4 Apr 2025 16:36:53 +0100 Subject: [PATCH 02/11] [KeyInstr][Clang] Update tests with ret atoms --- clang/test/DebugInfo/KeyInstructions/agg.c | 3 ++ .../DebugInfo/KeyInstructions/assign-scalar.c | 2 + .../DebugInfo/KeyInstructions/bitfield.cpp | 3 ++ .../test/DebugInfo/KeyInstructions/builtin.c | 2 + .../test/DebugInfo/KeyInstructions/complex.c | 2 + clang/test/DebugInfo/KeyInstructions/do.c | 3 ++ clang/test/DebugInfo/KeyInstructions/for.c | 40 +++++++++++++++++++ clang/test/DebugInfo/KeyInstructions/if.c | 3 ++ .../test/DebugInfo/KeyInstructions/init-agg.c | 3 ++ .../DebugInfo/KeyInstructions/init-member.cpp | 2 + .../DebugInfo/KeyInstructions/init-scalar.c | 2 + .../DebugInfo/KeyInstructions/init-static.cpp | 6 ++- clang/test/DebugInfo/KeyInstructions/switch.c | 3 ++ .../DebugInfo/KeyInstructions/try-catch.cpp | 3 ++ clang/test/DebugInfo/KeyInstructions/while.c | 3 ++ 15 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 clang/test/DebugInfo/KeyInstructions/for.c 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/for.c b/clang/test/DebugInfo/KeyInstructions/for.c new file mode 100644 index 0000000000000..1830b28dc7926 --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/for.c @@ -0,0 +1,40 @@ +// 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 + +// Perennial quesiton: should the inc be its own source atom or not +// (currently it is). + +// FIXME: See do.c and while.c regarding cmp and cond br groups. + +void a(int A) { +// CHECK: entry: +// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[G1R1:!.*]] +// CHECK: for.cond: +// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[G2R1:!.*]] +// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[G3R1:!.*]] + +// FIXME: Added uncond br group here which is useful for O0, which we're +// no longer targeting. With optimisations loop rotate puts the condition +// into for.inc and simplifycfg smooshes that and for.body together, so +// it's not clear whether it adds any value. +// CHECK: for.body: +// CHECK: br label %for.inc, !dbg [[G5R1:!.*]] + +// CHECK: for.inc: +// CHECK: %inc = add{{.*}}, !dbg [[G4R2:!.*]] +// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]] + for (int i = 0; i < A; ++i) { } + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] +} + +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) +// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, 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/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/switch.c b/clang/test/DebugInfo/KeyInstructions/switch.c index 5142f204ff587..cb3672cb45381 100644 --- a/clang/test/DebugInfo/KeyInstructions/switch.c +++ b/clang/test/DebugInfo/KeyInstructions/switch.c @@ -41,6 +41,8 @@ void a(int A, int B) { } break; default: break; } + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) @@ -49,3 +51,4 @@ void a(int A, int B) { // CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, 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 64594a835536e1401712826af42347e0e2ebb683 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Wed, 21 May 2025 17:09:46 +0100 Subject: [PATCH 03/11] 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/for.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 +- clang/test/DebugInfo/KeyInstructions/switch.c | 2 +- .../DebugInfo/KeyInstructions/try-catch.cpp | 2 +- clang/test/DebugInfo/KeyInstructions/while.c | 2 +- 20 files changed, 125 insertions(+), 30 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 36f02b262385a..6e5cb71e059e2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3921,9 +3921,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); @@ -3939,7 +3939,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; } @@ -4121,7 +4124,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 043d89bb9cd85..56ce9133c1c85 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -341,15 +341,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(); @@ -452,8 +443,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 92e9ab8156ad2..d38a0628fe1eb 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2612,9 +2612,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/for.c b/clang/test/DebugInfo/KeyInstructions/for.c index 1830b28dc7926..a99cf27e91464 100644 --- a/clang/test/DebugInfo/KeyInstructions/for.c +++ b/clang/test/DebugInfo/KeyInstructions/for.c @@ -37,4 +37,4 @@ void a(int A) { // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, 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/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/switch.c b/clang/test/DebugInfo/KeyInstructions/switch.c index cb3672cb45381..09bbad2b22fe9 100644 --- a/clang/test/DebugInfo/KeyInstructions/switch.c +++ b/clang/test/DebugInfo/KeyInstructions/switch.c @@ -51,4 +51,4 @@ void a(int A, int B) { // CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, 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 5966afcfb187df30acb80f57745fbc599534b1fe Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Wed, 21 May 2025 17:12:28 +0100 Subject: [PATCH 04/11] 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 cc95976e0c2677fc5a7b2f613c9212c4e4947b02 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 09:32:28 +0100 Subject: [PATCH 05/11] 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 56ce9133c1c85..1d5dbacd21cb8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1555,12 +1555,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 922bd4dba180eece3f42bc1255110ce66697e9d5 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 09:35:58 +0100 Subject: [PATCH 06/11] 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 1d5dbacd21cb8..11fce271c868e 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -444,10 +444,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 5ddda1d240e9130d427e371782b69b82b6f6e92c Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 09:47:12 +0100 Subject: [PATCH 07/11] rm test not yet in main --- clang/test/DebugInfo/KeyInstructions/for.c | 40 ---------------------- 1 file changed, 40 deletions(-) delete mode 100644 clang/test/DebugInfo/KeyInstructions/for.c diff --git a/clang/test/DebugInfo/KeyInstructions/for.c b/clang/test/DebugInfo/KeyInstructions/for.c deleted file mode 100644 index a99cf27e91464..0000000000000 --- a/clang/test/DebugInfo/KeyInstructions/for.c +++ /dev/null @@ -1,40 +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 - -// Perennial quesiton: should the inc be its own source atom or not -// (currently it is). - -// FIXME: See do.c and while.c regarding cmp and cond br groups. - -void a(int A) { -// CHECK: entry: -// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[G1R1:!.*]] -// CHECK: for.cond: -// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[G2R1:!.*]] -// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[G3R1:!.*]] - -// FIXME: Added uncond br group here which is useful for O0, which we're -// no longer targeting. With optimisations loop rotate puts the condition -// into for.inc and simplifycfg smooshes that and for.body together, so -// it's not clear whether it adds any value. -// CHECK: for.body: -// CHECK: br label %for.inc, !dbg [[G5R1:!.*]] - -// CHECK: for.inc: -// CHECK: %inc = add{{.*}}, !dbg [[G4R2:!.*]] -// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]] - for (int i = 0; i < A; ++i) { } - -// CHECK: ret{{.*}}, !dbg [[RET:!.*]] -} - -// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) -// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) -// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) -// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) -// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) -// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) -// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: [[#]], atomRank: [[#]]) >From ab88feb11e437bcd6555c273ead1847a8aa8620e Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 10:05:30 +0100 Subject: [PATCH 08/11] 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 ddda5e3c705240f54befc4c0df03b87d25cd8bc6 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 10:11:31 +0100 Subject: [PATCH 09/11] 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 93a95ddd7baef3fe3697cf8297cb3da85c5d799a Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 11:05:27 +0100 Subject: [PATCH 10/11] 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 e819c17f367e1..3629b77cecb37 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1581,7 +1581,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 37c869ab01e37ba041f74154b44c85c909746138 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <orlando.hy...@sony.com> Date: Tue, 3 Jun 2025 11:08:31 +0100 Subject: [PATCH 11/11] 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: [[#]]) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits