From b15c48b4e62ecc05fb3482058ceb0eac82d1acbf Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Thu, 29 May 2025 14:18:36 +0100 Subject: [PATCH 1/7] enable in build --- llvm/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 206f009b45f59..2cf98e4334a5c 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -573,7 +573,7 @@ set(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "DISABLED" CACHE STRING set_property(CACHE LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING PROPERTY STRINGS DISABLED COVERAGE) option(LLVM_EXPERIMENTAL_KEY_INSTRUCTIONS - "Add additional fields to DILocations to support Key Instructions" OFF) + "Add additional fields to DILocations to support Key Instructions" ON) set(WINDOWS_PREFER_FORWARD_SLASH_DEFAULT OFF) if (MINGW) From b1051897f1cdb39bde69596f8ff656a4ec92c9d6 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Thu, 29 May 2025 14:20:18 +0100 Subject: [PATCH 2/7] enable in clang by default2 --- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 2d676aa0b9c8e..7446605127cf8 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4609,7 +4609,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, } if (Args.hasFlag(options::OPT_gkey_instructions, - options::OPT_gno_key_instructions, false)) { + options::OPT_gno_key_instructions, true)) { CmdArgs.push_back("-gkey-instructions"); CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-dwarf-use-key-instructions"); From 527fb0cef686e1787f3acf06976cf6babd7222af Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Fri, 6 Jun 2025 16:52:59 +0100 Subject: [PATCH 3/7] [KeyInstr] Introduce "always key" sentinel atomGroup: n, atomRank: 0 indicates an instruction is always to be treated as a key instruction. This is currently only used in DILocation::getMergedLocation to ease the path to DISubprogram-owned nextAtomGroup counters (rather than tracking it globally). --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 14 +++-- llvm/lib/IR/DebugInfoMetadata.cpp | 11 ++-- .../X86/dwarf-key-sentinel.mir | 63 +++++++++++++++++++ llvm/unittests/IR/MetadataTest.cpp | 10 +-- 4 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5fb74a016a75e..c78257fcfca10 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2415,15 +2415,19 @@ void DwarfDebug::computeKeyInstructions(const MachineFunction *MF) { const auto &TII = *MI.getParent()->getParent()->getSubtarget().getInstrInfo(); bool IsCallLike = MI.isCall() || TII.isTailCall(MI); - if (IsCallLike) { + // (Group: n, Rank: 0) is a sentinel that means disregard AtomGroup and + // emit as is_stmt, typically generated while merging instructions. + bool IsKeySentinel = + MI.getDebugLoc()->getAtomGroup() && !MI.getDebugLoc()->getAtomRank(); + if (IsKeySentinel || IsCallLike) { assert(MI.getDebugLoc() && "Unexpectedly missing DL"); - // Calls are always key. Put the buoy (may not be the call) into + // These are always key. Put the buoy (may not be this inst) into // KeyInstructions directly rather than the candidate map to avoid it - // being erased (and we may not have a group number for the call). + // being erased (and we may not have a group number for a call inst). KeyInstructions.insert(Buoy); - // Avoid floating any future is_stmts up to the call. + // Avoid floating any future is_stmts up to this instruction. Buoy = nullptr; BuoyAtom = 0; @@ -2435,7 +2439,7 @@ void DwarfDebug::computeKeyInstructions(const MachineFunction *MF) { auto *InlinedAt = MI.getDebugLoc()->getInlinedAt(); uint64_t Group = MI.getDebugLoc()->getAtomGroup(); uint8_t Rank = MI.getDebugLoc()->getAtomRank(); - if (!Group || !Rank) + if (!Group) continue; // Don't let is_stmts float past instructions from different source atoms. diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 473114b99225b..b7b23bfdacfca 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -383,12 +383,11 @@ DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) { Group = UseL1Atom ? L1->getAtomGroup() : L2->getAtomGroup(); Rank = UseL1Atom ? L1->getAtomRank() : L2->getAtomRank(); } else { - // If either instruction is part of a source atom, reassign it a new - // atom group. This essentially regresses to non-key-instructions - // behaviour (now that it's the only instruction in its group it'll - // probably get is_stmt applied). - Group = C.incNextDILocationAtomGroup(); - Rank = 1; + // If either instruction is part of a source atom, reassign it a sentinel + // atom rank. This causes the instruction to get is_stmt, ignoring other + // instructions in the group (and the other instructions ignore this one). + Group = L1->getAtomGroup() ? L1->getAtomGroup() : L2->getAtomGroup(); + Rank = 0; } return DILocation::get(C, Line, Col, Scope, InlinedAt, IsImplicitCode, Group, Rank); diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir new file mode 100644 index 0000000000000..d47ac70a9cb5b --- /dev/null +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir @@ -0,0 +1,63 @@ +# RUN: llc %s --start-after=livedebugvalues --dwarf-use-key-instructions --filetype=obj -o - \ +# RUN: | llvm-objdump -d - --no-show-raw-insn \ +# RUN: | FileCheck %s --check-prefix=OBJ + +# RUN: llc %s --start-after=livedebugvalues --dwarf-use-key-instructions --filetype=obj -o - \ +# RUN: | llvm-dwarfdump - --debug-line \ +# RUN: | FileCheck %s --check-prefix=DBG + +# OBJ: 0000000000000000 : +# OBJ-NEXT: 0: movl $0x0, %eax +# OBJ-NEXT: 5: movl $0x1, %eax +# OBJ-NEXT: a: movl $0x2, %eax +# OBJ-NEXT: f: movl $0x3, %eax +# OBJ-NEXT: 14: retq + +# DBG: Address Line Column File ISA Discriminator OpIndex Flags +# DBG-NEXT: ------------------ ------ ------ ------ --- ------------- ------- ------------- +# DBG-NEXT: 0x0000000000000000 1 0 0 0 0 0 is_stmt prologue_end +# DBG-NEXT: 0x0000000000000005 2 0 0 0 0 0 is_stmt +# DBG-NEXT: 0x000000000000000f 2 0 0 0 0 0 is_stmt +# DBG-NEXT: 0x0000000000000014 2 0 0 0 0 0 is_stmt + +## (atomGroup: n, atomRank: 0) is a sentinel that means "ignore the group and +## this is always Key. Check the is_stmt for `MOV32ri 2` (0xa) floats up to +## `MOV32ri 1` (0x5), and that the subsequent sentinel and normal key +## instruction get is_stmt. As per usual, is_stmts can't float up past other +## is_stmts. + +--- | + target triple = "x86_64-unknown-linux-gnu" + + define hidden noundef i32 @f() local_unnamed_addr !dbg !5 { + entry: + ret i32 3 + } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!2, !3} + !llvm.ident = !{!4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_17, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None) + !1 = !DIFile(filename: "test.cpp", directory: "/") + !2 = !{i32 7, !"Dwarf Version", i32 5} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = !{!"clang version 19.0.0"} + !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) + !6 = !DISubroutineType(types: !7) + !7 = !{} + +... +--- +name: f +alignment: 16 +body: | + bb.0.entry: + + $eax = MOV32ri 0, debug-location !DILocation(line: 1, scope: !5) + $eax = MOV32ri 1, debug-location !DILocation(line: 2, scope: !5) + $eax = MOV32ri 2, debug-location !DILocation(line: 2, scope: !5, atomGroup: 1, atomRank: 0) + $eax = MOV32ri 3, debug-location !DILocation(line: 2, scope: !5, atomGroup: 1, atomRank: 0) + RET64 $eax, debug-location !DILocation(line: 2, scope: !5, atomGroup: 1, atomRank: 1) + +... diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index df415602cef59..f6fbca19b2393 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -1592,7 +1592,9 @@ TEST_F(DILocationTest, Merge) { // Partially equal inlined-at chain but different atoms. Generate a new atom // group (if either have a group number). This configuration seems unlikely - // to occur as line numbers must match, but isn't impossible. + // to occur as line numbers must match, but isn't impossible. AtomRank=0 is + // a sentinel that indicates the instruction is in its own undefined atom + // group. { // Reset global counter to ensure EXPECT numbers line up. Context.pImpl->NextAtomGroup = 1; @@ -1609,7 +1611,7 @@ TEST_F(DILocationTest, Merge) { auto *M = DILocation::getMergedLocation(X1IntoY2, Y3IntoZ4); EXPECT_EQ(M->getScope(), FY); EXPECT_EQ(M->getInlinedAt()->getScope(), FZ); - EXPECT_ATOM(M, /*AtomGroup*/ 2u, /*AtomRank*/ 1u); + EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 0u); // This swapped merge will produce a new atom group too. M = DILocation::getMergedLocation(Y3IntoZ4, X1IntoY2); @@ -1618,9 +1620,9 @@ TEST_F(DILocationTest, Merge) { auto *X1IntoY2SameAtom = DILocation::get(Context, 1, 1, FX, Y2IntoZ4, false, /*AtomGroup*/ 1, /*AtomRank*/ 1); M = DILocation::getMergedLocation(X1IntoY2SameAtom, Y3IntoZ4); - EXPECT_ATOM(M, /*AtomGroup*/ 4u, /*AtomRank*/ 1u); + EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 0u); M = DILocation::getMergedLocation(Y3IntoZ4, X1IntoY2SameAtom); - EXPECT_ATOM(M, /*AtomGroup*/ 5u, /*AtomRank*/ 1u); + EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 0u); } #undef EXPECT_ATOM } From d1b961aded895b70c8c12f33c338e88e8083834c Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Tue, 13 May 2025 17:01:34 +0100 Subject: [PATCH 4/7] DISubprogram nextAtomGroup and bitcode --- clang/lib/CodeGen/CGDebugInfo.cpp | 6 +- llvm/include/llvm/IR/DIBuilder.h | 3 +- llvm/include/llvm/IR/DebugInfoMetadata.h | 87 +++++++++++++++---- llvm/include/llvm/IR/LLVMContext.h | 8 -- llvm/include/llvm/Transforms/Utils/Cloning.h | 5 +- llvm/lib/AsmParser/LLParser.cpp | 5 +- llvm/lib/CodeGen/MIRParser/MIParser.cpp | 4 +- llvm/lib/CodeGen/WinEHPrepare.cpp | 4 +- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 2 +- llvm/lib/IR/AsmWriter.cpp | 2 + llvm/lib/IR/DIBuilder.cpp | 6 +- llvm/lib/IR/DebugInfoMetadata.cpp | 78 ++++++++++++++--- llvm/lib/IR/LLVMContext.cpp | 8 -- llvm/lib/IR/LLVMContextImpl.h | 16 +--- .../ControlHeightReduction.cpp | 3 +- .../Transforms/Scalar/DFAJumpThreading.cpp | 4 +- llvm/lib/Transforms/Scalar/JumpThreading.cpp | 6 +- .../Transforms/Scalar/SimpleLoopUnswitch.cpp | 9 +- .../Transforms/Utils/BreakCriticalEdges.cpp | 3 +- llvm/lib/Transforms/Utils/CloneFunction.cpp | 32 ++++--- llvm/lib/Transforms/Utils/Debugify.cpp | 6 +- llvm/lib/Transforms/Utils/InlineFunction.cpp | 25 ++++++ llvm/lib/Transforms/Utils/LoopConstrainer.cpp | 3 +- llvm/lib/Transforms/Utils/LoopPeel.cpp | 3 +- .../Transforms/Utils/LoopRotationUtils.cpp | 6 +- llvm/lib/Transforms/Utils/LoopUnroll.cpp | 3 +- .../lib/Transforms/Utils/LoopUnrollAndJam.cpp | 3 +- .../Transforms/Utils/LoopUnrollRuntime.cpp | 3 +- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 4 +- .../KeyInstructions/Generic/inline-nodbg.ll | 4 +- .../KeyInstructions/Generic/inline.ll | 6 +- .../Generic/jump-threading-2-bbs.ll | 3 +- .../Generic/jump-threading-basic.ll | 3 +- ...-threading-dup-cond-br-on-phi-into-pred.ll | 3 +- .../KeyInstructions/Generic/loop-rotate.ll | 12 ++- .../Generic/loop-unroll-runtime.ll | 3 +- .../KeyInstructions/Generic/loop-unroll.ll | 2 +- .../KeyInstructions/Generic/loop-unswitch.ll | 3 +- .../KeyInstructions/Generic/parse.ll | 3 +- .../Generic/simplifycfg-branch-fold.ll | 4 +- .../Generic/simplifycfg-thread-phi.ll | 4 +- .../X86/cgp-break-critical-edge.ll | 3 +- .../KeyInstructions/X86/dwarf-basic-ranks.ll | 14 +-- .../KeyInstructions/X86/dwarf-basic.ll | 16 ++-- .../X86/dwarf-buoy-multi-key.mir | 2 +- .../KeyInstructions/X86/dwarf-buoy.mir | 2 +- .../KeyInstructions/X86/dwarf-calls.ll | 41 ++++++--- .../X86/dwarf-key-sentinel.mir | 2 +- .../KeyInstructions/X86/dwarf-ranks-blocks.ll | 26 ++++-- .../DebugInfo/KeyInstructions/X86/parse.mir | 3 +- .../DebugInfo/KeyInstructions/debugify.ll | 3 + llvm/unittests/IR/BasicBlockDbgInfoTest.cpp | 5 +- llvm/unittests/IR/MetadataTest.cpp | 47 +++++----- .../Transforms/Utils/CloningTest.cpp | 12 +-- 54 files changed, 379 insertions(+), 194 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index ee5e3d68a5ffa..097abdcd3cd9c 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1904,7 +1904,8 @@ CGDebugInfo::createInlinedSubprogram(StringRef FuncName, /*ScopeLine=*/0, /*Flags=*/llvm::DINode::FlagArtificial, /*SPFlags=*/llvm::DISubprogram::SPFlagDefinition, - /*TParams=*/nullptr, /*ThrownTypes=*/nullptr, /*Annotations=*/nullptr); + /*TParams=*/nullptr, /*ThrownTypes=*/nullptr, /*Annotations=*/nullptr, + nullptr, StringRef(), CGM.getCodeGenOpts().DebugKeyInstructions); } return SP; @@ -4686,8 +4687,9 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc, llvm::DISubprogram *SP = DBuilder.createFunction( FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl, nullptr, - Annotations); + Annotations, "", CGM.getCodeGenOpts().DebugKeyInstructions); Fn->setSubprogram(SP); + // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls // as they will overwrite the actual VarDecl Decl in the cache. diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index ebfe41dd59afb..71ba7e3d7a0c8 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -905,7 +905,8 @@ namespace llvm { DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, DITemplateParameterArray TParams = nullptr, DISubprogram *Decl = nullptr, DITypeArray ThrownTypes = nullptr, - DINodeArray Annotations = nullptr, StringRef TargetFuncName = ""); + DINodeArray Annotations = nullptr, StringRef TargetFuncName = "", + bool UseKeyInstructions = false); /// Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 02f0a9f677db3..d274f991f6c99 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1976,6 +1976,9 @@ class DISubprogram : public DILocalScope { /// negative. int ThisAdjustment; + /// Not serialised. + uint32_t NextAtomGroup = 0; // set to 1 to mark as "has key insts" + public: /// Debug info subprogram flags. enum DISPFlags : uint32_t { @@ -2003,6 +2006,29 @@ class DISubprogram : public DILocalScope { unsigned Virtuality = SPFlagNonvirtual, bool IsMainSubprogram = false); + uint32_t incNextDILocationAtomGroup() { + assert(isDefinition() && getKeyInstructionsEnabled()); + // NOTE: This may wrap, which effectively disables Key Instructions for + // this function (as long as getNextDILocationAtomGroup is checked before + // the next call). As a result, instances that have already been inlined + // will also have Key Instructions disabled for them, since we look back + // to this DISubprogram to check if it's enabled during DWARF emission. + // A quirk of the implementation that only shows up in extreme edge cases. + return NextAtomGroup++; + } + uint32_t getNextDILocationAtomGroup() const { + assert(getKeyInstructionsEnabled()); + return NextAtomGroup; + } + bool getKeyInstructionsEnabled() const { return NextAtomGroup; } + /// Key Instructions: update the highest number atom group emitted for any + /// function. + void updateDILocationAtomGroupWaterline(uint32_t G) { + assert(getKeyInstructionsEnabled()); + // FIXME: should really be G+1, if the waterline is "current max". + NextAtomGroup = std::max(NextAtomGroup, G); + } + private: DIFlags Flags; DISPFlags SPFlags; @@ -2021,15 +2047,37 @@ class DISubprogram : public DILocalScope { DITemplateParameterArray TemplateParams, DISubprogram *Declaration, DINodeArray RetainedNodes, DITypeArray ThrownTypes, DINodeArray Annotations, StringRef TargetFuncName, - StorageType Storage, bool ShouldCreate = true) { + uint32_t NextAtomGroup, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams.get(), Declaration, RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), - getCanonicalMDString(Context, TargetFuncName), + getCanonicalMDString(Context, TargetFuncName), NextAtomGroup, Storage, ShouldCreate); } + + static DISubprogram * + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, + DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, + unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, + DISPFlags SPFlags, DICompileUnit *Unit, + DITemplateParameterArray TemplateParams, DISubprogram *Declaration, + DINodeArray RetainedNodes, DITypeArray ThrownTypes, + DINodeArray Annotations, StringRef TargetFuncName, + bool UseKeyInstructions, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, + Flags, SPFlags, Unit, TemplateParams.get(), Declaration, + RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), + getCanonicalMDString(Context, TargetFuncName), + static_cast(UseKeyInstructions), Storage, + ShouldCreate); + } LLVM_ABI static DISubprogram * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, @@ -2037,7 +2085,7 @@ class DISubprogram : public DILocalScope { int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, - MDString *TargetFuncName, StorageType Storage, + MDString *TargetFuncName, uint32_t NextAtomGroup, StorageType Storage, bool ShouldCreate = true); TempDISubprogram cloneImpl() const { @@ -2047,7 +2095,7 @@ class DISubprogram : public DILocalScope { getThisAdjustment(), getFlags(), getSPFlags(), getUnit(), getTemplateParams(), getDeclaration(), getRetainedNodes(), getThrownTypes(), getAnnotations(), - getTargetFuncName()); + getTargetFuncName()); // TODO: Key Instructions Stuff! } public: @@ -2060,10 +2108,11 @@ class DISubprogram : public DILocalScope { DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr, - StringRef TargetFuncName = ""), + StringRef TargetFuncName = "", uint32_t UseKeyInstructions = false), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) + Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName, + UseKeyInstructions)) DEFINE_MDNODE_GET( DISubprogram, @@ -2073,10 +2122,12 @@ class DISubprogram : public DILocalScope { DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, - Metadata *Annotations = nullptr, MDString *TargetFuncName = nullptr), + Metadata *Annotations = nullptr, MDString *TargetFuncName = nullptr, + uint32_t UseKeyInstructions = 0), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) + Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName, + UseKeyInstructions)) TempDISubprogram clone() const { return cloneImpl(); } @@ -2245,23 +2296,23 @@ class DILocation : public MDNode { friend class LLVMContextImpl; friend class MDNode; #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS - uint64_t AtomGroup : 61; - uint64_t AtomRank : 3; + uint32_t AtomGroup : 29; + uint32_t AtomRank : 3; #endif - DILocation(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, uint64_t AtomGroup, uint8_t AtomRank, - ArrayRef MDs, bool ImplicitCode); + DILocation(LLVMContext &C, StorageType Storage, DISubprogram *SP, + unsigned Line, unsigned Column, uint32_t AtomGroup, + uint8_t AtomRank, ArrayRef MDs, bool ImplicitCode); ~DILocation() { dropAllReferences(); } LLVM_ABI static DILocation * getImpl(LLVMContext &Context, unsigned Line, unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup, + Metadata *InlinedAt, bool ImplicitCode, uint32_t AtomGroup, uint8_t AtomRank, StorageType Storage, bool ShouldCreate = true); static DILocation *getImpl(LLVMContext &Context, unsigned Line, unsigned Column, DILocalScope *Scope, DILocation *InlinedAt, bool ImplicitCode, - uint64_t AtomGroup, uint8_t AtomRank, + uint32_t AtomGroup, uint8_t AtomRank, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Line, Column, static_cast(Scope), static_cast(InlinedAt), ImplicitCode, AtomGroup, @@ -2277,7 +2328,7 @@ class DILocation : public MDNode { } public: - uint64_t getAtomGroup() const { + uint32_t getAtomGroup() const { #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS return AtomGroup; #else @@ -2305,13 +2356,13 @@ class DILocation : public MDNode { DEFINE_MDNODE_GET(DILocation, (unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt = nullptr, bool ImplicitCode = false, - uint64_t AtomGroup = 0, uint8_t AtomRank = 0), + uint32_t AtomGroup = 0, uint8_t AtomRank = 0), (Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup, AtomRank)) DEFINE_MDNODE_GET(DILocation, (unsigned Line, unsigned Column, DILocalScope *Scope, DILocation *InlinedAt = nullptr, bool ImplicitCode = false, - uint64_t AtomGroup = 0, uint8_t AtomRank = 0), + uint32_t AtomGroup = 0, uint8_t AtomRank = 0), (Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup, AtomRank)) diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index 852a3a4e2f638..012f97ebb6ba2 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -341,14 +341,6 @@ class LLVMContext { LLVM_ABI StringRef getDefaultTargetFeatures(); LLVM_ABI void setDefaultTargetFeatures(StringRef Features); - /// Key Instructions: update the highest number atom group emitted for any - /// function. - LLVM_ABI void updateDILocationAtomGroupWaterline(uint64_t G); - - /// Key Instructions: get the next free atom group number and increment - /// the global tracker. - LLVM_ABI uint64_t incNextDILocationAtomGroup(); - private: // Module needs access to the add/removeModule methods. friend class Module; diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h index 6b56230a6e1d4..c5078caa509e6 100644 --- a/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -130,13 +130,14 @@ struct ClonedCodeInfo { /// but is sometimes unnecessary, causing extra work that could be avoided by /// setting the parameter to false. LLVM_ABI BasicBlock * -CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, +CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, DISubprogram *SP, const Twine &NameSuffix = "", Function *F = nullptr, ClonedCodeInfo *CodeInfo = nullptr, bool MapAtoms = true); /// Mark a cloned instruction as a new instance so that its source loc can /// be updated when remapped. -LLVM_ABI void mapAtomInstance(const DebugLoc &DL, ValueToValueMapTy &VMap); +LLVM_ABI void mapAtomInstance(DISubprogram *Target, const DebugLoc &DL, + ValueToValueMapTy &VMap); /// Return a copy of the specified function and add it to that /// function's module. Also, any references specified in the VMap are changed diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index b933d240c4d27..d4cd41bbe5cf7 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5823,7 +5823,8 @@ bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) { OPTIONAL(retainedNodes, MDField, ); \ OPTIONAL(thrownTypes, MDField, ); \ OPTIONAL(annotations, MDField, ); \ - OPTIONAL(targetFuncName, MDStringField, ); + OPTIONAL(targetFuncName, MDStringField, ); \ + OPTIONAL(nextAtomGroup, MDUnsignedField, (0, UINT32_MAX)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5843,7 +5844,7 @@ bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) { type.Val, scopeLine.Val, containingType.Val, virtualIndex.Val, thisAdjustment.Val, flags.Val, SPFlags, unit.Val, templateParams.Val, declaration.Val, retainedNodes.Val, thrownTypes.Val, annotations.Val, - targetFuncName.Val)); + targetFuncName.Val, nextAtomGroup.Val)); return false; } diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 3a364d5ff0d20..04a03e53bcd45 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -2332,8 +2332,8 @@ bool MIParser::parseDILocation(MDNode *&Loc) { MDNode *Scope = nullptr; MDNode *InlinedAt = nullptr; bool ImplicitCode = false; - uint64_t AtomGroup = 0; - uint64_t AtomRank = 0; + uint32_t AtomGroup = 0; + uint32_t AtomRank = 0; if (expectAndConsume(MIToken::lparen)) return true; diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 66d29cb5d65e4..abb576b64b205 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -943,8 +943,8 @@ bool WinEHPrepareImpl::cloneCommonBlocks(Function &F) { << "\'.\n"); // Create a new basic block and copy instructions into it! - BasicBlock *CBB = - CloneBasicBlock(BB, VMap, Twine(".for.", FuncletPadBB->getName())); + BasicBlock *CBB = CloneBasicBlock( + BB, VMap, F.getSubprogram(), Twine(".for.", FuncletPadBB->getName())); // Insert the clone immediately after the original to ensure determinism // and to keep the same relative ordering of any funclet's blocks. CBB->insertInto(&F, BB->getNextNode()); diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index ca3d8438654dc..e59703417121b 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -5407,7 +5407,7 @@ void OpenMPIRBuilder::createIfVersion(CanonicalLoopInfo *CanonicalLoop, VMap[CanonicalLoop->getPreheader()] = ElseBlock; for (BasicBlock *Block : L->getBlocks()) { - BasicBlock *NewBB = CloneBasicBlock(Block, VMap, "", F); + BasicBlock *NewBB = CloneBasicBlock(Block, VMap, F->getSubprogram(), "", F); NewBB->moveBefore(CanonicalLoop->getExit()); VMap[Block] = NewBB; NewBlocks.push_back(NewBB); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 7223dd845d18d..b9c16c8b29f2b 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2452,6 +2452,8 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N, Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); Printer.printMetadata("annotations", N->getRawAnnotations()); Printer.printString("targetFuncName", N->getTargetFuncName()); + if (N->getKeyInstructionsEnabled()) + Printer.printInt("nextAtomGroup", N->getNextDILocationAtomGroup()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 5e5ff22132e99..baeb52219b5eb 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -934,14 +934,14 @@ DISubprogram *DIBuilder::createFunction( unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, DISubprogram *Decl, - DITypeArray ThrownTypes, DINodeArray Annotations, - StringRef TargetFuncName) { + DITypeArray ThrownTypes, DINodeArray Annotations, StringRef TargetFuncName, + bool UseKeyInstructions) { bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, ScopeLine, nullptr, 0, 0, Flags, SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, nullptr, - ThrownTypes, Annotations, TargetFuncName); + ThrownTypes, Annotations, TargetFuncName, UseKeyInstructions); AllSubprograms.push_back(Node); trackIfUnresolved(Node); diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index b7b23bfdacfca..a807130c0c8aa 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -19,8 +19,10 @@ #include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Function.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -63,9 +65,10 @@ DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI) : DebugVariable(DVI->getVariable(), std::nullopt, DVI->getDebugLoc()->getInlinedAt()) {} -DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, uint64_t AtomGroup, uint8_t AtomRank, - ArrayRef MDs, bool ImplicitCode) +DILocation::DILocation(LLVMContext &C, StorageType Storage, DISubprogram *Fn, + unsigned Line, unsigned Column, uint32_t AtomGroup, + uint8_t AtomRank, ArrayRef MDs, + bool ImplicitCode) : MDNode(C, DILocationKind, Storage, MDs) #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS , @@ -75,8 +78,23 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line, #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits"); #endif - if (AtomGroup) - C.updateDILocationAtomGroupWaterline(AtomGroup + 1); + // OCH huurrrr + + // if (AtomGroup) + // C.updateDILocationAtomGroupWaterline(AtomGroup + 1); + if (AtomGroup) { + // assert(Fn); + // assert(Fn->isDefinition()); + if (Fn) { + // Fn might be a temporary during parsing, which sucks but there we go. + // allow null for now - probably need to verify somewhere? + // this occurs e.g. + // !1 = ... inlinedAt !2 // < temporary + // !2 = ... + assert(Fn->isDefinition()); + Fn->updateDILocationAtomGroupWaterline(AtomGroup + 1); + } + } assert((MDs.size() == 1 || MDs.size() == 2) && "Expected a scope and optional inlined-at"); @@ -98,7 +116,7 @@ static void adjustColumn(unsigned &Column) { DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt, bool ImplicitCode, - uint64_t AtomGroup, uint8_t AtomRank, + uint32_t AtomGroup, uint8_t AtomRank, StorageType Storage, bool ShouldCreate) { // Fixup column. adjustColumn(Column); @@ -117,10 +135,38 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, SmallVector Ops; Ops.push_back(Scope); + if (InlinedAt) Ops.push_back(InlinedAt); + + DISubprogram *SP = nullptr; + // all this BS should go away, we should just delay checks to verifier and add + // comments explaining why! (or keep checks but streamline) + // gotta keep checks because obvs optimisations + FE need to update thru this. + // TODO: Prettify, and verify. + if (isa_and_nonnull(Scope) && cast(Scope)->isResolved()) { + if (auto *LS = dyn_cast_or_null(Scope)) { + if (LS->isResolved()) { + if (!isa(LS) || + (cast(LS)->getRawScope() && + cast(cast(LS)->getRawScope()) + ->isResolved())) { + SP = LS->getSubprogram(); + if (InlinedAt) { + assert(SP); + if (!cast(InlinedAt)->isResolved()) + SP = nullptr; + else { + auto *X = cast(InlinedAt)->getInlinedAtScope(); + SP = X->getSubprogram(); + } + } + } + } + } + } return storeImpl(new (Ops.size(), Storage) - DILocation(Context, Storage, Line, Column, AtomGroup, + DILocation(Context, Storage, SP, Line, Column, AtomGroup, AtomRank, Ops, ImplicitCode), Storage, Context.pImpl->DILocations); } @@ -1395,10 +1441,11 @@ DISubprogram *DISubprogram::getImpl( int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName, - StorageType Storage, bool ShouldCreate) { + uint32_t NextAtomGroup, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); assert(isCanonical(TargetFuncName) && "Expected canonical MDString"); + // TODO: Key on UseKeyInstructions??? DEFINE_GETIMPL_LOOKUP(DISubprogram, (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, @@ -1424,10 +1471,17 @@ DISubprogram *DISubprogram::getImpl( } } } - DEFINE_GETIMPL_STORE_N( - DISubprogram, - (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags, SPFlags), Ops, - Ops.size()); + DISubprogram *SP = [&]() { + DEFINE_GETIMPL_STORE_N( + DISubprogram, + (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags, SPFlags), Ops, + Ops.size()); + }(); + if (NextAtomGroup) { + assert(SP->isDistinct()); + SP->NextAtomGroup = NextAtomGroup; + } + return SP; } bool DISubprogram::describes(const Function *F) const { diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index 57532cd491dd6..447e5d92e0b99 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -377,11 +377,3 @@ StringRef LLVMContext::getDefaultTargetFeatures() { void LLVMContext::setDefaultTargetFeatures(StringRef Features) { pImpl->DefaultTargetFeatures = Features; } - -void LLVMContext::updateDILocationAtomGroupWaterline(uint64_t V) { - pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V); -} - -uint64_t LLVMContext::incNextDILocationAtomGroup() { - return pImpl->NextAtomGroup++; -} diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 87cd52e357be2..60f168f734914 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -316,12 +316,12 @@ template <> struct MDNodeKeyImpl { Metadata *InlinedAt; bool ImplicitCode; #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS - uint64_t AtomGroup : 61; - uint64_t AtomRank : 3; + uint32_t AtomGroup : 29; + uint32_t AtomRank : 3; #endif MDNodeKeyImpl(unsigned Line, uint16_t Column, Metadata *Scope, - Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup, + Metadata *InlinedAt, bool ImplicitCode, uint32_t AtomGroup, uint8_t AtomRank) : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt), ImplicitCode(ImplicitCode) @@ -1886,16 +1886,6 @@ class LLVMContextImpl { std::string DefaultTargetCPU; std::string DefaultTargetFeatures; - - /// The next available source atom group number. The front end is responsible - /// for assigning source atom numbers, but certain optimisations need to - /// assign new group numbers to a set of instructions. Most often code - /// duplication optimisations like loop unroll. Tracking a global maximum - /// value means we can know (cheaply) we're never using a group number that's - /// already used within this function. - /// - /// Start a 1 because 0 means the source location isn't part of an atom group. - uint64_t NextAtomGroup = 1; }; } // end namespace llvm diff --git a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp index c14bbecf0d4e1..1525c8202de82 100644 --- a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp +++ b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp @@ -1765,7 +1765,8 @@ void CHR::cloneScopeBlocks(CHRScope *Scope, for (BasicBlock *BB : RI.R->blocks()) { // This includes the blocks in the // sub-Scopes. assert(BB != PreEntryBlock && "Don't copy the preetntry block"); - BasicBlock *NewBB = CloneBasicBlock(BB, VMap, ".nonchr", &F); + BasicBlock *NewBB = + CloneBasicBlock(BB, VMap, F.getSubprogram(), ".nonchr", &F); NewBlocks.push_back(NewBB); VMap[BB] = NewBB; diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp index 938aab5879044..a044e5245c954 100644 --- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp @@ -1085,8 +1085,8 @@ struct TransformDFA { DomTreeUpdater *DTU) { ValueToValueMapTy VMap; BasicBlock *NewBB = CloneBasicBlock( - BB, VMap, ".jt" + std::to_string(NextState.getLimitedValue()), - BB->getParent()); + BB, VMap, BB->getParent()->getSubprogram(), + ".jt" + std::to_string(NextState.getLimitedValue()), BB->getParent()); NewBB->moveAfter(BB); NumCloned++; diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 9449b4cb35b93..062dc47c8fb02 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -2084,7 +2084,7 @@ void JumpThreadingPass::cloneInstructions(ValueToValueMapTy &ValueMapping, NewPN->addIncoming(PN->getIncomingValueForBlock(PredBB), PredBB); ValueMapping[PN] = NewPN; if (const DebugLoc &DL = PN->getDebugLoc()) - mapAtomInstance(DL, ValueMapping); + mapAtomInstance(PN->getFunction()->getSubprogram(), DL, ValueMapping); } // Clone noalias scope declarations in the threaded block. When threading a @@ -2114,7 +2114,7 @@ void JumpThreadingPass::cloneInstructions(ValueToValueMapTy &ValueMapping, CloneAndRemapDbgInfo(New, &*BI); if (const DebugLoc &DL = New->getDebugLoc()) - mapAtomInstance(DL, ValueMapping); + mapAtomInstance(New->getFunction()->getSubprogram(), DL, ValueMapping); if (RetargetDbgValueIfPossible(New)) continue; @@ -2723,7 +2723,7 @@ bool JumpThreadingPass::duplicateCondBranchOnPHIIntoPred( // Remap debug variable operands. remapDebugVariable(ValueMapping, New); if (const DebugLoc &DL = New->getDebugLoc()) - mapAtomInstance(DL, ValueMapping); + mapAtomInstance(New->getFunction()->getSubprogram(), DL, ValueMapping); // If this instruction can be simplified after the operands are updated, // just use the simplified value instead. This frequently happens due to diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 0bf90036b8b82..c69c8e8305cbe 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -298,10 +298,9 @@ static void buildPartialInvariantUnswitchConditionalBranch( Instruction *Inst = cast(Val); Instruction *NewInst = Inst->clone(); - if (const DebugLoc &DL = Inst->getDebugLoc()) - mapAtomInstance(DL, VMap); - NewInst->insertInto(&BB, BB.end()); + if (const DebugLoc &DL = Inst->getDebugLoc()) + mapAtomInstance(Inst->getFunction()->getSubprogram(), DL, VMap); RemapInstruction(NewInst, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); VMap[Val] = NewInst; @@ -1183,7 +1182,9 @@ static BasicBlock *buildClonedLoopBlocks( // a helper. auto CloneBlock = [&](BasicBlock *OldBB) { // Clone the basic block and insert it before the new preheader. - BasicBlock *NewBB = CloneBasicBlock(OldBB, VMap, ".us", OldBB->getParent()); + BasicBlock *NewBB = + CloneBasicBlock(OldBB, VMap, LoopPH->getParent()->getSubprogram(), + ".us", OldBB->getParent()); NewBB->moveBefore(LoopPH); // Record this block and the mapping. diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp index ddd203f3acf71..7400cbc28924f 100644 --- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -405,7 +405,8 @@ bool llvm::SplitIndirectBrCriticalEdges(Function &F, // block's body. Create a copy of Target that will be used by the "direct" // preds. ValueToValueMapTy VMap; - BasicBlock *DirectSucc = CloneBasicBlock(Target, VMap, ".clone", &F); + BasicBlock *DirectSucc = + CloneBasicBlock(Target, VMap, F.getSubprogram(), ".clone", &F); if (!VMap.AtomMap.empty()) for (Instruction &I : *DirectSucc) RemapSourceAtom(&I, VMap); diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 5487dbef8a434..2c10ac26257e3 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -43,11 +43,20 @@ using namespace llvm; STATISTIC(RemappedAtomMax, "Highest global NextAtomGroup (after mapping)"); -void llvm::mapAtomInstance(const DebugLoc &DL, ValueToValueMapTy &VMap) { - auto CurGroup = DL->getAtomGroup(); +void llvm::mapAtomInstance(DISubprogram *Target, const DebugLoc &DL, + ValueToValueMapTy &VMap) { + assert(!Target || Target->isDefinition()); + if (!Target || !Target->getKeyInstructionsEnabled()) + return; + + auto CurGroup = DL.get()->getAtomGroup(); if (!CurGroup) return; +#ifdef EXPENSIVE_CHECKS + assert(Target == DL->getInlinedAtScope()->getSubprogram()); +#endif + // Try inserting a new entry. If there's already a mapping for this atom // then there's nothing to do. auto [It, Inserted] = VMap.AtomMap.insert({{DL.getInlinedAt(), CurGroup}, 0}); @@ -55,7 +64,7 @@ void llvm::mapAtomInstance(const DebugLoc &DL, ValueToValueMapTy &VMap) { return; // Map entry to a new atom group. - uint64_t NewGroup = DL->getContext().incNextDILocationAtomGroup(); + uint32_t NewGroup = Target->incNextDILocationAtomGroup(); assert(NewGroup > CurGroup && "Next should always be greater than current"); It->second = NewGroup; @@ -111,8 +120,9 @@ MetadataPredicate createIdentityMDPredicate(const Function &F, /// See comments in Cloning.h. BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, - const Twine &NameSuffix, Function *F, - ClonedCodeInfo *CodeInfo, bool MapAtoms) { + DISubprogram *SP, const Twine &NameSuffix, + Function *F, ClonedCodeInfo *CodeInfo, + bool MapAtoms) { BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F); NewBB->IsNewDbgInfoFormat = BB->IsNewDbgInfoFormat; if (BB->hasName()) @@ -133,7 +143,7 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, if (MapAtoms) { if (const DebugLoc &DL = NewInst->getDebugLoc()) - mapAtomInstance(DL.get(), VMap); + mapAtomInstance(SP, DL.get(), VMap); } if (isa(I) && !I.isDebugOrPseudoInst()) { @@ -238,8 +248,8 @@ void llvm::CloneFunctionBodyInto(Function &NewFunc, const Function &OldFunc, for (const BasicBlock &BB : OldFunc) { // Create a new basic block and copy instructions into it! - BasicBlock *CBB = - CloneBasicBlock(&BB, VMap, NameSuffix, &NewFunc, CodeInfo); + BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NewFunc.getSubprogram(), + NameSuffix, &NewFunc, CodeInfo); // Add basic block mapping. VMap[&BB] = CBB; @@ -1057,7 +1067,8 @@ Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, BasicBlock *OrigPH = OrigLoop->getLoopPreheader(); assert(OrigPH && "No preheader"); - BasicBlock *NewPH = CloneBasicBlock(OrigPH, VMap, NameSuffix, F); + BasicBlock *NewPH = + CloneBasicBlock(OrigPH, VMap, F->getSubprogram(), NameSuffix, F); // To rename the loop PHIs. VMap[OrigPH] = NewPH; Blocks.push_back(NewPH); @@ -1089,7 +1100,8 @@ Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, Loop *&NewLoop = LMap[CurLoop]; assert(NewLoop && "Expecting new loop to be allocated"); - BasicBlock *NewBB = CloneBasicBlock(BB, VMap, NameSuffix, F); + BasicBlock *NewBB = + CloneBasicBlock(BB, VMap, F->getSubprogram(), NameSuffix, F); VMap[BB] = NewBB; // Update LoopInfo. diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 729813a92f516..4ac4b53841d91 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -123,7 +123,9 @@ bool llvm::applyDebugifyMetadata( if (F.hasPrivateLinkage() || F.hasInternalLinkage()) SPFlags |= DISubprogram::SPFlagLocalToUnit; auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, - SPType, NextLine, DINode::FlagZero, SPFlags); + SPType, NextLine, DINode::FlagZero, SPFlags, + nullptr, nullptr, nullptr, nullptr, "", + /*UseKeyInstructions*/ ApplyAtomGroups); F.setSubprogram(SP); // Helper that inserts a dbg.value before \p InsertBefore, copying the @@ -145,7 +147,7 @@ bool llvm::applyDebugifyMetadata( for (BasicBlock &BB : F) { // Attach debug locations. for (Instruction &I : BB) { - uint64_t AtomGroup = ApplyAtomGroups ? NextLine : 0; + uint32_t AtomGroup = ApplyAtomGroups ? NextLine : 0; uint8_t AtomRank = ApplyAtomGroups ? 1 : 0; uint64_t Line = NextLine++; I.setDebugLoc(DILocation::get(Ctx, Line, 1, SP, nullptr, false, diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 7a9605bf5f8d4..4705a7547285d 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1917,10 +1917,32 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, DVR->setDebugLoc(IDL); }; + // Update the atomGroup waterline (from inlined instructions) if both + // functions were built with Key Instructions. The result at DWARF emission + // is: + // + // Key Instructions before/after inlining? + // caller + callee -> caller + callee + // caller only -> caller only + // callee only -> neither + // neither -> neither + // + // `callee only -> callee only` isn't supported due to how + // `getKeyInstructionsEnabled` is implemented, and because it would be + // expensive to assume all functions may contain Key Instructions if none + // do. + bool KeyInstructions = Fn->getSubprogram()->getKeyInstructionsEnabled(); + uint32_t MaxInlineAtom = 0; + // Iterate over all instructions, updating metadata and debug-info records. for (; FI != Fn->end(); ++FI) { for (Instruction &I : *FI) { UpdateInst(I); + + if (KeyInstructions) + if (auto &DL = I.getDebugLoc()) + MaxInlineAtom = std::max(MaxInlineAtom, DL->getAtomGroup()); + for (DbgRecord &DVR : I.getDbgRecordRange()) { UpdateDVR(&DVR); } @@ -1940,6 +1962,9 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, } } } + + if (KeyInstructions) + Fn->getSubprogram()->updateDILocationAtomGroupWaterline(MaxInlineAtom + 1); } #undef DEBUG_TYPE diff --git a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp index 8f103153059e8..63994d66ccbec 100644 --- a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp +++ b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp @@ -468,7 +468,8 @@ LoopConstrainer::LoopConstrainer(Loop &L, LoopInfo &LI, void LoopConstrainer::cloneLoop(LoopConstrainer::ClonedLoop &Result, const char *Tag) const { for (BasicBlock *BB : OriginalLoop.getBlocks()) { - BasicBlock *Clone = CloneBasicBlock(BB, Result.Map, Twine(".") + Tag, &F); + BasicBlock *Clone = CloneBasicBlock(BB, Result.Map, F.getSubprogram(), + Twine(".") + Tag, &F); Result.Blocks.push_back(Clone); Result.Map[BB] = Clone; } diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp index f343962548259..db7e2032bfeed 100644 --- a/llvm/lib/Transforms/Utils/LoopPeel.cpp +++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp @@ -848,7 +848,8 @@ static void cloneLoopBlocks( // For each block in the original loop, create a new copy, // and update the value map with the newly created values. for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { - BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, ".peel", F); + BasicBlock *NewBB = + CloneBasicBlock(*BB, VMap, F->getSubprogram(), ".peel", F); NewBlocks.push_back(NewBB); // If an original block is an immediate child of the loop L, its copy diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index 693b1f517f8d0..c9f7ae690071a 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -657,11 +657,11 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // Otherwise, create a duplicate of the instruction. Instruction *C = Inst->clone(); - if (const DebugLoc &DL = C->getDebugLoc()) - mapAtomInstance(DL, ValueMap); - C->insertBefore(LoopEntryBranch->getIterator()); + if (const DebugLoc &DL = C->getDebugLoc()) + mapAtomInstance(C->getFunction()->getSubprogram(), DL, ValueMap); + ++NumInstrsDuplicated; if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat && diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp index 86b268de43cf6..c92fcd42abd44 100644 --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -717,7 +717,8 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { ValueToValueMapTy VMap; - BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It)); + BasicBlock *New = CloneBasicBlock( + *BB, VMap, Header->getParent()->getSubprogram(), "." + Twine(It)); Header->getParent()->insert(BlockInsertPt, New); assert((*BB != Header || LI->getLoopFor(*BB) == L) && diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp index ca90bb65f5708..900fa6d973b0f 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -369,7 +369,8 @@ llvm::UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount, for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { ValueToValueMapTy VMap; - BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It)); + BasicBlock *New = CloneBasicBlock( + *BB, VMap, Header->getParent()->getSubprogram(), "." + Twine(It)); Header->getParent()->insert(Header->getParent()->end(), New); // Tell LI about New. diff --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index bf882d7406853..6ed22cdb9780c 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -355,7 +355,8 @@ CloneLoopBlocks(Loop *L, Value *NewIter, const bool UseEpilogRemainder, // For each block in the original loop, create a new copy, // and update the value map with the newly created values. for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { - BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, "." + suffix, F); + BasicBlock *NewBB = + CloneBasicBlock(*BB, VMap, F->getSubprogram(), "." + suffix, F); NewBlocks.push_back(NewBB); addClonedBlockToLoopInfo(*BB, NewBB, LI, NewLoops); diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index e221022bb8361..b8ffd22dc7a05 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1139,7 +1139,7 @@ static void cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses( // dead code caused by folding dead branches. NewBonusInst->setDebugLoc(DebugLoc()); } else if (const DebugLoc &DL = NewBonusInst->getDebugLoc()) { - mapAtomInstance(DL, VMap); + mapAtomInstance(BonusInst.getFunction()->getSubprogram(), DL, VMap); } } @@ -3606,7 +3606,7 @@ foldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU, // Update operands due to translation. // Key Instructions: Remap all the atom groups. if (const DebugLoc &DL = BBI->getDebugLoc()) - mapAtomInstance(DL, TranslateMap); + mapAtomInstance(BBI->getFunction()->getSubprogram(), DL, TranslateMap); RemapInstruction(N, TranslateMap, RF_IgnoreMissingLocals | RF_NoModuleLevelChanges); diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/inline-nodbg.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/inline-nodbg.ll index 33f7f673d91c3..0d107c00247f0 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/inline-nodbg.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/inline-nodbg.ll @@ -11,6 +11,8 @@ ; CHECK: _Z1bv() ; CHECK: store i32 1, ptr @g, align 4, !dbg [[DBG:!.*]] + +; CHECK: distinct !DISubprogram(name: "b", {{.*}}nextAtomGroup: 3) ; CHECK: [[DBG]] = !DILocation(line: 3, scope: ![[#]]) @g = hidden global i32 0, align 4 @@ -36,7 +38,7 @@ entry: !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!15 = distinct !DISubprogram(name: "b", scope: !1, file: !1, line: 3, type: !16, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!15 = distinct !DISubprogram(name: "b", scope: !1, file: !1, line: 3, type: !16, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !16 = !DISubroutineType(types: !17) !17 = !{} !18 = !DILocation(line: 3, scope: !15, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/inline.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/inline.ll index b9b6abdd1e9c0..a4cd790625ec3 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/inline.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/inline.ll @@ -8,6 +8,7 @@ ; CHECK: %add.i = add nsw i32 %mul.i, 1, !dbg [[G1R2:!.*]] ; CHECK-NEXT: store i32 %add.i, ptr %x.i, align 4, !dbg [[G1R1:!.*]] +; CHECK: distinct !DISubprogram(name: "g", {{.*}}nextAtomGroup: 2) ; CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) ; CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -41,11 +42,10 @@ entry: !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !12 = !DISubroutineType(types: !13) !13 = !{} !19 = !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) !20 = !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 1) -!23 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!23 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 1) !24 = !DILocation(line: 5, scope: !23) - diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-2-bbs.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-2-bbs.ll index 612e74792fac2..3c39cc569f531 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-2-bbs.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-2-bbs.ll @@ -27,6 +27,7 @@ ; CHECK: bb.f2: ; CHECK-NEXT: store ptr @a, ptr %p, align 4, !dbg [[G4R1:!.*]] +; CHECK: distinct !DISubprogram(name: "foo", {{.*}}nextAtomGroup: 5) ; CHECK: [[G1R2]] = !DILocation(line: 1, column: 1, scope: ![[#]], atomGroup: 1, atomRank: 2) ; CHECK: [[G1R1]] = !DILocation(line: 1, column: 1, scope: ![[#]], atomGroup: 1, atomRank: 1) ; CHECK: [[G3R2]] = !DILocation(line: 1, column: 1, scope: ![[#]], atomGroup: 3, atomRank: 2) @@ -76,7 +77,7 @@ declare void @f2() !2 = !{i32 16} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !6 = !DISubroutineType(types: !7) !7 = !{} !9 = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 2) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-basic.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-basic.ll index 1541df3469087..1797c351b84e2 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-basic.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-basic.ll @@ -26,6 +26,7 @@ ; CHECK-NEXT: %C = add i32 %v2, 1, !dbg [[G1R2:!.*]] ; CHECK-NEXT: store i32 %C, ptr %p, align 4, !dbg [[G1R1:!.*]] +; CHECK: distinct !DISubprogram(name: "test1", {{.*}}nextAtomGroup: 3) ; CHECK: [[G2R2]] = !DILocation(line: 8, column: 1, scope: ![[#]], atomGroup: 2, atomRank: 2) ; CHECK: [[G2R1]] = !DILocation(line: 8, column: 1, scope: ![[#]], atomGroup: 2, atomRank: 1) ; CHECK: [[G1R2]] = !DILocation(line: 8, column: 1, scope: ![[#]], atomGroup: 1, atomRank: 2) @@ -70,7 +71,7 @@ declare void @f3() !2 = !{i32 12} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "test1", linkageName: "test1", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "test1", linkageName: "test1", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocation(line: 8, column: 1, scope: !5, atomGroup: 1, atomRank: 2) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-dup-cond-br-on-phi-into-pred.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-dup-cond-br-on-phi-into-pred.ll index 1ab1c1ac2e9f6..2acfb54ac4392 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-dup-cond-br-on-phi-into-pred.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/jump-threading-dup-cond-br-on-phi-into-pred.ll @@ -30,6 +30,7 @@ ; CHECK-NEXT: %C = add i32 %v2, 1, !dbg [[G2R2:!.*]] ; CHECK-NEXT: store i32 %C, ptr %p, align 4, !dbg [[G2R1:!.*]] +; CHECK: distinct !DISubprogram(name: "test5", {{.*}}nextAtomGroup: 4) ; CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) ; CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) ; CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -79,7 +80,7 @@ declare void @f3() !2 = !{i32 12} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "test5", linkageName: "test5", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "test5", linkageName: "test5", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-rotate.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-rotate.ll index 6da7146b5b07a..352706dd2a8fd 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-rotate.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-rotate.ll @@ -25,6 +25,7 @@ ; CHECK: [[CMP:%.*]] = icmp slt i32 {{.*}}, 100, !dbg [[G2R2:![0-9]+]] ; CHECK: br i1 [[CMP]], label %for.body, label %for.end, !dbg [[G2R1:![0-9]+]] ; +; CHECK: distinct !DISubprogram(name: "test1", {{.*}}nextAtomGroup: 5) ; CHECK: [[G3R1]] = !DILocation(line: 4{{.*}}, atomGroup: 3, atomRank: 1) ; CHECK: [[G4R1]] = !DILocation(line: 6{{.*}}, atomGroup: 4, atomRank: 1) ; CHECK: [[G1R1]] = !DILocation(line: 4{{.*}}, atomGroup: 1, atomRank: 1) @@ -40,9 +41,9 @@ entry: for.cond: ; preds = %for.body, %entry %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] - store i32 %i.0, ptr @glob, align 16, !dbg !DILocation(line: 4, scope: !5, atomGroup: 1, atomRank: 1) - %cmp = icmp slt i32 %i.0, 100, !dbg !DILocation(line: 5, scope: !5, atomGroup: 2, atomRank: 2) - br i1 %cmp, label %for.body, label %for.end, !dbg !DILocation(line: 6, scope: !5, atomGroup: 2, atomRank: 1) + store i32 %i.0, ptr @glob, align 16, !dbg !8 + %cmp = icmp slt i32 %i.0, 100, !dbg !9 + br i1 %cmp, label %for.body, label %for.end, !dbg !10 for.body: ; preds = %for.cond %inc = add nsw i32 %i.0, 1 @@ -69,6 +70,9 @@ attributes #1 = { noduplicate } !2 = !{i32 12} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "test1", linkageName: "test1", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "test1", linkageName: "test1", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !6 = !DISubroutineType(types: !7) !7 = !{} +!8 = !DILocation(line: 4, scope: !5, atomGroup: 1, atomRank: 1) +!9 = !DILocation(line: 5, scope: !5, atomGroup: 2, atomRank: 2) +!10 = !DILocation(line: 6, scope: !5, atomGroup: 2, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll-runtime.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll-runtime.ll index 6deb04cc00f8d..06deab8be50a6 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll-runtime.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll-runtime.ll @@ -25,6 +25,7 @@ ; CHECK-NEXT: store i64 %indvars.iv.next.2, ptr %p, align 4, !dbg [[G7R1:!.*]] ; CHECK-NEXT: %indvars.iv.next.3 = add nuw nsw i64 %indvars.iv, 4 +; CHECK: distinct !DISubprogram(name: "unroll", {{.*}}nextAtomGroup: 8) ; CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) ; CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) ; CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) @@ -63,7 +64,7 @@ for.body: ; preds = %for.body, %for.body !2 = !{i32 17} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "unroll", linkageName: "unroll", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "unroll", linkageName: "unroll", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll.ll index 557e8387e5bc5..2eb07d9fc738c 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unroll.ll @@ -41,7 +41,7 @@ attributes #0 = { nounwind ssp uwtable } !2 = !{i32 8} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !11 = !DILocation(line: 4, column: 1, scope: !5, atomGroup: 1, atomRank: 2) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unswitch.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unswitch.ll index 557950439ef3b..2752330650200 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unswitch.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/loop-unswitch.ll @@ -125,7 +125,7 @@ declare void @clobber() !2 = !{i32 13} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "partial_unswitch_true_successor_hoist_invariant", linkageName: "partial_unswitch_true_successor_hoist_invariant", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "partial_unswitch_true_successor_hoist_invariant", linkageName: "partial_unswitch_true_successor_hoist_invariant", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 14) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocation(line: 1, scope: !5, atomGroup: 1, atomRank: 1) @@ -142,6 +142,7 @@ declare void @clobber() !19 = !DILocation(line: 12, scope: !5, atomGroup: 12, atomRank: 1) !20 = !DILocation(line: 13, scope: !5, atomGroup: 13, atomRank: 1) ;. +; CHECK: distinct !DISubprogram(name: "partial_unswitch_true_successor_hoist_invariant", {{.*}}nextAtomGroup: 27) ; CHECK: [[DBG8]] = !DILocation(line: 3{{.*}}, atomGroup: 24, atomRank: 1) ; CHECK: [[DBG9]] = !DILocation(line: 4{{.*}}, atomGroup: 25, atomRank: 1) ; CHECK: [[DBG10]] = !DILocation(line: 5{{.*}}, atomGroup: 26, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll index 33219a582fee8..2232b84e47e83 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll @@ -1,5 +1,6 @@ ; RUN: opt %s -o - -S| FileCheck %s +; CHECK: distinct !DISubprogram(name: "f", {{.*}}nextAtomGroup: 2) ; CHECK: !DILocation(line: 1, column: 11, scope: ![[#]], atomGroup: 1, atomRank: 1) define dso_local void @f() !dbg !10 { @@ -13,7 +14,7 @@ entry: !1 = !DIFile(filename: "test.cpp", directory: "/") !3 = !{i32 2, !"Debug Info Version", i32 3} !9 = !{!"clang version 21.0.0git"} -!10 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) +!10 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, nextAtomGroup: 2) !11 = !DISubroutineType(types: !12) !12 = !{null} !13 = !DILocation(line: 1, column: 11, scope: !10, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-branch-fold.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-branch-fold.ll index 75a05ad931707..98d91f4eba00a 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-branch-fold.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-branch-fold.ll @@ -70,7 +70,7 @@ f: !4 = !{i32 0} !5 = !{i32 2, !"Debug Info Version", i32 3} !7 = !DISubroutineType(types: !2) -!17 = distinct !DISubprogram(name: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!17 = distinct !DISubprogram(name: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2, nextAtomGroup: 3) !18 = !DILocation(line: 10, column: 10, scope: !17) !19 = !DILocation(line: 10, column: 10, scope: !17, atomGroup: 1, atomRank: 2) !20 = !DILocation(line: 10, column: 10, scope: !17, atomGroup: 2, atomRank: 2) @@ -79,7 +79,7 @@ f: ; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]]) ; CHECK: [[META1]] = !DIFile(filename: "a.ll", directory: {{.*}}) ; CHECK: [[META2]] = !{} -; CHECK: [[DBG6]] = distinct !DISubprogram(name: "f", scope: null, file: [[META1]], line: 1, type: [[META7:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META2]]) +; CHECK: [[DBG6]] = distinct !DISubprogram(name: "f", scope: null, file: [[META1]], line: 1, type: [[META7:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META2]], nextAtomGroup: 7) ; CHECK: [[META7]] = !DISubroutineType(types: [[META2]]) ; CHECK: [[DBG8]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 5, atomRank: 2) ; CHECK: [[DBG9]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 6, atomRank: 2) diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-thread-phi.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-thread-phi.ll index f8477600c6418..0fe31fdcfc51e 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-thread-phi.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/simplifycfg-thread-phi.ll @@ -13,6 +13,8 @@ ; CHECK: store i32 1{{.*}}, !dbg [[DBG1:!.*]] ; CHECK: if.end.1.critedge: ; CHECK: store i32 1{{.*}}, !dbg [[DBG2:!.*]] +; +; CHECK: distinct !DISubprogram(name: "bar", {{.*}}nextAtomGroup: 3) ; CHECK: [[DBG1]] = !DILocation(line: 1{{.*}}, atomGroup: 1 ; CHECK: [[DBG2]] = !DILocation(line: 1{{.*}}, atomGroup: 2 @@ -56,7 +58,7 @@ declare void @foo() !2 = !{i32 15} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/cgp-break-critical-edge.ll b/llvm/test/DebugInfo/KeyInstructions/X86/cgp-break-critical-edge.ll index a21b1da15a45d..3b67005fddced 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/cgp-break-critical-edge.ll +++ b/llvm/test/DebugInfo/KeyInstructions/X86/cgp-break-critical-edge.ll @@ -9,6 +9,7 @@ ; CHECK: while.body.clone: ; CHECK-NEXT: %dest.sroa.clone = phi i32 [ %1, %.split ], [ poison, %if.else ], !dbg [[G2R1:!.*]] +; CHECK: distinct !DISubprogram(name: "test", {{.*}}nextAtomGroup: 3) ; CHECK: [[G1R1]] = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 1) ; CHECK: [[G2R1]] = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 2, atomRank: 1) @@ -46,7 +47,7 @@ if.else1: ; preds = %if.else1, %preheade !2 = !{i32 11} !3 = !{i32 0} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DISubprogram(name: "test", linkageName: "test", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!5 = distinct !DISubprogram(name: "test", linkageName: "test", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !12 = !DILocation(line: 1, column: 1, scope: !5, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic-ranks.ll b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic-ranks.ll index 6988a6fb2ec3f..496d5532e4d0e 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic-ranks.ll +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic-ranks.ll @@ -47,10 +47,10 @@ target triple = "x86_64-unknown-linux-gnu" define hidden noundef i32 @_Z1fPiii(ptr %a, i32 %b, i32 %c) local_unnamed_addr !dbg !11 { entry: - tail call void @_Z12prologue_endv(), !dbg !DILocation(line: 4, scope: !11) - %add = add nsw i32 %c, %b, !dbg !DILocation(line: 6, scope: !11, atomGroup: 1, atomRank: 2) - store i32 %add, ptr %a, align 4, !dbg !DILocation(line: 5, scope: !11, atomGroup: 1, atomRank: 1) - ret i32 %add, !dbg !DILocation(line: 7, scope: !11, atomGroup: 2, atomRank: 1) + tail call void @_Z12prologue_endv(), !dbg !14 ; !DILocation(line: 4, scope: !11) + %add = add nsw i32 %c, %b, !dbg !15 ; !DILocation(line: 6, scope: !11, atomGroup: 1, atomRank: 2) + store i32 %add, ptr %a, align 4, !dbg !16 ; !DILocation(line: 5, scope: !11, atomGroup: 1, atomRank: 1) + ret i32 %add, !dbg !17 ; !DILocation(line: 7, scope: !11, atomGroup: 2, atomRank: 1) } declare void @_Z12prologue_endv() local_unnamed_addr #1 @@ -64,6 +64,10 @@ declare void @_Z12prologue_endv() local_unnamed_addr #1 !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !12 = !DISubroutineType(types: !13) !13 = !{} +!14 = !DILocation(line: 4, scope: !11) +!15 = !DILocation(line: 6, scope: !11, atomGroup: 1, atomRank: 2) +!16 = !DILocation(line: 5, scope: !11, atomGroup: 1, atomRank: 1) +!17 = !DILocation(line: 7, scope: !11, atomGroup: 2, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic.ll b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic.ll index ba38bb2ffe903..298e11c7b0f88 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic.ll +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-basic.ll @@ -36,14 +36,14 @@ target triple = "x86_64-unknown-linux-gnu" define hidden noundef i32 @_Z1fi(i32 noundef %a) local_unnamed_addr !dbg !11 { entry: - %add = add nsw i32 %a, 1, !dbg !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) - ret i32 %add, !dbg !DILocation(line: 3, scope: !11, atomGroup: 3, atomRank: 1) + %add = add nsw i32 %a, 1, !dbg !19 ; !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) + ret i32 %add, !dbg !20 ; !DILocation(line: 3, scope: !11, atomGroup: 3, atomRank: 1) } define hidden noundef i32 @_Z1gi(i32 noundef %b) local_unnamed_addr !dbg !16 { entry: - %add.i = add nsw i32 %b, 1, !dbg !DILocation(line: 2, scope: !11, inlinedAt: !18, atomGroup: 1, atomRank: 2) - ret i32 %add.i, !dbg !DILocation(line: 6, scope: !16, atomGroup: 1, atomRank: 1) + %add.i = add nsw i32 %b, 1, !dbg !21 ; !DILocation(line: 2, scope: !11, inlinedAt: !18, atomGroup: 1, atomRank: 2) + ret i32 %add.i, !dbg !22 ; !DILocation(line: 6, scope: !16, atomGroup: 1, atomRank: 1) } !llvm.dbg.cu = !{!0} @@ -55,8 +55,12 @@ entry: !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 4) !12 = !DISubroutineType(types: !13) !13 = !{} -!16 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 5, type: !12, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!16 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 5, type: !12, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !18 = distinct !DILocation(line: 6, scope: !16) +!19 = !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) +!20 = !DILocation(line: 3, scope: !11, atomGroup: 3, atomRank: 1) +!21 = !DILocation(line: 2, scope: !11, inlinedAt: !18, atomGroup: 1, atomRank: 2) +!22 = !DILocation(line: 6, scope: !16, atomGroup: 1, atomRank: 1) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy-multi-key.mir b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy-multi-key.mir index 3b7d5850e7e83..fda74ccd35534 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy-multi-key.mir +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy-multi-key.mir @@ -48,7 +48,7 @@ !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{!"clang version 19.0.0"} - !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) + !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 4) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 1, type: !7) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy.mir b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy.mir index 3aff5e22326ec..56a180db58bfb 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy.mir +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-buoy.mir @@ -44,7 +44,7 @@ !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{!"clang version 19.0.0"} - !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) + !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} !8 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 1, type: !7) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-calls.ll b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-calls.ll index 14dfa8a6a9ccb..3fc29899d3996 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-calls.ll +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-calls.ll @@ -77,24 +77,24 @@ target triple = "x86_64-unknown-linux-gnu" define hidden i32 @fun() local_unnamed_addr !dbg !11 { entry: - %b = load i32, ptr @a, !dbg !DILocation(line: 2, scope: !11) + %b = load i32, ptr @a, !dbg !14 ; !DILocation(line: 2, scope: !11) ;; Test A: - tail call void @f(), !dbg !DILocation(line: 3, scope: !11) + tail call void @f(), !dbg !15 ; !DILocation(line: 3, scope: !11) ;; Test B: - %x = tail call i32 @g(), !dbg !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 2) - %y = add i32 %x, %b, !dbg !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 1) + %x = tail call i32 @g(), !dbg !16 ; !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 2) + %y = add i32 %x, %b, !dbg !17 ; !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 1) ;; Test C: - store i32 1, ptr @z, !dbg !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 2) - tail call void @f(), !dbg !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 1) + store i32 1, ptr @z, !dbg !18 ; !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 2) + tail call void @f(), !dbg !19 ; !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 1) ;; Test D: - store i32 2, ptr @z, !dbg !DILocation(line: 6, scope: !11, atomGroup: 3, atomRank: 2) - tail call void @f(), !dbg !DILocation(line: 7, scope: !11, atomGroup: 3, atomRank: 1) + store i32 2, ptr @z, !dbg !20 ; !DILocation(line: 6, scope: !11, atomGroup: 3, atomRank: 2) + tail call void @f(), !dbg !21 ; !DILocation(line: 7, scope: !11, atomGroup: 3, atomRank: 1) ;; Test E: - store i32 3, ptr @z, !dbg !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 2) - tail call void @f(), !dbg !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 1) - store i32 4, ptr @z, !dbg !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) - tail call void @f(), !dbg !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) - ret i32 %y, !dbg !DILocation(line: 10, scope: !11) + store i32 3, ptr @z, !dbg !22 ; !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 2) + tail call void @f(), !dbg !23 ; !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 1) + store i32 4, ptr @z, !dbg !24 ; !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) + tail call void @f(), !dbg !25 ; !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) + ret i32 %y, !dbg !26 ; !DILocation(line: 10, scope: !11) } declare void @f() local_unnamed_addr @@ -109,6 +109,19 @@ declare i32 @g() local_unnamed_addr !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!11 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 6) !12 = !DISubroutineType(types: !13) !13 = !{} +!14 = !DILocation(line: 2, scope: !11) +!15 = !DILocation(line: 3, scope: !11) +!16 = !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 2) +!17 = !DILocation(line: 4, scope: !11, atomGroup: 1, atomRank: 1) +!18 = !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 2) +!19 = !DILocation(line: 5, scope: !11, atomGroup: 2, atomRank: 1) +!20 = !DILocation(line: 6, scope: !11, atomGroup: 3, atomRank: 2) +!21 = !DILocation(line: 7, scope: !11, atomGroup: 3, atomRank: 1) +!22 = !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 2) +!23 = !DILocation(line: 8, scope: !11, atomGroup: 4, atomRank: 1) +!24 = !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) +!25 = !DILocation(line: 9, scope: !11, atomGroup: 5, atomRank: 1) +!26 = !DILocation(line: 10, scope: !11) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir index d47ac70a9cb5b..b4c184333a329 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-key-sentinel.mir @@ -43,7 +43,7 @@ !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{!"clang version 19.0.0"} - !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) + !5 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-ranks-blocks.ll b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-ranks-blocks.ll index cd840ecce07f5..20502368e69dd 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-ranks-blocks.ll +++ b/llvm/test/DebugInfo/KeyInstructions/X86/dwarf-ranks-blocks.ll @@ -35,18 +35,18 @@ target triple = "x86_64-unknown-linux-gnu" define hidden noundef i32 @_Z1fPiii(ptr %a, i32 %b, i32 %c, i1 %cond) local_unnamed_addr !dbg !11 { entry: - tail call void @_Z12prologue_endv(), !dbg !DILocation(line: 1, scope: !11) - %add = add nsw i32 %c, %b, !dbg !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) - br i1 %cond, label %bb1, label %bb2, !dbg !DILocation(line: 1, scope: !11) + tail call void @_Z12prologue_endv(), !dbg !14 ; !DILocation(line: 1, scope: !11) + %add = add nsw i32 %c, %b, !dbg !15 ; !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) + br i1 %cond, label %bb1, label %bb2, !dbg !16 ; !DILocation(line: 1, scope: !11) bb1: - store i32 %add, ptr %a, align 4, !dbg !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) - ret i32 %add, !dbg !DILocation(line: 1, scope: !11) + store i32 %add, ptr %a, align 4, !dbg !17 ; !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) + ret i32 %add, !dbg !18 ; !DILocation(line: 1, scope: !11) bb2: - store i32 %b, ptr %a, align 4, !dbg !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) - store i32 %c, ptr %a, align 4, !dbg !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) - ret i32 %add, !dbg !DILocation(line: 1, scope: !11) + store i32 %b, ptr %a, align 4, !dbg !19 ; !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) + store i32 %c, ptr %a, align 4, !dbg !20 ; !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) + ret i32 %add, !dbg !21 ; !DILocation(line: 1, scope: !11) } declare void @_Z12prologue_endv() local_unnamed_addr #1 @@ -60,6 +60,14 @@ declare void @_Z12prologue_endv() local_unnamed_addr #1 !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !10 = !{!"clang version 19.0.0"} -!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) !12 = !DISubroutineType(types: !13) !13 = !{} +!14 = !DILocation(line: 1, scope: !11) +!15 = !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) +!16 = !DILocation(line: 1, scope: !11) +!17 = !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) +!18 = !DILocation(line: 1, scope: !11) +!19 = !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) +!20 = !DILocation(line: 3, scope: !11, atomGroup: 1, atomRank: 1) +!21 = !DILocation(line: 1, scope: !11) diff --git a/llvm/test/DebugInfo/KeyInstructions/X86/parse.mir b/llvm/test/DebugInfo/KeyInstructions/X86/parse.mir index 45cc23831412c..65ac199fd96ef 100644 --- a/llvm/test/DebugInfo/KeyInstructions/X86/parse.mir +++ b/llvm/test/DebugInfo/KeyInstructions/X86/parse.mir @@ -2,6 +2,7 @@ ## Check the MIR parser understands atomGroup and atomRank. +# CHECK: distinct !DISubprogram(name: "p", {{.*}}nextAtomGroup: 2) # CHECK: RET64 $eax, debug-location !DILocation(line: 2, scope: ![[#]], atomGroup: 1, atomRank: 2) --- | @@ -22,7 +23,7 @@ !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{!"clang version 19.0.0"} - !5 = distinct !DISubprogram(name: "p", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) + !5 = distinct !DISubprogram(name: "p", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) !6 = !DISubroutineType(types: !7) !7 = !{} diff --git a/llvm/test/DebugInfo/KeyInstructions/debugify.ll b/llvm/test/DebugInfo/KeyInstructions/debugify.ll index 881375873f324..3cfcb6f1d5694 100644 --- a/llvm/test/DebugInfo/KeyInstructions/debugify.ll +++ b/llvm/test/DebugInfo/KeyInstructions/debugify.ll @@ -38,9 +38,12 @@ define i32 @boom() { ret i32 %retval } +; CHECK: distinct !DISubprogram(name: "foo", {{.*}}nextAtomGroup: 2) ; CHECK-DAG: ![[RET1]] = !DILocation(line: 1, {{.*}}, atomGroup: 1, atomRank: 1 +; CHECK: distinct !DISubprogram(name: "bar", {{.*}}nextAtomGroup: 5) ; CHECK-DAG: ![[CALL1]] = !DILocation(line: 2, {{.*}}, atomGroup: 2, atomRank: 1 ; CHECK-DAG: ![[ADD1]] = !DILocation(line: 3, {{.*}}, atomGroup: 3, atomRank: 1 ; CHECK-DAG: ![[RET2]] = !DILocation(line: 4, {{.*}}, atomGroup: 4, atomRank: 1 +; CHECK: distinct !DISubprogram(name: "boom", {{.*}}nextAtomGroup: 7) ; CHECK-DAG: ![[musttail]] = !DILocation(line: 5, {{.*}}, atomGroup: 5, atomRank: 1 ; CHECK-DAG: ![[musttailRes]] = !DILocation(line: 6, {{.*}}, atomGroup: 6, atomRank: 1 diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp index cb1a56a26f063..ae4887af570a3 100644 --- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp +++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp @@ -154,7 +154,7 @@ TEST(BasicBlockDbgInfoTest, DropSourceAtomOnSplit) { std::unique_ptr M = parseIR(C, R"---( define dso_local void @func() !dbg !10 { %1 = alloca i32, align 4 - ret void, !dbg !DILocation(line: 3, column: 2, scope: !10, atomGroup: 1, atomRank: 1) + ret void, !dbg !16 } !llvm.dbg.cu = !{!0} @@ -164,12 +164,13 @@ TEST(BasicBlockDbgInfoTest, DropSourceAtomOnSplit) { !1 = !DIFile(filename: "dummy", directory: "dummy") !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} - !10 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13) + !10 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13, nextAtomGroup: 2) !11 = !DISubroutineType(types: !12) !12 = !{null} !13 = !{} !14 = !DILocalVariable(name: "a", scope: !10, file: !1, line: 2, type: !15) !15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !16 = !DILocation(line: 3, column: 2, scope: !10, atomGroup: 1, atomRank: 1) )---"); ASSERT_TRUE(M); diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index f6fbca19b2393..0bd0c3b3e3443 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -92,9 +92,10 @@ class MetadataTest : public testing::Test { getNode(nullptr)); } DISubprogram *getSubprogram(DIFile *F = nullptr) { - return DISubprogram::getDistinct(Context, nullptr, "", "", F, 0, nullptr, 0, - nullptr, 0, 0, DINode::FlagZero, - DISubprogram::SPFlagZero, nullptr); + return DISubprogram::getDistinct( + Context, nullptr, "", "", F, 0, nullptr, 0, nullptr, 0, 0, + DINode::FlagZero, DISubprogram::SPFlagDefinition, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, "", /*UseKeyInstructions*/ true); } DIFile *getFile() { return DIFile::getDistinct(Context, "file.c", "/path/to/dir"); @@ -1596,13 +1597,15 @@ TEST_F(DILocationTest, Merge) { // a sentinel that indicates the instruction is in its own undefined atom // group. { - // Reset global counter to ensure EXPECT numbers line up. - Context.pImpl->NextAtomGroup = 1; // x1 -> y2 -> z4 // y3 -> z4 auto *FX = getSubprogram(); auto *FY = getSubprogram(); auto *FZ = getSubprogram(); + EXPECT_EQ(FX->getNextDILocationAtomGroup(), 1); + EXPECT_EQ(FY->getNextDILocationAtomGroup(), 1); + EXPECT_EQ(FZ->getNextDILocationAtomGroup(), 1); + auto *Z4 = DILocation::get(Context, 1, 4, FZ); auto *Y3IntoZ4 = DILocation::get(Context, 1, 3, FY, Z4, false, /*AtomGroup*/ 1, /*AtomRank*/ 1); @@ -1750,11 +1753,11 @@ TEST_F(DILocationTest, discriminatorSpecialCases) { } TEST_F(DILocationTest, KeyInstructions) { - Context.pImpl->NextAtomGroup = 1; + DISubprogram *SP = getSubprogram(); + uint32_t NextGroup = SP->getNextDILocationAtomGroup(); + EXPECT_EQ(NextGroup, 1u); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u); - DILocation *A1 = - DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2); + DILocation *A1 = DILocation::get(Context, 1, 0, SP, nullptr, false, 1, 2); // The group is only applied to the DILocation if we've built LLVM with // EXPERIMENTAL_KEY_INSTRUCTIONS. #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS @@ -1766,26 +1769,26 @@ TEST_F(DILocationTest, KeyInstructions) { #endif // Group number 1 has been "used" so next available is 2. - EXPECT_EQ(Context.pImpl->NextAtomGroup, 2u); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 2u); // Set a group number higher than current + 1, then check the waterline. - DILocation::get(Context, 2, 0, getSubprogram(), nullptr, false, 5, 1); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u); + DILocation::get(Context, 2, 0, SP, nullptr, false, 5, 1); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 6u); // The waterline should be unchanged (group <= next). - DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 4, 1); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u); - DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 5, 1); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u); + DILocation::get(Context, 3, 0, SP, nullptr, false, 4, 1); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 6u); + DILocation::get(Context, 3, 0, SP, nullptr, false, 5, 1); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 6u); // Check the waterline gets incremented by 1. - EXPECT_EQ(Context.incNextDILocationAtomGroup(), 6u); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 7u); + EXPECT_EQ(SP->incNextDILocationAtomGroup(), 6u); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 7u); - Context.updateDILocationAtomGroupWaterline(8); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u); - Context.updateDILocationAtomGroupWaterline(7); - EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u); + SP->updateDILocationAtomGroupWaterline(8); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 8u); + SP->updateDILocationAtomGroupWaterline(7); + EXPECT_EQ(SP->getNextDILocationAtomGroup(), 8u); } typedef MetadataTest GenericDINodeTest; diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp index 09b32bf09df0e..077ec0b2168dd 100644 --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -1223,7 +1223,7 @@ TEST_F(CloneInstruction, cloneKeyInstructions) { ValueToValueMapTy VM; // Store1 and Store2 have the same atomGroup number, but have different // inlining scopes, so only Store1 should change group. - mapAtomInstance(Store1->getDebugLoc(), VM); + mapAtomInstance(F->getSubprogram(), Store1->getDebugLoc(), VM); for (Instruction &I : *BB) RemapSourceAtom(&I, VM); EXPECT_ATOM(Store1, 3); @@ -1233,7 +1233,7 @@ TEST_F(CloneInstruction, cloneKeyInstructions) { VM.clear(); // Store2 and Store3 have the same group number; both should get remapped. - mapAtomInstance(Store2->getDebugLoc(), VM); + mapAtomInstance(F->getSubprogram(), Store2->getDebugLoc(), VM); for (Instruction &I : *BB) RemapSourceAtom(&I, VM); EXPECT_ATOM(Store1, 3); @@ -1243,8 +1243,8 @@ TEST_F(CloneInstruction, cloneKeyInstructions) { VM.clear(); // Cloning BB with MapAtoms=false should clone the atom numbers. - BasicBlock *BB2 = - CloneBasicBlock(BB, VM, "", nullptr, nullptr, /*MapAtoms*/ false); + BasicBlock *BB2 = CloneBasicBlock(BB, VM, F->getSubprogram(), "", nullptr, + nullptr, /*MapAtoms*/ false); for (Instruction &I : *BB2) RemapSourceAtom(&I, VM); Store1 = &*BB2->begin(); @@ -1259,8 +1259,8 @@ TEST_F(CloneInstruction, cloneKeyInstructions) { delete BB2; // Cloning BB with MapAtoms=true should map the atom numbers. - BasicBlock *BB3 = - CloneBasicBlock(BB, VM, "", nullptr, nullptr, /*MapAtoms*/ true); + BasicBlock *BB3 = CloneBasicBlock(BB, VM, F->getSubprogram(), "", nullptr, + nullptr, /*MapAtoms*/ true); for (Instruction &I : *BB3) RemapSourceAtom(&I, VM); Store1 = &*BB3->begin(); From 56f141595298a1d86d26d7066b1bbaddbd5069a4 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Tue, 10 Jun 2025 12:59:36 +0100 Subject: [PATCH 5/7] General fixups and cleanups tidy getImpl fix test.. simplfy... needs further looking at, does this need to be recursive? reduce cost of constructing dilocations add verifier check don't crash when keyinsts is disabled --- clang/lib/CodeGen/CGDebugInfo.cpp | 22 ++++- clang/lib/CodeGen/CGDebugInfo.h | 4 +- clang/lib/CodeGen/CodeGenFunction.cpp | 4 +- llvm/include/llvm/IR/DIBuilder.h | 19 ++-- llvm/include/llvm/IR/DebugInfoMetadata.h | 88 +++++++++--------- llvm/include/llvm/IR/ValueMap.h | 2 +- llvm/lib/IR/DIBuilder.cpp | 4 +- llvm/lib/IR/DebugInfoMetadata.cpp | 96 ++++++++++---------- llvm/lib/IR/LLVMContextImpl.h | 1 + llvm/lib/IR/Verifier.cpp | 6 ++ llvm/lib/Transforms/Utils/Debugify.cpp | 1 + llvm/lib/Transforms/Utils/InlineFunction.cpp | 18 ++-- 12 files changed, 139 insertions(+), 126 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 097abdcd3cd9c..24deb1e56c702 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -42,6 +42,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -192,8 +193,13 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, } } -void CGDebugInfo::completeFunction() { - // Reset the atom group number tracker as the numbers are function-local. +void CGDebugInfo::completeFunction(llvm::Function *Fn) { + // Set DISubprogram::NextAtomGroup. + if (CGM.getCodeGenOpts().DebugKeyInstructions && + Fn->getSubprogram()->isDefinition()) + Fn->getSubprogram()->updateDILocationAtomGroupWaterline( + KeyInstructionsInfo.HighestEmittedAtom + 1); + KeyInstructionsInfo.NextAtom = 1; KeyInstructionsInfo.HighestEmittedAtom = 0; KeyInstructionsInfo.CurrentAtom = 0; @@ -2285,7 +2291,8 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( llvm::DISubprogram *SP = DBuilder.createMethod( RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, MethodTy, VIndex, ThisAdjustment, ContainingType, Flags, SPFlags, - TParamsArray.get()); + TParamsArray.get(), /*ThrownTypes*/ nullptr, + CGM.getCodeGenOpts().DebugKeyInstructions); SPCache[Method->getCanonicalDecl()].reset(SP); @@ -4351,7 +4358,9 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, return DBuilder.createFunction( DContext, Name, LinkageName, Unit, Line, getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags, - TParamsArray.get(), getFunctionDeclaration(FD)); + TParamsArray.get(), getFunctionDeclaration(FD), /*ThrownTypes*/ nullptr, + /*Annotations*/ nullptr, /*TargetFuncName*/ "", + CGM.getCodeGenOpts().DebugKeyInstructions); } llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl( @@ -4748,9 +4757,12 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D); llvm::DISubroutineType *STy = getOrCreateFunctionType(D, FnType, Unit); + // Key Instructions: Do not set UseKeyInstructions on declarations. + assert(~SPFlags & llvm::DISubprogram::SPFlagDefinition); llvm::DISubprogram *SP = DBuilder.createFunction( FDContext, Name, LinkageName, Unit, LineNo, STy, ScopeLine, Flags, - SPFlags, TParamsArray.get(), nullptr, nullptr, Annotations); + SPFlags, TParamsArray.get(), nullptr, nullptr, Annotations, + /*TargetFunctionName*/ "", /*UseKeyInstructions*/ false); // Preserve btf_decl_tag attributes for parameters of extern functions // for BPF target. The parameters created in this loop are attached as diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 16759f25123cd..51101991eff02 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -657,8 +657,8 @@ class CGDebugInfo { llvm::DILocation *CreateSyntheticInlineAt(llvm::DebugLoc Location, StringRef FuncName); - /// Reset internal state. - void completeFunction(); + /// Finalize some function debug info and reset per-function internal state. + void completeFunction(llvm::Function *Fn); /// Add \p KeyInstruction and an optional \p Backup instruction to the /// current atom group, created using ApplyAtomGroup. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 56562002e7194..c8ca75073a1c5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1512,9 +1512,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, DebugInfo = nullptr; } // Finalize function debug info on exit. - auto Cleanup = llvm::make_scope_exit([this] { + auto Cleanup = llvm::make_scope_exit([this, Fn] { if (CGDebugInfo *DI = getDebugInfo()) - DI->completeFunction(); + DI->completeFunction(Fn); }); // The function might not have a body if we're generating thunks for a diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 71ba7e3d7a0c8..d162371553b0d 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -898,6 +898,7 @@ namespace llvm { /// \param Annotations Attribute Annotations. /// \param TargetFuncName The name of the target function if this is /// a trampoline. + /// \param UseKeyInstructions Enable Key Instructions debug info. LLVM_ABI DISubprogram *createFunction( DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, @@ -937,15 +938,15 @@ namespace llvm { /// \param SPFlags Additional flags specific to subprograms. /// \param TParams Function template parameters. /// \param ThrownTypes Exception types this function may throw. - LLVM_ABI DISubprogram * - createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, - DIFile *File, unsigned LineNo, DISubroutineType *Ty, - unsigned VTableIndex = 0, int ThisAdjustment = 0, - DIType *VTableHolder = nullptr, - DINode::DIFlags Flags = DINode::FlagZero, - DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, - DITemplateParameterArray TParams = nullptr, - DITypeArray ThrownTypes = nullptr); + /// \param UseKeyInstructions Enable Key Instructions debug info. + LLVM_ABI DISubprogram *createMethod( + DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, unsigned VTableIndex = 0, + int ThisAdjustment = 0, DIType *VTableHolder = nullptr, + DINode::DIFlags Flags = DINode::FlagZero, + DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, + DITemplateParameterArray TParams = nullptr, + DITypeArray ThrownTypes = nullptr, bool UseKeyInstructions = false); /// Create common block entry for a Fortran common block. /// \param Scope Scope of this common block. diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index d274f991f6c99..25dacd6b8fd00 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1976,8 +1976,20 @@ class DISubprogram : public DILocalScope { /// negative. int ThisAdjustment; - /// Not serialised. - uint32_t NextAtomGroup = 0; // set to 1 to mark as "has key insts" + /// Key Instructions: The next available atom group number for this function. + /// The front end is responsible for assigning source atom numbers, but + /// certain optimisations need to assign new group numbers to a set of + /// instructions. Most often code duplication optimisations like loop unroll. + /// + /// NOTE: This field doesn't contribute to the identity of the DISubprogram; + /// it's not represented in MDNodeKeyImpl. This is intentional. + /// It SHOULD ONLY be written to by distinct DISubprograms. + /// + /// Zero indicates the function doesn't use Key Instructions + /// There may be Key Instruction metadata on its instructions, e.g. from + /// inlined instructions, that's all going to be ignored for this function + /// at DWARF emission time. + uint32_t NextAtomGroup = 0; public: /// Debug info subprogram flags. @@ -2006,27 +2018,31 @@ class DISubprogram : public DILocalScope { unsigned Virtuality = SPFlagNonvirtual, bool IsMainSubprogram = false); + /// Key Instructions: get the next available atom group number and increment + /// the function-local tracker. uint32_t incNextDILocationAtomGroup() { - assert(isDefinition() && getKeyInstructionsEnabled()); + assert(isDistinct() && getKeyInstructionsEnabled()); // NOTE: This may wrap, which effectively disables Key Instructions for - // this function (as long as getNextDILocationAtomGroup is checked before - // the next call). As a result, instances that have already been inlined + // this function. As a result, instances that have already been inlined // will also have Key Instructions disabled for them, since we look back // to this DISubprogram to check if it's enabled during DWARF emission. // A quirk of the implementation that only shows up in extreme edge cases. return NextAtomGroup++; } + + /// Key Instructions: get the next available atom group number. uint32_t getNextDILocationAtomGroup() const { - assert(getKeyInstructionsEnabled()); + assert(isDistinct() && getKeyInstructionsEnabled()); return NextAtomGroup; } + bool getKeyInstructionsEnabled() const { return NextAtomGroup; } + /// Key Instructions: update the highest number atom group emitted for any /// function. - void updateDILocationAtomGroupWaterline(uint32_t G) { - assert(getKeyInstructionsEnabled()); - // FIXME: should really be G+1, if the waterline is "current max". - NextAtomGroup = std::max(NextAtomGroup, G); + void updateDILocationAtomGroupWaterline(uint32_t NewNextGroup) { + assert(isDistinct() && getKeyInstructionsEnabled()); + NextAtomGroup = std::max(NextAtomGroup, NewNextGroup); } private: @@ -2047,27 +2063,7 @@ class DISubprogram : public DILocalScope { DITemplateParameterArray TemplateParams, DISubprogram *Declaration, DINodeArray RetainedNodes, DITypeArray ThrownTypes, DINodeArray Annotations, StringRef TargetFuncName, - uint32_t NextAtomGroup, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), - getCanonicalMDString(Context, LinkageName), File, Line, Type, - ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, - Flags, SPFlags, Unit, TemplateParams.get(), Declaration, - RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), - getCanonicalMDString(Context, TargetFuncName), NextAtomGroup, - Storage, ShouldCreate); - } - - static DISubprogram * - getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - StringRef LinkageName, DIFile *File, unsigned Line, - DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, - unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, - DISPFlags SPFlags, DICompileUnit *Unit, - DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DINodeArray RetainedNodes, DITypeArray ThrownTypes, - DINodeArray Annotations, StringRef TargetFuncName, - bool UseKeyInstructions, StorageType Storage, + uint32_t KeyInstNextAtomGroup, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, @@ -2075,9 +2071,9 @@ class DISubprogram : public DILocalScope { Flags, SPFlags, Unit, TemplateParams.get(), Declaration, RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), getCanonicalMDString(Context, TargetFuncName), - static_cast(UseKeyInstructions), Storage, - ShouldCreate); + KeyInstNextAtomGroup, Storage, ShouldCreate); } + LLVM_ABI static DISubprogram * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, @@ -2085,17 +2081,16 @@ class DISubprogram : public DILocalScope { int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, - MDString *TargetFuncName, uint32_t NextAtomGroup, StorageType Storage, - bool ShouldCreate = true); + MDString *TargetFuncName, uint32_t KeyInstNextAtomGroup, + StorageType Storage, bool ShouldCreate = true); TempDISubprogram cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getLinkageName(), - getFile(), getLine(), getType(), getScopeLine(), - getContainingType(), getVirtualIndex(), - getThisAdjustment(), getFlags(), getSPFlags(), - getUnit(), getTemplateParams(), getDeclaration(), - getRetainedNodes(), getThrownTypes(), getAnnotations(), - getTargetFuncName()); // TODO: Key Instructions Stuff! + return getTemporary( + getContext(), getScope(), getName(), getLinkageName(), getFile(), + getLine(), getType(), getScopeLine(), getContainingType(), + getVirtualIndex(), getThisAdjustment(), getFlags(), getSPFlags(), + getUnit(), getTemplateParams(), getDeclaration(), getRetainedNodes(), + getThrownTypes(), getAnnotations(), getTargetFuncName(), NextAtomGroup); } public: @@ -2108,7 +2103,7 @@ class DISubprogram : public DILocalScope { DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr, - StringRef TargetFuncName = "", uint32_t UseKeyInstructions = false), + StringRef TargetFuncName = "", uint32_t UseKeyInstructions = 0), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName, @@ -2300,9 +2295,10 @@ class DILocation : public MDNode { uint32_t AtomRank : 3; #endif - DILocation(LLVMContext &C, StorageType Storage, DISubprogram *SP, - unsigned Line, unsigned Column, uint32_t AtomGroup, - uint8_t AtomRank, ArrayRef MDs, bool ImplicitCode); + DILocation(LLVMContext &C, StorageType Storage, + DISubprogram *SPForKeyInstructions, unsigned Line, unsigned Column, + uint32_t AtomGroup, uint8_t AtomRank, ArrayRef MDs, + bool ImplicitCode); ~DILocation() { dropAllReferences(); } LLVM_ABI static DILocation * diff --git a/llvm/include/llvm/IR/ValueMap.h b/llvm/include/llvm/IR/ValueMap.h index 1a11718bfcdae..16dfa16646e3c 100644 --- a/llvm/include/llvm/IR/ValueMap.h +++ b/llvm/include/llvm/IR/ValueMap.h @@ -88,7 +88,7 @@ class ValueMap { using MapT = DenseMap>; using MDMapT = DenseMap; /// Map {(InlinedAt, old atom number) -> new atom number}. - using DMAtomT = SmallDenseMap, uint64_t>; + using DMAtomT = SmallDenseMap, uint32_t>; using ExtraData = typename Config::ExtraData; MapT Map; diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index baeb52219b5eb..8528c1ed55803 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -968,7 +968,7 @@ DISubprogram *DIBuilder::createMethod( unsigned LineNo, DISubroutineType *Ty, unsigned VIndex, int ThisAdjustment, DIType *VTableHolder, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, - DITypeArray ThrownTypes) { + DITypeArray ThrownTypes, bool UseKeyInstructions) { assert(getNonCompileUnitScope(Context) && "Methods should have both a Context and a context that isn't " "the compile unit."); @@ -978,7 +978,7 @@ DISubprogram *DIBuilder::createMethod( /*IsDistinct=*/IsDefinition, VMContext, cast(Context), Name, LinkageName, F, LineNo, Ty, LineNo, VTableHolder, VIndex, ThisAdjustment, Flags, SPFlags, IsDefinition ? CUNode : nullptr, TParams, nullptr, - nullptr, ThrownTypes); + nullptr, ThrownTypes, nullptr, "", IsDefinition && UseKeyInstructions); AllSubprograms.push_back(SP); trackIfUnresolved(SP); diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index a807130c0c8aa..fa8b84f4ba544 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -65,10 +65,10 @@ DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI) : DebugVariable(DVI->getVariable(), std::nullopt, DVI->getDebugLoc()->getInlinedAt()) {} -DILocation::DILocation(LLVMContext &C, StorageType Storage, DISubprogram *Fn, - unsigned Line, unsigned Column, uint32_t AtomGroup, - uint8_t AtomRank, ArrayRef MDs, - bool ImplicitCode) +DILocation::DILocation(LLVMContext &C, StorageType Storage, + DISubprogram *SPForKeyInstructions, unsigned Line, + unsigned Column, uint32_t AtomGroup, uint8_t AtomRank, + ArrayRef MDs, bool ImplicitCode) : MDNode(C, DILocationKind, Storage, MDs) #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS , @@ -78,22 +78,17 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, DISubprogram *Fn, #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits"); #endif - // OCH huurrrr - - // if (AtomGroup) - // C.updateDILocationAtomGroupWaterline(AtomGroup + 1); - if (AtomGroup) { - // assert(Fn); - // assert(Fn->isDefinition()); - if (Fn) { - // Fn might be a temporary during parsing, which sucks but there we go. - // allow null for now - probably need to verify somewhere? - // this occurs e.g. - // !1 = ... inlinedAt !2 // < temporary - // !2 = ... - assert(Fn->isDefinition()); - Fn->updateDILocationAtomGroupWaterline(AtomGroup + 1); - } + + if (AtomGroup && SPForKeyInstructions) { + // Fn might be a temporary during parsing, which sucks but there we go. + // allow null for now - probably need to verify somewhere? + // this occurs e.g. + // !1 = ... inlinedAt !2 // < temporary + // !2 = ... + // TODO: Accept temporaries, so we can work that out in here? + assert(false); + assert(SPForKeyInstructions->isDefinition()); + SPForKeyInstructions->updateDILocationAtomGroupWaterline(AtomGroup + 1); } assert((MDs.size() == 1 || MDs.size() == 2) && @@ -113,6 +108,27 @@ static void adjustColumn(unsigned &Column) { Column = 0; } +static DISubprogram *getResolvedInlinedAtSubprogram(Metadata *Scope, + Metadata *InlinedAt) { + auto *InlinedAtNode = dyn_cast_or_null(InlinedAt); + if (InlinedAt && (!InlinedAtNode || !InlinedAtNode->isResolved())) + return nullptr; + + auto *LS = dyn_cast(Scope); + if (!LS || !LS->isResolved()) + return nullptr; + + auto *LexicalBlockBase = dyn_cast(LS); + if (LexicalBlockBase && + !cast(LexicalBlockBase->getRawScope())->isResolved()) + return nullptr; + + if (!InlinedAt) + return LS->getSubprogram(); + + return cast(InlinedAt)->getInlinedAtScope()->getSubprogram(); +} + DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt, bool ImplicitCode, @@ -139,35 +155,12 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, if (InlinedAt) Ops.push_back(InlinedAt); - DISubprogram *SP = nullptr; - // all this BS should go away, we should just delay checks to verifier and add - // comments explaining why! (or keep checks but streamline) - // gotta keep checks because obvs optimisations + FE need to update thru this. - // TODO: Prettify, and verify. - if (isa_and_nonnull(Scope) && cast(Scope)->isResolved()) { - if (auto *LS = dyn_cast_or_null(Scope)) { - if (LS->isResolved()) { - if (!isa(LS) || - (cast(LS)->getRawScope() && - cast(cast(LS)->getRawScope()) - ->isResolved())) { - SP = LS->getSubprogram(); - if (InlinedAt) { - assert(SP); - if (!cast(InlinedAt)->isResolved()) - SP = nullptr; - else { - auto *X = cast(InlinedAt)->getInlinedAtScope(); - SP = X->getSubprogram(); - } - } - } - } - } - } - return storeImpl(new (Ops.size(), Storage) - DILocation(Context, Storage, SP, Line, Column, AtomGroup, - AtomRank, Ops, ImplicitCode), + DISubprogram *SPForKeyInstructions = nullptr; + // AtomGroup ? getResolvedInlinedAtSubprogram(Scope, InlinedAt) : nullptr; + // What about don't, and just verify this :---) + return storeImpl(new (Ops.size(), Storage) DILocation( + Context, Storage, SPForKeyInstructions, Line, Column, + AtomGroup, AtomRank, Ops, ImplicitCode), Storage, Context.pImpl->DILocations); } @@ -1445,7 +1438,6 @@ DISubprogram *DISubprogram::getImpl( assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); assert(isCanonical(TargetFuncName) && "Expected canonical MDString"); - // TODO: Key on UseKeyInstructions??? DEFINE_GETIMPL_LOOKUP(DISubprogram, (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, @@ -1477,6 +1469,10 @@ DISubprogram *DISubprogram::getImpl( (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags, SPFlags), Ops, Ops.size()); }(); + // Key Instructions: As per DISubprogram::NextAtomGroup's doc-comment, + // NextAtomGroup doesn't contribute to the identity of the DISubprogram; it's + // not represented in MDNodeKeyImpl. Set it now, after the + // (distinct) DISubprogram has been created. if (NextAtomGroup) { assert(SP->isDistinct()); SP->NextAtomGroup = NextAtomGroup; diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 60f168f734914..7cbe9cec18a1f 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -939,6 +939,7 @@ template <> struct MDNodeKeyImpl { Metadata *ThrownTypes; Metadata *Annotations; MDString *TargetFuncName; + // Key Instructions: Do not track NextAtomGroup. See DISubprogram for info. MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 592bb6aa90613..56a45d4cd5474 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3165,6 +3165,12 @@ void Verifier::visitFunction(const Function &F) { CheckDI(SP->describes(&F), "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); + + if (auto atomGroup = DL->getAtomGroup()) + CheckDI(!SP->getKeyInstructionsEnabled() || + SP->getNextDILocationAtomGroup() > atomGroup, + "DbgLoc's atomGroup should be less than SP's nextAtomGroup", DL, + atomGroup, SP, SP->getNextDILocationAtomGroup()); }; for (auto &BB : F) for (auto &I : BB) { diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 4ac4b53841d91..830072426a1c4 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -201,6 +201,7 @@ bool llvm::applyDebugifyMetadata( if (ApplyToMF) ApplyToMF(DIB, F); DIB.finalizeSubprogram(SP); + SP->updateDILocationAtomGroupWaterline(NextLine); } DIB.finalize(); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 4705a7547285d..d10b2b7d2fc3e 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1921,16 +1921,16 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, // functions were built with Key Instructions. The result at DWARF emission // is: // - // Key Instructions before/after inlining? - // caller + callee -> caller + callee - // caller only -> caller only - // callee only -> neither - // neither -> neither + // Key Instructions before -> after inlining + // caller + callee -> caller + inlined callee + // caller only -> caller only + // callee only -> neither + // neither -> neither // - // `callee only -> callee only` isn't supported due to how - // `getKeyInstructionsEnabled` is implemented, and because it would be - // expensive to assume all functions may contain Key Instructions if none - // do. + // `callee only -> inlined callee only` isn't supported due to how + // `getKeyInstructionsEnabled` is implemented, and because it may be + // expensive to assume all functions may contain Key Instructions in + // a subset of nested scopes. bool KeyInstructions = Fn->getSubprogram()->getKeyInstructionsEnabled(); uint32_t MaxInlineAtom = 0; From 77a9f8e98f36fe78b68fc4d400f1f6cbaf8e2889 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Tue, 10 Jun 2025 17:33:47 +0100 Subject: [PATCH 6/7] Revert "remove bitcode stuff" This reverts commit 0bb783d093627914f1d8679e43eeff088ef71ada. --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 +- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 ++-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 25 ++++-- .../KeyInstructions/Generic/link-two-modes.ll | 67 +++++++++++++++ .../KeyInstructions/Generic/roundtrip.ll | 82 +++++++++++++++++++ 5 files changed, 181 insertions(+), 16 deletions(-) create mode 100644 llvm/test/DebugInfo/KeyInstructions/Generic/link-two-modes.ll create mode 100644 llvm/test/DebugInfo/KeyInstructions/Generic/roundtrip.ll diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 31129b7e5cf77..552cb485864a6 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5086,7 +5086,9 @@ Error BitcodeReader::parseFunctionBody(Function *F) { unsigned Line = Record[0], Col = Record[1]; unsigned ScopeID = Record[2], IAID = Record[3]; - bool isImplicitCode = Record.size() == 5 && Record[4]; + bool isImplicitCode = Record.size() >= 5 && Record[4]; + uint32_t AtomGroup = Record.size() == 7 ? Record[5] : 0; + uint8_t AtomRank = Record.size() == 7 ? Record[6] : 0; MDNode *Scope = nullptr, *IA = nullptr; if (ScopeID) { @@ -5101,8 +5103,9 @@ Error BitcodeReader::parseFunctionBody(Function *F) { if (!IA) return error("Invalid record"); } + LastLoc = DILocation::get(Scope->getContext(), Line, Col, Scope, IA, - isImplicitCode); + isImplicitCode, AtomGroup, AtomRank); I->setDebugLoc(LastLoc); I = nullptr; continue; diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 1cd1797c1092d..753de8ca5811c 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1416,7 +1416,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_LOCATION: { - if (Record.size() != 5 && Record.size() != 6) + // 5: inlinedAt, 6: isImplicit, 8: Key Instructions fields. + if (Record.size() != 5 && Record.size() != 6 && Record.size() != 8) return error("Invalid record"); IsDistinct = Record[0]; @@ -1424,10 +1425,12 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( unsigned Column = Record[2]; Metadata *Scope = getMD(Record[3]); Metadata *InlinedAt = getMDOrNull(Record[4]); - bool ImplicitCode = Record.size() == 6 && Record[5]; + bool ImplicitCode = Record.size() >= 6 && Record[5]; + uint32_t AtomGroup = Record.size() == 8 ? Record[6] : 0; + uint8_t AtomRank = Record.size() == 8 ? Record[7] : 0; MetadataList.assignValue( GET_OR_DISTINCT(DILocation, (Context, Line, Column, Scope, InlinedAt, - ImplicitCode)), + ImplicitCode, AtomGroup, AtomRank)), NextMetadataNo); NextMetadataNo++; break; @@ -1857,7 +1860,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_SUBPROGRAM: { - if (Record.size() < 18 || Record.size() > 21) + if (Record.size() < 18 || Record.size() > 22) return error("Invalid record"); bool HasSPFlags = Record[0] & 4; @@ -1922,6 +1925,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( HasAnnotations = Record.size() >= 19; HasTargetFuncName = Record.size() >= 20; } + uint32_t NextAtomGroup = Record.size() >= 21 ? Record[20] : 0; Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]); DISubprogram *SP = GET_OR_DISTINCT( DISubprogram, @@ -1947,8 +1951,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( HasAnnotations ? getMDOrNull(Record[18 + OffsetB]) : nullptr, // annotations HasTargetFuncName ? getMDString(Record[19 + OffsetB]) - : nullptr // targetFuncName - )); + : nullptr, // targetFuncName + NextAtomGroup)); MetadataList.assignValue(SP, NextMetadataNo); NextMetadataNo++; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 628b939af19ce..43e167ce84aaa 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1799,12 +1799,15 @@ unsigned ModuleBitcodeWriter::createDILocationAbbrev() { // location (it's never more expensive than building an array size 1). auto Abbv = std::make_shared(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_LOCATION)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isDistinct + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // line + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // column + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // scope + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // inlinedAt + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isImplicitCode + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, + 6)); // atomGroup | TODO tune the VBR size. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // atomRank return Stream.EmitAbbrev(std::move(Abbv)); } @@ -1820,7 +1823,8 @@ void ModuleBitcodeWriter::writeDILocation(const DILocation *N, Record.push_back(VE.getMetadataID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getInlinedAt())); Record.push_back(N->isImplicitCode()); - + Record.push_back(N->getAtomGroup()); + Record.push_back(N->getAtomRank()); Stream.EmitRecord(bitc::METADATA_LOCATION, Record, Abbrev); Record.clear(); } @@ -2141,7 +2145,8 @@ void ModuleBitcodeWriter::writeDISubprogram(const DISubprogram *N, Record.push_back(VE.getMetadataOrNullID(N->getThrownTypes().get())); Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); Record.push_back(VE.getMetadataOrNullID(N->getRawTargetFuncName())); - + Record.push_back( + N->getKeyInstructionsEnabled() ? N->getNextDILocationAtomGroup() : 0); Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev); Record.clear(); } @@ -3710,6 +3715,8 @@ void ModuleBitcodeWriter::writeFunction( if (DILocation *DL = I.getDebugLoc()) { if (DL == LastDL) { // Just repeat the same debug loc as last time. + // TODO: Probably want to have this ignore atom-group... Experiment + // with that. Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); } else { Vals.push_back(DL->getLine()); @@ -3717,6 +3724,8 @@ void ModuleBitcodeWriter::writeFunction( Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); Vals.push_back(DL->isImplicitCode()); + Vals.push_back(DL->getAtomGroup()); + Vals.push_back(DL->getAtomRank()); Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); Vals.clear(); LastDL = DL; diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/link-two-modes.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/link-two-modes.ll new file mode 100644 index 0000000000000..4ca718eef5869 --- /dev/null +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/link-two-modes.ll @@ -0,0 +1,67 @@ +; RUN: split-file %s %t +; RUN: llvm-as %t/key-instr-enabled.ll -o %t/key-instr-enabled.bc +; RUN: llvm-as %t/key-instr-disabled.ll -o %t/key-instr-disabled.bc +; RUN: llvm-link %t/key-instr-enabled.bc %t/key-instr-disabled.bc -o - | llvm-dis | FileCheck %s + +;; Check the Key Instructions metadata is preserved correctly when linking a +;; modules with Key Instructions enabled/disabled. + +;; Key Instructions enabled. +; CHECK: void @f() !dbg [[f:!.*]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void, !dbg [[enabled:!.*]] +; CHECK-NEXT: } + +;; Key Instructions disabled. +; CHECK: void @g() !dbg [[g:!.*]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void, !dbg [[disabled:!.*]] +; CHECK-NEXT: } + +; CHECK: !llvm.dbg.cu = !{!0, !2} +; CHECK-NEXT: !llvm.module.flags = !{!4} + +; CHECK: [[file1:!.*]] = !DIFile(filename: "key-instr-enabled.cpp", directory: "/") +; CHECK: [[file2:!.*]] = !DIFile(filename: "key-instr-disabled.cpp", directory: "/") +; CHECK: [[f]] = distinct !DISubprogram(name: "f", scope: [[file1]]{{.*}}, nextAtomGroup: 2) +; CHECK: [[enabled]] = !DILocation(line: 1, column: 11, scope: [[f]], atomGroup: 1, atomRank: 1) +; CHECK: [[g]] = distinct !DISubprogram(name: "g", scope: [[file2]] +; CHECK-NOT: nextAtomGroup +; CHECK-SAME: ) +; CHECK: [[disabled]] = !DILocation(line: 1, column: 11, scope: [[g]]) + +;--- key-instr-enabled.ll +define dso_local void @f() !dbg !10 { +entry: + ret void, !dbg !13 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "key-instr-enabled.cpp", directory: "/") +!3 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{!"clang version 21.0.0git"} +!10 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, nextAtomGroup: 2) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !DILocation(line: 1, column: 11, scope: !10, atomGroup: 1, atomRank: 1) + +;--- key-instr-disabled.ll +define dso_local void @g() !dbg !10 { +entry: + ret void, !dbg !13 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "key-instr-disabled.cpp", directory: "/") +!3 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{!"clang version 21.0.0git"} +!10 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !DILocation(line: 1, column: 11, scope: !10) \ No newline at end of file diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/roundtrip.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/roundtrip.ll new file mode 100644 index 0000000000000..a84cb4e3e7135 --- /dev/null +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/roundtrip.ll @@ -0,0 +1,82 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt %s -o - -S | llvm-as - | llvm-dis - | FileCheck %s + +; Key Instructions enabled. +define dso_local void @f() !dbg !5 { +; CHECK-LABEL: define dso_local void @f( +; CHECK-SAME: ) !dbg [[DBG5:![0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: ret void, !dbg [[DBG8:![0-9]+]] +; +entry: + ret void, !dbg !8 ; atomGroup: 1, atomRank: 1 +} + +; Key Instructions enabled, atomGroup > 1 and forward-ref scope in DILocation. +define dso_local void @g() !dbg !10 { +; CHECK-LABEL: define dso_local void @g( +; CHECK-SAME: ) !dbg [[DBG9:![0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: ret void, !dbg [[DBG10:![0-9]+]] +; +entry: + ret void, !dbg !9 ; atomGroup: 2, atomRank: 2 +} + +; Key Instructions not enabled. +define dso_local void @h() !dbg !11 { +; CHECK-LABEL: define dso_local void @h( +; CHECK-SAME: ) !dbg [[DBG11:![0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: ret void, !dbg [[DBG12:![0-9]+]] +; +entry: + ret void, !dbg !12 ; atomGroup: 0, atomRank: 0 +} + +; Key Instructions, inlined instruction (from g). +define dso_local void @i() !dbg !13 { +; CHECK-LABEL: define dso_local void @i( +; CHECK-SAME: ) !dbg [[DBG13:![0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: ret void, !dbg [[DBG14:![0-9]+]] +; +entry: + ret void, !dbg !14 ; scope g, inlinedAt i:4, atomGroup: 2, atomRank: 0 +} + +!llvm.dbg.cu = !{!0} +!llvm.debugify = !{!2, !3} +!llvm.module.flags = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "roundtrip.ll", directory: "/") +!2 = !{i32 2} +!3 = !{i32 0} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 2) +!6 = !DISubroutineType(types: !7) +!7 = !{} +!8 = !DILocation(line: 1, scope: !5, atomGroup: 1, atomRank: 1) +!9 = !DILocation(line: 2, scope: !10, atomGroup: 2, atomRank: 2) ; fwd-ref scope. +!10 = distinct !DISubprogram(name: "g", linkageName: "g", scope: null, file: !1, line: 2, type: !6, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) +!11 = distinct !DISubprogram(name: "h", linkageName: "h", scope: null, file: !1, line: 3, type: !6, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!12 = !DILocation(line: 3, scope: !11) +!13 = distinct !DISubprogram(name: "i", linkageName: "i", scope: null, file: !1, line: 4, type: !6, scopeLine: 4, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, nextAtomGroup: 3) +!14 = !DILocation(line: 2, scope: !10, inlinedAt: !15, atomGroup: 2, atomRank: 1) ; fwd-ref inlinedAt. +!15 = distinct !DILocation(line: 4, scope: !13) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +; CHECK: [[META1]] = !DIFile(filename: "{{.*}}roundtrip.ll", directory: {{.*}}) +; CHECK: [[DBG5]] = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], nextAtomGroup: 2) +; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]]) +; CHECK: [[META7]] = !{} +; CHECK: [[DBG8]] = !DILocation(line: 1, scope: [[DBG5]], atomGroup: 1, atomRank: 1) +; CHECK: [[DBG9]] = distinct !DISubprogram(name: "g", linkageName: "g", scope: null, file: [[META1]], line: 2, type: [[META6]], scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], nextAtomGroup: 3) +; CHECK: [[DBG10]] = !DILocation(line: 2, scope: [[DBG9]], atomGroup: 2, atomRank: 2) +; CHECK: [[DBG11]] = distinct !DISubprogram(name: "h", linkageName: "h", scope: null, file: [[META1]], line: 3, type: [[META6]], scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]]) +; CHECK: [[DBG12]] = !DILocation(line: 3, scope: [[DBG11]]) +; CHECK: [[DBG13]] = distinct !DISubprogram(name: "i", linkageName: "i", scope: null, file: [[META1]], line: 4, type: [[META6]], scopeLine: 4, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], nextAtomGroup: 3) +; CHECK: [[DBG14]] = !DILocation(line: 2, scope: [[DBG9]], inlinedAt: [[META15:![0-9]+]], atomGroup: 2, atomRank: 1) +; CHECK: [[META15]] = distinct !DILocation(line: 4, scope: [[DBG13]]) +;. From 8aa823ce499463a337f69ec2ab6f6529b9122951 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Tue, 10 Jun 2025 17:33:55 +0100 Subject: [PATCH 7/7] Revert "revert DWARF stuff" This reverts commit 4e5b7a875e11e8f02306792bca0040014e1a89c1. --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c78257fcfca10..651adda32175e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -169,8 +169,10 @@ static cl::opt MinimizeAddrInV5Option( "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default)); +/// Chicken-bit that can be set to false to disable the interpretation of Key +/// Instructions metadata for is_stmt placement. static cl::opt KeyInstructionsAreStmts("dwarf-use-key-instructions", - cl::Hidden, cl::init(false)); + cl::Hidden, cl::init(true)); static constexpr unsigned ULEB128PadSize = 4; @@ -2077,8 +2079,16 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { unsigned LastAsmLine = Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); + // Not-Key-Instructions functions inlined into Key Instructions functions + // should fall back to default is_stmt handling. + bool ScopeUsesKeyInstructions = + KeyInstructionsAreStmts && SP->getKeyInstructionsEnabled(); + if (ScopeUsesKeyInstructions && DL && DL.getInlinedAt()) + ScopeUsesKeyInstructions = + DL->getScope()->getSubprogram()->getKeyInstructionsEnabled(); + bool IsKey = false; - if (KeyInstructionsAreStmts && DL && DL.getLine()) + if (ScopeUsesKeyInstructions && DL && DL.getLine()) IsKey = KeyInstructions.contains(MI); if (!DL && MI == PrologEndLoc) { @@ -2158,7 +2168,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { PrologEndLoc = nullptr; } - if (KeyInstructionsAreStmts) { + if (ScopeUsesKeyInstructions) { if (IsKey) Flags |= DWARF2_FLAG_IS_STMT; } else { @@ -2437,7 +2447,7 @@ void DwarfDebug::computeKeyInstructions(const MachineFunction *MF) { } auto *InlinedAt = MI.getDebugLoc()->getInlinedAt(); - uint64_t Group = MI.getDebugLoc()->getAtomGroup(); + uint32_t Group = MI.getDebugLoc()->getAtomGroup(); uint8_t Rank = MI.getDebugLoc()->getAtomRank(); if (!Group) continue; @@ -2655,7 +2665,13 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) { PrologEndLoc = emitInitialLocDirective( *MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID()); - if (KeyInstructionsAreStmts) + // If this function wasn't built with Key Instructions but has a function + // inlined into it that was, we treat the inlined instance as if it wasn't + // built with Key Instructions. If this function was built with Key + // Instructions but a function inlined into it wasn't then we continue to use + // Key Instructions for this function and fall back to non-key behaviour for + // the inlined function (except it doesn't beneit from findForceIsStmtInstrs). + if (KeyInstructionsAreStmts && SP->getKeyInstructionsEnabled()) computeKeyInstructions(MF); else findForceIsStmtInstrs(MF);