Index: llvm/docs/SourceLevelDebugging.rst =================================================================== --- llvm/docs/SourceLevelDebugging.rst +++ llvm/docs/SourceLevelDebugging.rst @@ -770,7 +770,9 @@ positions, translating virtual register references into their physical machine locations. To avoid encoding incorrect variable locations, in this pass any DBG_VALUE of a virtual register that is not live, is replaced by -the undefined location. +the undefined location. After the LiveDebugVariables is being done, we can +end up having redundant DBG_VALUEs (because of virtual register rewritting), +so the RemoveRedundantDebugValues pass removes all such DBG_VALUEs. LiveDebugValues expansion of variable locations ----------------------------------------------- Index: llvm/include/llvm/CodeGen/CodeGenPassBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/CodeGenPassBuilder.h +++ llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -869,6 +869,8 @@ // Run post-ra passes. derived().addPostRegAlloc(addPass); + addPass(RemoveRedundantDebugValuesPass()); + // Insert prolog/epilog code. Eliminate abstract frame index references... if (getOptLevel() != CodeGenOpt::None) { addPass(PostRAMachineSinkingPass()); Index: llvm/include/llvm/CodeGen/MachinePassRegistry.def =================================================================== --- llvm/include/llvm/CodeGen/MachinePassRegistry.def +++ llvm/include/llvm/CodeGen/MachinePassRegistry.def @@ -155,6 +155,7 @@ DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass, ()) DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ()) DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("removeredundantdebugvalues", RemoveRedundantDebugValuesPass, ()) DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ()) DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass, ()) DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ()) Index: llvm/include/llvm/CodeGen/Passes.h =================================================================== --- llvm/include/llvm/CodeGen/Passes.h +++ llvm/include/llvm/CodeGen/Passes.h @@ -386,6 +386,9 @@ /// the intrinsic for later emission to the StackMap. extern char &StackMapLivenessID; + /// RemoveRedundantDebugValues pass. + extern char &RemoveRedundantDebugValuesID; + /// LiveDebugValues pass extern char &LiveDebugValuesID; Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -382,6 +382,7 @@ void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); +void initializeRemoveRedundantDebugValuesPass(PassRegistry&); void initializeRenameIndependentSubregsPass(PassRegistry&); void initializeReplaceWithVeclibLegacyPass(PassRegistry &); void initializeResetMachineFunctionPass(PassRegistry&); Index: llvm/lib/CodeGen/CMakeLists.txt =================================================================== --- llvm/lib/CodeGen/CMakeLists.txt +++ llvm/lib/CodeGen/CMakeLists.txt @@ -142,6 +142,7 @@ RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp + RemoveRedundantDebugValues.cpp RenameIndependentSubregs.cpp MachineStableHash.cpp MIRVRegNamerUtils.cpp Index: llvm/lib/CodeGen/CodeGen.cpp =================================================================== --- llvm/lib/CodeGen/CodeGen.cpp +++ llvm/lib/CodeGen/CodeGen.cpp @@ -97,6 +97,7 @@ initializeRegUsageInfoCollectorPass(Registry); initializeRegUsageInfoPropagationPass(Registry); initializeRegisterCoalescerPass(Registry); + initializeRemoveRedundantDebugValuesPass(Registry); initializeRenameIndependentSubregsPass(Registry); initializeSafeStackLegacyPassPass(Registry); initializeShrinkWrapPass(Registry); Index: llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp =================================================================== --- /dev/null +++ llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp @@ -0,0 +1,137 @@ +//===- RemoveRedundantDebugValues.cpp - Remove Redundant Debug Value MIs --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" + +/// \file RemoveRedundantDebugValues.cpp +/// +/// The RemoveRedundantDebugValues removes redundant DBG_VALUEs that +/// appear in MIR after the register allocator. + +#define DEBUG_TYPE "removeredundantdebugvalues" + +using namespace llvm; + +STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)"); + +namespace { + +class RemoveRedundantDebugValues : public MachineFunctionPass { +public: + static char ID; + + RemoveRedundantDebugValues(); + + bool reduceDbgValues(MachineFunction &MF); + + /// Remove redundant debug value MIs for the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } +}; + +} // namespace + +//===----------------------------------------------------------------------===// +// Implementation +//===----------------------------------------------------------------------===// + +char RemoveRedundantDebugValues::ID = 0; + +char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValues::ID; + +INITIALIZE_PASS(RemoveRedundantDebugValues, DEBUG_TYPE, + "Remove Redundant DEBUG_VALUE analysis", false, false) + +/// Default construct and initialize the pass. +RemoveRedundantDebugValues::RemoveRedundantDebugValues() + : MachineFunctionPass(ID) { + initializeRemoveRedundantDebugValuesPass(*PassRegistry::getPassRegistry()); +} + +// This analysis aims to remove redundant DBG_VALUEs by going backward +// in the basic block by considering the latest DBG_VALUE in a row of +// consecutive DBG_VALUEs for the same variable as the one that is relevant +// value representation. +// For example: +// (1) DBG_VALUE $edi, !"var1", ... +// (2) DBG_VALUE $esi, !"var2", ... +// (3) DBG_VALUE $edi, !"var1", ... +// ... +// in this case, we can remove (1). +static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) { + LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n"); + SmallVector DbgValsToBeRemoved; + SmallDenseSet VariableSet; + + for (MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend(); + I != E; ++I) { + MachineInstr *MI = &*I; + + if (MI->isDebugValue()) { + DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(), + MI->getDebugLoc()->getInlinedAt()); + auto R = VariableSet.insert(Var); + // We have already encountered the value for this variable, + // so this one can be deleted. + if (!R.second) + DbgValsToBeRemoved.push_back(MI); + continue; + } + + // If we encountered a non-DBG_VALUE, try to find the next + // sequence with consecutive DBG_VALUE instructions. + VariableSet.clear(); + } + + for (auto &Instr : DbgValsToBeRemoved) { + LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); + Instr->eraseFromParent(); + ++NumRemovedBackward; + } + + return !DbgValsToBeRemoved.empty(); +} + +// TODO: Support DBG_VALUE_LIST and other debug instructions. +bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) { + LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n"); + + bool Changed = false; + + for (auto &MBB : MF) + Changed |= reduceDbgValsBackwardScan(MBB); + + return Changed; +} + +bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) { + // Skip functions without debugging information. + if (!MF.getFunction().getSubprogram()) + return false; + + // Skip functions from NoDebug compilation units. + if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == + DICompileUnit::NoDebug) + return false; + + bool Changed = reduceDbgValues(MF); + return Changed; +} Index: llvm/lib/CodeGen/TargetPassConfig.cpp =================================================================== --- llvm/lib/CodeGen/TargetPassConfig.cpp +++ llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1123,6 +1123,8 @@ // Run post-ra passes. addPostRegAlloc(); + addPass(&RemoveRedundantDebugValuesID, false); + addPass(&FixupStatepointCallerSavedID); // Insert prolog/epilog code. Eliminate abstract frame index references... Index: llvm/test/CodeGen/AArch64/O0-pipeline.ll =================================================================== --- llvm/test/CodeGen/AArch64/O0-pipeline.ll +++ llvm/test/CodeGen/AArch64/O0-pipeline.ll @@ -46,6 +46,7 @@ ; CHECK-NEXT: Eliminate PHI nodes for register allocation ; CHECK-NEXT: Two-Address instruction pass ; CHECK-NEXT: Fast Register Allocator +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: Lazy Machine Block Frequency Analysis ; CHECK-NEXT: Machine Optimization Remark Emitter Index: llvm/test/CodeGen/AArch64/O3-pipeline.ll =================================================================== --- llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -159,6 +159,7 @@ ; CHECK-NEXT: Machine Loop Invariant Code Motion ; CHECK-NEXT: AArch64 Redundant Copy Elimination ; CHECK-NEXT: A57 FP Anti-dependency breaker +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: MachineDominator Tree Construction Index: llvm/test/CodeGen/AMDGPU/llc-pipeline.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/llc-pipeline.ll +++ llvm/test/CodeGen/AMDGPU/llc-pipeline.ll @@ -135,6 +135,7 @@ ; GCN-O0-NEXT: Fast Register Allocator ; GCN-O0-NEXT: SI Fix VGPR copies ; GCN-O0-NEXT: SI lower SGPR spill instructions +; GCN-O0-NEXT: Remove Redundant DEBUG_VALUE analysis ; GCN-O0-NEXT: Fixup Statepoint Caller Saved ; GCN-O0-NEXT: Lazy Machine Block Frequency Analysis ; GCN-O0-NEXT: Machine Optimization Remark Emitter @@ -365,6 +366,7 @@ ; GCN-O1-NEXT: SI Fix VGPR copies ; GCN-O1-NEXT: SI optimize exec mask operations ; GCN-O1-NEXT: SI lower SGPR spill instructions +; GCN-O1-NEXT: Remove Redundant DEBUG_VALUE analysis ; GCN-O1-NEXT: Fixup Statepoint Caller Saved ; GCN-O1-NEXT: PostRA Machine Sink ; GCN-O1-NEXT: MachineDominator Tree Construction @@ -645,6 +647,7 @@ ; GCN-O1-OPTS-NEXT: SI Fix VGPR copies ; GCN-O1-OPTS-NEXT: SI optimize exec mask operations ; GCN-O1-OPTS-NEXT: SI lower SGPR spill instructions +; GCN-O1-OPTS-NEXT: Remove Redundant DEBUG_VALUE analysis ; GCN-O1-OPTS-NEXT: Fixup Statepoint Caller Saved ; GCN-O1-OPTS-NEXT: PostRA Machine Sink ; GCN-O1-OPTS-NEXT: MachineDominator Tree Construction @@ -926,6 +929,7 @@ ; GCN-O2-NEXT: SI Fix VGPR copies ; GCN-O2-NEXT: SI optimize exec mask operations ; GCN-O2-NEXT: SI lower SGPR spill instructions +; GCN-O2-NEXT: Remove Redundant DEBUG_VALUE analysis ; GCN-O2-NEXT: Fixup Statepoint Caller Saved ; GCN-O2-NEXT: PostRA Machine Sink ; GCN-O2-NEXT: MachineDominator Tree Construction @@ -1220,6 +1224,7 @@ ; GCN-O3-NEXT: SI Fix VGPR copies ; GCN-O3-NEXT: SI optimize exec mask operations ; GCN-O3-NEXT: SI lower SGPR spill instructions +; GCN-O3-NEXT: Remove Redundant DEBUG_VALUE analysis ; GCN-O3-NEXT: Fixup Statepoint Caller Saved ; GCN-O3-NEXT: PostRA Machine Sink ; GCN-O3-NEXT: MachineDominator Tree Construction Index: llvm/test/CodeGen/AMDGPU/ptr-arg-dbg-value.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/ptr-arg-dbg-value.ll +++ llvm/test/CodeGen/AMDGPU/ptr-arg-dbg-value.ll @@ -43,7 +43,8 @@ ; CHECK-NEXT: .loc 1 10 0 ; example.cpp:10:0 ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: ; %bb.0: -; CHECK-NEXT: ;DEBUG_VALUE: ptr_arg_split_reg_mem:b <- [$vgpr31+0] +;; NOTE: One dbg_value (DEBUG_VALUE: ptr_arg_split_reg_mem:b <- [$vgpr31+0]) will be considered as +;; redundant after the virtregrewrite, so it will be removed. ; CHECK-NEXT: ;DEBUG_VALUE: ptr_arg_split_reg_mem:b <- [$vgpr31+0] ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: buffer_load_dword v32, off, s[0:3], s32 Index: llvm/test/CodeGen/ARM/O3-pipeline.ll =================================================================== --- llvm/test/CodeGen/ARM/O3-pipeline.ll +++ llvm/test/CodeGen/ARM/O3-pipeline.ll @@ -128,6 +128,7 @@ ; CHECK-NEXT: Stack Slot Coloring ; CHECK-NEXT: Machine Copy Propagation Pass ; CHECK-NEXT: Machine Loop Invariant Code Motion +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: Machine Block Frequency Analysis Index: llvm/test/CodeGen/PowerPC/O3-pipeline.ll =================================================================== --- llvm/test/CodeGen/PowerPC/O3-pipeline.ll +++ llvm/test/CodeGen/PowerPC/O3-pipeline.ll @@ -162,6 +162,7 @@ ; CHECK-NEXT: Stack Slot Coloring ; CHECK-NEXT: Machine Copy Propagation Pass ; CHECK-NEXT: Machine Loop Invariant Code Motion +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: Machine Block Frequency Analysis Index: llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll =================================================================== --- llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll +++ llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll @@ -5,7 +5,6 @@ ; CHECK-LABEL: test: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: #DEBUG_VALUE: test:Fptr <- $x3 -; CHECK-NEXT: #DEBUG_VALUE: test:Fptr <- $x3 ; CHECK-NEXT: #DEBUG_VALUE: test:Vptr <- $x4 ; CHECK-NEXT: addis 5, 2, .LCPI0_0@toc@ha ; CHECK-NEXT: .Ltmp0: Index: llvm/test/CodeGen/X86/O0-pipeline.ll =================================================================== --- llvm/test/CodeGen/X86/O0-pipeline.ll +++ llvm/test/CodeGen/X86/O0-pipeline.ll @@ -49,6 +49,7 @@ ; CHECK-NEXT: X86 Lower Tile Copy ; CHECK-NEXT: Bundle Machine CFG Edges ; CHECK-NEXT: X86 FP Stackifier +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: Lazy Machine Block Frequency Analysis ; CHECK-NEXT: Machine Optimization Remark Emitter Index: llvm/test/CodeGen/X86/opt-pipeline.ll =================================================================== --- llvm/test/CodeGen/X86/opt-pipeline.ll +++ llvm/test/CodeGen/X86/opt-pipeline.ll @@ -152,6 +152,7 @@ ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Machine Dominance Frontier Construction ; CHECK-NEXT: X86 Load Value Injection (LVI) Load Hardening +; CHECK-NEXT: Remove Redundant DEBUG_VALUE analysis ; CHECK-NEXT: Fixup Statepoint Caller Saved ; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: Machine Block Frequency Analysis Index: llvm/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir =================================================================== --- llvm/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir +++ llvm/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir @@ -112,7 +112,6 @@ successors: %bb.1 liveins: $r0 - DBG_VALUE $r0, $noreg, !22, !DIExpression(), debug-location !23 DBG_VALUE $r0, $noreg, !22, !DIExpression(), debug-location !23 BUNDLE implicit-def dead $p0, implicit-def $pc, implicit killed $r0, implicit killed $r31, debug-location !24 { renamable $p0 = C2_cmpeqi killed renamable $r0, 0, debug-location !24 Index: llvm/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir +++ llvm/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir @@ -70,7 +70,6 @@ bb.0.entry: liveins: $edi - DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !18 DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !18 DBG_VALUE $esi, $noreg, !16, !DIExpression(), debug-location !18 DBG_VALUE $edx, $noreg, !17, !DIExpression(), debug-location !18 Index: llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir =================================================================== --- /dev/null +++ llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir @@ -0,0 +1,86 @@ +# RUN: llc %s -o - -run-pass=removeredundantdebugvalues | FileCheck %s + +## This checks that the RemoveRedundantDebugValues removes redundant +## DBG_VALUEs. + +# CHECK-LABEL: foo +# CHECK-LABEL: bb.0.entry: +# CHECK: DBG_VALUE $edi +# CHECK-NOT: DBG_VALUE $edi +# CHECK: frame-setup PUSH64r + +--- | + ; ModuleID = 'test.ll' + source_filename = "test.c" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-linux-gnu" + + @side_effect = external dso_local local_unnamed_addr global i32, align 4 + @value = external dso_local local_unnamed_addr global i32, align 4 + + ; Function Attrs: nounwind uwtable + define dso_local i32 @foo(i32 %param) local_unnamed_addr !dbg !8 { + entry: + call void @llvm.dbg.value(metadata i32 %param, metadata !13, metadata !DIExpression()), !dbg !14 + store i32 %param, i32* @side_effect, align 4, !dbg !15 + %0 = load i32, i32* @value, align 4, !dbg !20 + call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !DIExpression()), !dbg !14 + tail call void @bar(i32 %0), !dbg !21 + ret i32 0, !dbg !22 + } + + declare !dbg !23 dso_local void @bar(i32) local_unnamed_addr + + ; Function Attrs: nofree nosync nounwind readnone speculatable willreturn + declare void @llvm.dbg.value(metadata, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4, !5, !6} + !llvm.ident = !{!7} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) + !1 = !DIFile(filename: "test.c", directory: "/dir") + !2 = !{} + !3 = !{i32 7, !"Dwarf Version", i32 4} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = !{i32 1, !"wchar_size", i32 4} + !6 = !{i32 7, !"uwtable", i32 1} + !7 = !{!"clang version 13.0.0"} + !8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) + !9 = !DISubroutineType(types: !10) + !10 = !{!11, !11} + !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !12 = !{!13} + !13 = !DILocalVariable(name: "param", arg: 1, scope: !8, file: !1, line: 4, type: !11) + !14 = !DILocation(line: 0, scope: !8) + !15 = !DILocation(line: 5, column: 17, scope: !8) + !20 = !DILocation(line: 6, column: 13, scope: !8) + !21 = !DILocation(line: 7, column: 5, scope: !8) + !22 = !DILocation(line: 8, column: 5, scope: !8) + !23 = !DISubprogram(name: "bar", scope: !1, file: !1, line: 1, type: !24, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) + !24 = !DISubroutineType(types: !25) + !25 = !{null, !11} + +... +--- +name: foo +alignment: 16 +liveins: + - { reg: '$edi', virtual-reg: '' } +body: | + bb.0.entry: + liveins: $edi, $esi + + DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !14 + DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !14 + frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION def_cfa_offset 16 + MOV32mr $rip, 1, $noreg, @side_effect, $noreg, killed renamable $esi, debug-location !15 :: (store 4 into @side_effect) + DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !14 + CALL64pcrel32 @bar, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, debug-location !21 + $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !22 + $rcx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !22 + CFI_INSTRUCTION def_cfa_offset 8, debug-location !22 + RETQ killed $eax, debug-location !22 + +... Index: llvm/test/DebugInfo/NVPTX/debug-loc-offset.ll =================================================================== --- llvm/test/DebugInfo/NVPTX/debug-loc-offset.ll +++ llvm/test/DebugInfo/NVPTX/debug-loc-offset.ll @@ -15,7 +15,6 @@ ; CHECK: Lfunc_begin0: ; CHECK: .loc [[CU1]] 1 0 -; CHECK: //DEBUG_VALUE: bar:b <- {{[0-9]+}} ; CHECK: //DEBUG_VALUE: bar:b <- {{[0-9]+}} ; CHECK: .loc [[CU1]] 2 0 ; CHECK: ret; @@ -234,6 +233,21 @@ ; CHECK-NEXT: .b8 0 // EOM(1) ; CHECK-NEXT: .b8 0 // EOM(2) ; CHECK-NEXT: .b8 7 // Abbreviation Code +; CHECK-NEXT: .b8 5 // DW_TAG_formal_parameter +; CHECK-NEXT: .b8 0 // DW_CHILDREN_no +; CHECK-NEXT: .b8 28 // DW_AT_const_value +; CHECK-NEXT: .b8 13 // DW_FORM_sdata +; CHECK-NEXT: .b8 3 // DW_AT_name +; CHECK-NEXT: .b8 8 // DW_FORM_string +; CHECK-NEXT: .b8 58 // DW_AT_decl_file +; CHECK-NEXT: .b8 11 // DW_FORM_data1 +; CHECK-NEXT: .b8 59 // DW_AT_decl_line +; CHECK-NEXT: .b8 11 // DW_FORM_data1 +; CHECK-NEXT: .b8 73 // DW_AT_type +; CHECK-NEXT: .b8 19 // DW_FORM_ref4 +; CHECK-NEXT: .b8 0 // EOM(1) +; CHECK-NEXT: .b8 0 // EOM(2) +; CHECK-NEXT: .b8 8 // Abbreviation Code ; CHECK-NEXT: .b8 36 // DW_TAG_base_type ; CHECK-NEXT: .b8 0 // DW_CHILDREN_no ; CHECK-NEXT: .b8 3 // DW_AT_name @@ -361,15 +375,15 @@ ; CHECK-NEXT: .b8 0 ; CHECK-NEXT: .b8 2 // DW_AT_decl_file ; CHECK-NEXT: .b8 7 // DW_AT_decl_line -; CHECK-NEXT: .b64 .debug_info+311 // DW_AT_type +; CHECK-NEXT: .b64 .debug_info+312 // DW_AT_type ; CHECK-NEXT: .b8 0 // End Of Children Mark ; CHECK-NEXT: .b8 0 // End Of Children Mark -; CHECK-NEXT: .b32 152 // Length of Unit +; CHECK-NEXT: .b32 153 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 ; CHECK-NEXT: .b32 .debug_abbrev // Offset Into Abbrev. Section ; CHECK-NEXT: .b8 8 // Address Size (in bytes) -; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0x91 DW_TAG_compile_unit +; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0x92 DW_TAG_compile_unit ; CHECK-NEXT: .b8 99 // DW_AT_producer ; CHECK-NEXT: .b8 108 ; CHECK-NEXT: .b8 97 @@ -441,7 +455,7 @@ ; CHECK-NEXT: .b8 0 ; CHECK-NEXT: .b64 Lfunc_begin0 // DW_AT_low_pc ; CHECK-NEXT: .b64 Lfunc_end0 // DW_AT_high_pc -; CHECK-NEXT: .b8 6 // Abbrev [6] 0x64:0x30 DW_TAG_subprogram +; CHECK-NEXT: .b8 6 // Abbrev [6] 0x64:0x31 DW_TAG_subprogram ; CHECK-NEXT: .b64 Lfunc_begin0 // DW_AT_low_pc ; CHECK-NEXT: .b64 Lfunc_end0 // DW_AT_high_pc ; CHECK-NEXT: .b8 1 // DW_AT_frame_base @@ -460,16 +474,17 @@ ; CHECK-NEXT: .b8 0 ; CHECK-NEXT: .b8 1 // DW_AT_decl_file ; CHECK-NEXT: .b8 1 // DW_AT_decl_line -; CHECK-NEXT: .b32 148 // DW_AT_type +; CHECK-NEXT: .b32 149 // DW_AT_type ; CHECK-NEXT: .b8 1 // DW_AT_external -; CHECK-NEXT: .b8 4 // Abbrev [4] 0x8a:0x9 DW_TAG_formal_parameter +; CHECK-NEXT: .b8 7 // Abbrev [7] 0x8a:0xa DW_TAG_formal_parameter +; CHECK-NEXT: .b8 1 // DW_AT_const_value ; CHECK-NEXT: .b8 98 // DW_AT_name ; CHECK-NEXT: .b8 0 ; CHECK-NEXT: .b8 1 // DW_AT_decl_file ; CHECK-NEXT: .b8 1 // DW_AT_decl_line -; CHECK-NEXT: .b32 148 // DW_AT_type +; CHECK-NEXT: .b32 149 // DW_AT_type ; CHECK-NEXT: .b8 0 // End Of Children Mark -; CHECK-NEXT: .b8 7 // Abbrev [7] 0x94:0x7 DW_TAG_base_type +; CHECK-NEXT: .b8 8 // Abbrev [8] 0x95:0x7 DW_TAG_base_type ; CHECK-NEXT: .b8 105 // DW_AT_name ; CHECK-NEXT: .b8 110 ; CHECK-NEXT: .b8 116 Index: llvm/test/DebugInfo/X86/livedebugvars-avoid-duplicates.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/livedebugvars-avoid-duplicates.ll @@ -0,0 +1,59 @@ +;; Check that after virtregrewrite MIR does not contain +;; redundant DBG_VALUEs. + +; RUN: llc -O2 %s -stop-before=livedebugvalues -o - | FileCheck %s + +; CHECK: DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !14 +; CHECK-NEXT: frame-setup +; CHECK: DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !14 + +; ModuleID = 'test.c' +source_filename = "test.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@side_effect = external dso_local local_unnamed_addr global i32, align 4 +@value = external dso_local local_unnamed_addr global i32, align 4 + +; Function Attrs: nounwind uwtable +define dso_local i32 @foo(i32 %param) local_unnamed_addr !dbg !8 { +entry: + call void @llvm.dbg.value(metadata i32 %param, metadata !13, metadata !DIExpression()), !dbg !14 + store i32 %param, i32* @side_effect, align 4, !dbg !15 + %0 = load i32, i32* @value, align 4, !dbg !20 + call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !DIExpression()), !dbg !14 + tail call void @bar(i32 %0), !dbg !21 + ret i32 0, !dbg !22 +} + +declare !dbg !23 dso_local void @bar(i32) local_unnamed_addr + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn mustprogress +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/dir") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{!"clang version 13.0.0"} +!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!9 = !DISubroutineType(types: !10) +!10 = !{!11, !11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !{!13} +!13 = !DILocalVariable(name: "param", arg: 1, scope: !8, file: !1, line: 4, type: !11) +!14 = !DILocation(line: 0, scope: !8) +!15 = !DILocation(line: 5, column: 17, scope: !8) +!20 = !DILocation(line: 6, column: 13, scope: !8) +!21 = !DILocation(line: 7, column: 5, scope: !8) +!22 = !DILocation(line: 8, column: 5, scope: !8) +!23 = !DISubprogram(name: "bar", scope: !1, file: !1, line: 1, type: !24, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!24 = !DISubroutineType(types: !25) +!25 = !{null, !11} Index: llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn +++ llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn @@ -170,6 +170,7 @@ "RegisterPressure.cpp", "RegisterScavenging.cpp", "RegisterUsageInfo.cpp", + "RemoveRedundantDebugValues.cpp", "RenameIndependentSubregs.cpp", "ReplaceWithVeclib.cpp", "ResetMachineFunctionPass.cpp",