From 53c014009fa285447d257b1e5463a018a90ee1c0 Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Thu, 19 Sep 2024 22:32:12 +0000 Subject: [PATCH 1/3] Fix performance bug in buildLocationList In buildLocationList, with basic block sections, we iterate over every basic block twice to detect section start and end. This is sub-optimal and shows up as significantly time consuming when compiling large functions. This patch uses the set of sections already stored in MBBSectionRanges and iterates over sections rather than basic blocks. When detecting if loclists can be merged, the end label of an entry is matched with the beginning label of the next entry. For the section corresponding to the entry basic block, this is skipped. This is because the loc list uses the end label corresponding to the function whereas the MBBSectionRanges map uses the function end label. For example: .Lfunc_begin0: .file .loc 0 4 0 # ex2.cc:4:0 .cfi_startproc .Ltmp0: .loc 0 8 5 prologue_end # ex2.cc:8:5 .... .LBB_END0_0: .cfi_endproc .section .text._Z4testv,"ax",@progbits,unique,1 ... .Lfunc_end0: .size _Z4testv, .Lfunc_end0-_Z4testv The debug loc uses ".LBB_END0_0" for the end of the section whereas MBBSectionRanges uses ".Lfunc_end0". It is alright to skip this as we already check the section corresponding to the debugloc entry. Added a new test case to check that if this works correctly when the variable's value is mutated in the entry section. --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 13 ++- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 38 ++++---- .../basic-block-sections-debug-loclist-6.ll | 92 +++++++++++++++++++ .../DebugInfo/X86/basic-block-sections_1.ll | 6 +- 4 files changed, 123 insertions(+), 26 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-6.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index db7adfd3b21e5..4c5afaa513275 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1737,6 +1737,12 @@ void AsmPrinter::emitFunctionBody() { bool IsEHa = MMI->getModule()->getModuleFlag("eh-asynch"); bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE); + // Create a slot for the entry basic block section so that the section + // order is preserved when iterating over MBBSectionRanges. + if (!MF->empty()) + MBBSectionRanges[MF->front().getSectionID()] = + MBBSectionRange{CurrentFnBegin, nullptr}; + for (auto &MBB : *MF) { // Print a label for the basic block. emitBasicBlockStart(MBB); @@ -2000,11 +2006,8 @@ void AsmPrinter::emitFunctionBody() { } for (auto &Handler : Handlers) Handler->markFunctionEnd(); - - assert(!MBBSectionRanges.contains(MF->front().getSectionID()) && - "Overwrite section range"); - MBBSectionRanges[MF->front().getSectionID()] = - MBBSectionRange{CurrentFnBegin, CurrentFnEnd}; + // Update the end label of the entry block's section. + MBBSectionRanges[MF->front().getSectionID()].EndLabel = CurrentFnEnd; // Print out jump tables referenced by the function. emitJumpTableInfo(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index e9649f9ff8165..890deb319ea73 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -34,6 +34,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" @@ -1772,18 +1773,14 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, // span each individual section in the range from StartLabel to EndLabel. if (Asm->MF->hasBBSections() && StartLabel == Asm->getFunctionBegin() && !Instr->getParent()->sameSection(&Asm->MF->front())) { - const MCSymbol *BeginSectionLabel = StartLabel; - - for (const MachineBasicBlock &MBB : *Asm->MF) { - if (MBB.isBeginSection() && &MBB != &Asm->MF->front()) - BeginSectionLabel = MBB.getSymbol(); - - if (MBB.sameSection(Instr->getParent())) { - DebugLoc.emplace_back(BeginSectionLabel, EndLabel, Values); + for (const auto &[MBBSectionId, MBBSectionRange] : + Asm->MBBSectionRanges) { + if (Instr->getParent()->getSectionID() == MBBSectionId) { + DebugLoc.emplace_back(MBBSectionRange.BeginLabel, EndLabel, Values); break; } - if (MBB.isEndSection()) - DebugLoc.emplace_back(BeginSectionLabel, MBB.getEndSymbol(), Values); + DebugLoc.emplace_back(MBBSectionRange.BeginLabel, + MBBSectionRange.EndLabel, Values); } } else { DebugLoc.emplace_back(StartLabel, EndLabel, Values); @@ -1824,22 +1821,27 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, RangeMBB = &Asm->MF->front(); else RangeMBB = Entries.begin()->getInstr()->getParent(); + auto RangeIt = Asm->MBBSectionRanges.find(RangeMBB->getSectionID()); + assert(RangeIt != Asm->MBBSectionRanges.end() && + "Range MBB not found in MBBSectionRanges!"); auto *CurEntry = DebugLoc.begin(); auto *NextEntry = std::next(CurEntry); + auto NextRangeIt = std::next(RangeIt); while (NextEntry != DebugLoc.end()) { - // Get the last machine basic block of this section. - while (!RangeMBB->isEndSection()) - RangeMBB = RangeMBB->getNextNode(); - if (!RangeMBB->getNextNode()) + if (NextRangeIt == Asm->MBBSectionRanges.end()) return false; // CurEntry should end the current section and NextEntry should start // the next section and the Values must match for these two ranges to be - // merged. - if (CurEntry->getEndSym() != RangeMBB->getEndSymbol() || - NextEntry->getBeginSym() != RangeMBB->getNextNode()->getSymbol() || + // merged. Do not match the section label end if it is the entry block + // section. This is because the end label for the Debug Loc and the + // Function end label could be different. + if ((RangeIt->second.EndLabel != Asm->getFunctionEnd() && + CurEntry->getEndSym() != RangeIt->second.EndLabel) || + NextEntry->getBeginSym() != NextRangeIt->second.BeginLabel || CurEntry->getValues() != NextEntry->getValues()) return false; - RangeMBB = RangeMBB->getNextNode(); + RangeIt = NextRangeIt; + NextRangeIt = std::next(RangeIt); CurEntry = NextEntry; NextEntry = std::next(CurEntry); } diff --git a/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-6.ll b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-6.ll new file mode 100644 index 0000000000000..8c8eef68b2ec0 --- /dev/null +++ b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-6.ll @@ -0,0 +1,92 @@ +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s + +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +7, DW_OP_stack_value +; CHECK-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +8, DW_OP_stack_value +; CHECK-NEXT: DW_AT_name ("i") + +; SECTIONS: DW_TAG_variable +; SECTIONS-NEXT: DW_AT_location +; SECTIONS-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +7, DW_OP_stack_value +; SECTIONS-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +8, DW_OP_stack_value +; SECTIONS-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +8, DW_OP_stack_value +; SECTIONS-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_consts +8, DW_OP_stack_value +; SECTIONS-NEXT: DW_AT_name ("i") + +; Source to generate the IR below: +; void f1(); +; extern bool b; +; void test() { +; // i is not a const throughout the whole scope and should +; // not use DW_AT_const_value +; int i = 7; +; f1(); +; i = 8; +; if (b) +; f1(); +; } +; $ clang++ -S loclist_section.cc -O2 -g -emit-llvm + +@b = external local_unnamed_addr global i8, align 1 + +; Function Attrs: mustprogress uwtable +define dso_local void @_Z4testv() local_unnamed_addr #0 !dbg !10 { +entry: + #dbg_value(i32 7, !14, !DIExpression(), !16) + tail call void @_Z2f1v(), !dbg !17 + #dbg_value(i32 8, !14, !DIExpression(), !16) + %0 = load i8, ptr @b, align 1, !dbg !18, !tbaa !20, !range !24, !noundef !25 + %loadedv = trunc nuw i8 %0 to i1, !dbg !18 + br i1 %loadedv, label %if.then, label %if.end, !dbg !26 + +if.then: ; preds = %entry + tail call void @_Z2f1v(), !dbg !27 + br label %if.end, !dbg !27 + +if.end: ; preds = %if.then, %entry + ret void, !dbg !28 +} + +declare !dbg !29 void @_Z2f1v() local_unnamed_addr #1 + +attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 20.0.0git (git@github.com:)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "loclist_section.cc", directory: "Examples/debug_loc", checksumkind: CSK_MD5, checksum: "67769a94389681c8a6da481e2f358abb") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true} +!9 = !{!"clang version 20.0.0git (git@github.com:.../llvm-project.git 7c3256280a78b0505ae4d43985c4d3239451a151)"} +!10 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !{!14} +!14 = !DILocalVariable(name: "i", scope: !10, file: !1, line: 6, type: !15) +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !DILocation(line: 0, scope: !10) +!17 = !DILocation(line: 7, column: 5, scope: !10) +!18 = !DILocation(line: 9, column: 9, scope: !19) +!19 = distinct !DILexicalBlock(scope: !10, file: !1, line: 9, column: 9) +!20 = !{!21, !21, i64 0} +!21 = !{!"bool", !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C++ TBAA"} +!24 = !{i8 0, i8 2} +!25 = !{} +!26 = !DILocation(line: 9, column: 9, scope: !10) +!27 = !DILocation(line: 10, column: 7, scope: !19) +!28 = !DILocation(line: 11, column: 1, scope: !10) +!29 = !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 1, type: !11, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) diff --git a/llvm/test/DebugInfo/X86/basic-block-sections_1.ll b/llvm/test/DebugInfo/X86/basic-block-sections_1.ll index 12b60c4dc321b..c90d715142ec8 100644 --- a/llvm/test/DebugInfo/X86/basic-block-sections_1.ll +++ b/llvm/test/DebugInfo/X86/basic-block-sections_1.ll @@ -16,10 +16,10 @@ ; NO-SECTIONS: DW_AT_high_pc [DW_FORM_data4] ({{.*}}) ; BB-SECTIONS: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) ; BB-SECTIONS-NEXT: DW_AT_ranges [DW_FORM_sec_offset] +; BB-SECTIONS-NEXT: [{{.*}}) ".text.hot._Z3fooi" ; BB-SECTIONS-NEXT: [{{.*}}) ".text.hot._Z3fooi._Z3fooi.__part.1" ; BB-SECTIONS-NEXT: [{{.*}}) ".text.hot._Z3fooi._Z3fooi.__part.2" ; BB-SECTIONS-NEXT: [{{.*}}) ".text.hot._Z3fooi._Z3fooi.__part.3" -; BB-SECTIONS-NEXT: [{{.*}}) ".text.hot._Z3fooi" ; BB-SECTIONS-ASM: _Z3fooi: ; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}: ; BB-SECTIONS-ASM-NEXT: .loc 1 2 9 prologue_end @@ -36,14 +36,14 @@ ; BB-SECTIONS-ASM: .size _Z3fooi.__part.3, .LBB_END0_{{[0-9]+}}-_Z3fooi.__part.3 ; BB-SECTIONS-ASM: .Lfunc_end0: ; BB-SECTIONS-ASM: .Ldebug_ranges0: +; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_begin0 +; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_end0 ; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.__part.1 ; BB-SECTIONS-ASM-NEXT: .quad .LBB_END0_{{[0-9]+}} ; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.__part.2 ; BB-SECTIONS-ASM-NEXT: .quad .LBB_END0_{{[0-9]+}} ; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.__part.3 ; BB-SECTIONS-ASM-NEXT: .quad .LBB_END0_{{[0-9]+}} -; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_begin0 -; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_end0 ; BB-SECTIONS-ASM-NEXT: .quad 0 ; BB-SECTIONS-ASM-NEXT: .quad 0 ; BB-SECTIONS-LINE-TABLE: 0x0000000000000000 1 0 1 0 0 0 is_stmt From 11a50269e82b6dce49249c5cbe3a989b06f0848f Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Mon, 23 Sep 2024 22:29:30 +0000 Subject: [PATCH 2/3] Const value variable within a scope test. Test to check that a variable declared within a scope that has basic block sections still produces DW_AT_const_value. --- .../basic-block-sections-debug-loclist-7.ll | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-7.ll diff --git a/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-7.ll b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-7.ll new file mode 100644 index 0000000000000..1afef53c45454 --- /dev/null +++ b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-7.ll @@ -0,0 +1,129 @@ +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s + +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc +; CHECK-NEXT: DW_AT_high_pc +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_const_value (7) +; CHECK-NEXT: DW_AT_name ("i") + +; SECTIONS: DW_TAG_lexical_block +; SECTIONS-NEXT: DW_AT_ranges +; SECTIONS: DW_TAG_variable +; SECTIONS-NEXT: DW_AT_const_value (7) +; SECTIONS-NEXT: DW_AT_name ("i") + +; Test to check that a variable declared within a scope that has basic block +; sections still produces DW_AT_const_value. +; Source to generate the IR below: + +; void f1(int *); +; extern bool b; +; int test() { +; // i is const throughout the whole scope and should +; // use DW_AT_const_value. The scope creates basic +; // block sections and should use DW_AT_ranges. +; int j = 10; +; { +; int i = 7; +; f1(&j); +; if (b) +; f1(&j); +; } +; return j; +; } +; +; clang++ -S scoped_section_const.cc -g -O2 -emit-llvm + +@b = external local_unnamed_addr global i8, align 1 + +; Function Attrs: mustprogress uwtable +define dso_local noundef i32 @_Z4testv() local_unnamed_addr #0 !dbg !9 { + %1 = alloca i32, align 4 + call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %1) #4, !dbg !17 + call void @llvm.dbg.value(metadata i32 10, metadata !14, metadata !DIExpression()), !dbg !18 + store i32 10, ptr %1, align 4, !dbg !19, !tbaa !20 + call void @llvm.dbg.value(metadata i32 7, metadata !15, metadata !DIExpression()), !dbg !24 + call void @llvm.dbg.value(metadata ptr %1, metadata !14, metadata !DIExpression(DW_OP_deref)), !dbg !18 + call void @_Z2f1Pi(ptr noundef nonnull %1), !dbg !25 + %2 = load i8, ptr @b, align 1, !dbg !26, !tbaa !28, !range !30, !noundef !31 + %3 = icmp eq i8 %2, 0, !dbg !26 + br i1 %3, label %5, label %4, !dbg !32 + +4: ; preds = %0 + call void @llvm.dbg.value(metadata ptr %1, metadata !14, metadata !DIExpression(DW_OP_deref)), !dbg !18 + call void @_Z2f1Pi(ptr noundef nonnull %1), !dbg !33 + br label %5, !dbg !33 + +5: ; preds = %4, %0 + %6 = load i32, ptr %1, align 4, !dbg !34, !tbaa !20 + call void @llvm.dbg.value(metadata i32 %6, metadata !14, metadata !DIExpression()), !dbg !18 + call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %1) #4, !dbg !35 + ret i32 %6, !dbg !36 +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 + +declare !dbg !37 void @_Z2f1Pi(ptr noundef) local_unnamed_addr #2 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "Debian clang version 16.0.6 (26)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "scoped_section_const.cc", directory: "", checksumkind: CSK_MD5, checksum: "0406492d2e2e38af35d9ea210ba1f24b") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{!"Debian clang version 16.0.6 (26)"} +!9 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 3, type: !10, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!10 = !DISubroutineType(types: !11) +!11 = !{!12} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{!14, !15} +!14 = !DILocalVariable(name: "j", scope: !9, file: !1, line: 6, type: !12) +!15 = !DILocalVariable(name: "i", scope: !16, file: !1, line: 8, type: !12) +!16 = distinct !DILexicalBlock(scope: !9, file: !1, line: 7, column: 5) +!17 = !DILocation(line: 6, column: 5, scope: !9) +!18 = !DILocation(line: 0, scope: !9) +!19 = !DILocation(line: 6, column: 9, scope: !9) +!20 = !{!21, !21, i64 0} +!21 = !{!"int", !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C++ TBAA"} +!24 = !DILocation(line: 0, scope: !16) +!25 = !DILocation(line: 9, column: 7, scope: !16) +!26 = !DILocation(line: 10, column: 11, scope: !27) +!27 = distinct !DILexicalBlock(scope: !16, file: !1, line: 10, column: 11) +!28 = !{!29, !29, i64 0} +!29 = !{!"bool", !22, i64 0} +!30 = !{i8 0, i8 2} +!31 = !{} +!32 = !DILocation(line: 10, column: 11, scope: !16) +!33 = !DILocation(line: 11, column: 9, scope: !27) +!34 = !DILocation(line: 13, column: 12, scope: !9) +!35 = !DILocation(line: 14, column: 1, scope: !9) +!36 = !DILocation(line: 13, column: 5, scope: !9) +!37 = !DISubprogram(name: "f1", linkageName: "_Z2f1Pi", scope: !1, file: !1, line: 1, type: !38, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !31) +!38 = !DISubroutineType(types: !39) +!39 = !{null, !40} +!40 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) From 5c8bec43babf93e89c1c3c3f252fc15d25fe2f5a Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Wed, 30 Oct 2024 22:16:10 +0000 Subject: [PATCH 3/3] Two more test cases where DW_AT_const cannot be used. These test cases check loclist merging in buildLocationList with basic block sections. 8.ll does not create any basic block sections and the merging must quit early because there is no constant value. 9.11 creates sections but cannot be merged as i is not a constant value. --- .../basic-block-sections-debug-loclist-8.ll | 107 +++++++++++++ .../basic-block-sections-debug-loclist-9.ll | 142 ++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-8.ll create mode 100644 llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-9.ll diff --git a/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-8.ll b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-8.ll new file mode 100644 index 0000000000000..d1af3c2c3ef3e --- /dev/null +++ b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-8.ll @@ -0,0 +1,107 @@ +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s + +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: DW_OP_consts +0, DW_OP_stack_value +; CHECK-NEXT: DW_OP_consts +7, DW_OP_stack_value +; CHECK-NEXT: DW_OP_consts +8, DW_OP_stack_value +; CHECK: DW_AT_name ("i") + +; void f1(int *); +; void f2(int); +; extern bool b; +; int test() { +; // i is not a const throughout the whole scope and +; // should *not* use DW_AT_const_value. +; int i = 0; +; int j = 10; +; { +; i = 7; +; f1(&j); +; } +; i = 8; +; f2(i); +; return j; +; } +; clang++ -S scoped_section.cc -g -O2 -emit-llvm + +; Function Attrs: mustprogress uwtable +define dso_local noundef i32 @_Z4testv() local_unnamed_addr #0 !dbg !10 { +entry: + %j = alloca i32, align 4, !DIAssignID !17 + #dbg_assign(i1 undef, !16, !DIExpression(), !17, ptr %j, !DIExpression(), !18) + #dbg_value(i32 0, !15, !DIExpression(), !18) + call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %j) #3, !dbg !19 + store i32 10, ptr %j, align 4, !dbg !20, !tbaa !21, !DIAssignID !25 + #dbg_assign(i32 10, !16, !DIExpression(), !25, ptr %j, !DIExpression(), !18) + #dbg_value(i32 7, !15, !DIExpression(), !18) + call void @_Z2f1Pi(ptr noundef nonnull %j), !dbg !26 + #dbg_value(i32 8, !15, !DIExpression(), !18) + call void @_Z2f2i(i32 noundef 8), !dbg !28 + %0 = load i32, ptr %j, align 4, !dbg !29, !tbaa !21 + call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %j) #3, !dbg !30 + ret i32 %0, !dbg !31 +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 + +declare !dbg !32 void @_Z2f1Pi(ptr noundef) local_unnamed_addr #2 + +declare !dbg !36 void @_Z2f2i(i32 noundef) local_unnamed_addr #2 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 + +attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 20.0.0git (git@github.com:tmsri/llvm-project.git 11a50269e82b6dce49249c5cbe3a989b06f0848f)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "scoped_section.cc", directory: "", checksumkind: CSK_MD5, checksum: "2d5675e292541e4f04eb60edf76b14d6") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true} +!9 = !{!"clang version 20.0.0git (git@github.com:tmsri/llvm-project.git 11a50269e82b6dce49249c5cbe3a989b06f0848f)"} +!10 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14) +!11 = !DISubroutineType(types: !12) +!12 = !{!13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !{!15, !16} +!15 = !DILocalVariable(name: "i", scope: !10, file: !1, line: 7, type: !13) +!16 = !DILocalVariable(name: "j", scope: !10, file: !1, line: 8, type: !13) +!17 = distinct !DIAssignID() +!18 = !DILocation(line: 0, scope: !10) +!19 = !DILocation(line: 8, column: 5, scope: !10) +!20 = !DILocation(line: 8, column: 9, scope: !10) +!21 = !{!22, !22, i64 0} +!22 = !{!"int", !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C++ TBAA"} +!25 = distinct !DIAssignID() +!26 = !DILocation(line: 11, column: 7, scope: !27) +!27 = distinct !DILexicalBlock(scope: !10, file: !1, line: 9, column: 5) +!28 = !DILocation(line: 14, column: 5, scope: !10) +!29 = !DILocation(line: 15, column: 12, scope: !10) +!30 = !DILocation(line: 16, column: 1, scope: !10) +!31 = !DILocation(line: 15, column: 5, scope: !10) +!32 = !DISubprogram(name: "f1", linkageName: "_Z2f1Pi", scope: !1, file: !1, line: 1, type: !33, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!33 = !DISubroutineType(types: !34) +!34 = !{null, !35} +!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!36 = !DISubprogram(name: "f2", linkageName: "_Z2f2i", scope: !1, file: !1, line: 2, type: !37, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!37 = !DISubroutineType(types: !38) +!38 = !{null, !13} \ No newline at end of file diff --git a/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-9.ll b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-9.ll new file mode 100644 index 0000000000000..a60fd106745b9 --- /dev/null +++ b/llvm/test/DebugInfo/X86/basic-block-sections-debug-loclist-9.ll @@ -0,0 +1,142 @@ +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=4 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=none -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu --dwarf-version=5 --basic-block-sections=all -filetype=obj -o - | llvm-dwarfdump - | FileCheck --check-prefix=SECTIONS %s + +; CHECK: DW_TAG_subprogram +; CHECK-NEXT: DW_AT_low_pc +; CHECK-NEXT: DW_AT_high_pc +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: DW_OP_consts +0, DW_OP_stack_value +; CHECK-NEXT: DW_OP_consts +7, DW_OP_stack_value +; CHECK-NEXT: DW_OP_consts +8, DW_OP_stack_value +; CHECK-NEXT: DW_AT_name ("i") + +; SECTIONS: DW_TAG_subprogram +; SECTIONS-NEXT: DW_AT_ranges +; SECTIONS: DW_TAG_variable +; SECTIONS: DW_TAG_variable +; SECTIONS-NEXT: DW_AT_location +; SECTIONS-NEXT: DW_OP_consts +0, DW_OP_stack_value +; SECTIONS-NEXT: DW_OP_consts +7, DW_OP_stack_value +; SECTIONS-NEXT: DW_OP_consts +7, DW_OP_stack_value +; SECTIONS-NEXT: DW_OP_consts +8, DW_OP_stack_value +; SECTIONS-NEXT: DW_AT_name ("i") + +; void f1(int *); +; void f2(int); +; extern bool b; +; int test() { +; // i is not a const throughout the whole scope and +; // should *not* use DW_AT_const_value. The scope +; // creates basic block sections and should use +; // DW_AT_ranges. +; int i = 0; +; int j = 10; +; { +; i = 7; +; if (b) +; f1(&j); +; } +; i = 8; +; f2(i); +; return j; +; } +; clang++ -S scoped_section.cc -g -O2 -emit-llvm + + +@b = external local_unnamed_addr global i8, align 1 + +; Function Attrs: mustprogress uwtable +define dso_local noundef i32 @_Z4testv() local_unnamed_addr #0 !dbg !10 { +entry: + %j = alloca i32, align 4, !DIAssignID !17 + #dbg_assign(i1 undef, !16, !DIExpression(), !17, ptr %j, !DIExpression(), !18) + #dbg_value(i32 0, !15, !DIExpression(), !18) + call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %j) #3, !dbg !19 + store i32 10, ptr %j, align 4, !dbg !20, !tbaa !21, !DIAssignID !25 + #dbg_assign(i32 10, !16, !DIExpression(), !25, ptr %j, !DIExpression(), !18) + #dbg_value(i32 7, !15, !DIExpression(), !18) + %0 = load i8, ptr @b, align 1, !dbg !26, !tbaa !29, !range !31, !noundef !32 + %loadedv = trunc nuw i8 %0 to i1, !dbg !26 + br i1 %loadedv, label %if.then, label %if.end, !dbg !33 + +if.then: ; preds = %entry + call void @_Z2f1Pi(ptr noundef nonnull %j), !dbg !34 + br label %if.end, !dbg !34 + +if.end: ; preds = %if.then, %entry + #dbg_value(i32 8, !15, !DIExpression(), !18) + call void @_Z2f2i(i32 noundef 8), !dbg !35 + %1 = load i32, ptr %j, align 4, !dbg !36, !tbaa !21 + call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %j) #3, !dbg !37 + ret i32 %1, !dbg !38 +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 + +declare !dbg !39 void @_Z2f1Pi(ptr noundef) local_unnamed_addr #2 + +declare !dbg !43 void @_Z2f2i(i32 noundef) local_unnamed_addr #2 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 + +attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 20.0.0git (git@github.com:tmsri/llvm-project.git 11a50269e82b6dce49249c5cbe3a989b06f0848f)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "scoped_section.cc", directory: "", checksumkind: CSK_MD5, checksum: "9dda8d16c16edf7724c901692e07587c") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true} +!9 = !{!"clang version 20.0.0git (git@github.com:tmsri/llvm-project.git 11a50269e82b6dce49249c5cbe3a989b06f0848f)"} +!10 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14) +!11 = !DISubroutineType(types: !12) +!12 = !{!13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !{!15, !16} +!15 = !DILocalVariable(name: "i", scope: !10, file: !1, line: 7, type: !13) +!16 = !DILocalVariable(name: "j", scope: !10, file: !1, line: 8, type: !13) +!17 = distinct !DIAssignID() +!18 = !DILocation(line: 0, scope: !10) +!19 = !DILocation(line: 8, column: 5, scope: !10) +!20 = !DILocation(line: 8, column: 9, scope: !10) +!21 = !{!22, !22, i64 0} +!22 = !{!"int", !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C++ TBAA"} +!25 = distinct !DIAssignID() +!26 = !DILocation(line: 11, column: 11, scope: !27) +!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 11, column: 11) +!28 = distinct !DILexicalBlock(scope: !10, file: !1, line: 9, column: 5) +!29 = !{!30, !30, i64 0} +!30 = !{!"bool", !23, i64 0} +!31 = !{i8 0, i8 2} +!32 = !{} +!33 = !DILocation(line: 11, column: 11, scope: !28) +!34 = !DILocation(line: 12, column: 9, scope: !27) +!35 = !DILocation(line: 15, column: 5, scope: !10) +!36 = !DILocation(line: 16, column: 12, scope: !10) +!37 = !DILocation(line: 17, column: 1, scope: !10) +!38 = !DILocation(line: 16, column: 5, scope: !10) +!39 = !DISubprogram(name: "f1", linkageName: "_Z2f1Pi", scope: !1, file: !1, line: 1, type: !40, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!40 = !DISubroutineType(types: !41) +!41 = !{null, !42} +!42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!43 = !DISubprogram(name: "f2", linkageName: "_Z2f2i", scope: !1, file: !1, line: 2, type: !44, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!44 = !DISubroutineType(types: !45) +!45 = !{null, !13} \ No newline at end of file