Index: llvm/lib/CodeGen/LiveDebugVariables.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugVariables.cpp +++ llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -1636,6 +1636,32 @@ return MBB->end(); } +// Avoid duplicates by scanning the machine basic block backward, up to the +// first non-debug instr or up to the MBBStart. +static bool shouldSkipThisDbgValue(MachineBasicBlock *MBB, MachineInstr &MI, + const DILocalVariable *Variable, + const MachineOperand &LocOp, + const DIExpression *Expr, DebugLoc &dl) { + MachineBasicBlock::reverse_iterator it = + std::next(MachineBasicBlock::reverse_iterator(MI)); + while (it != MBB->rend()) { + if (!it->isDebugValue()) + return false; + + MachineOperand &loc = it->getDebugOperand(0); + if (Variable == it->getDebugVariable() && loc.isReg() && LocOp.isReg() && + loc.getReg() == LocOp.getReg() && Expr == it->getDebugExpression() && + dl == it->getDebugLoc()) { + LLVM_DEBUG(llvm::dbgs() << "\navoiding duplicated "; it->dump();); + return true; + } + + it = std::next(it); + } + + return false; +} + void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, SlotIndex StopIdx, DbgVariableValue DbgValue, ArrayRef LocSpills, @@ -1648,6 +1674,15 @@ StopIdx = (MBBEndIdx < StopIdx) ? MBBEndIdx : StopIdx; MachineBasicBlock::iterator I = findInsertLocation(MBB, StartIdx, LIS, BBSkipInstsMap); + + // After virtual register rewriting, we can end up having multiple same + // contiguous DBG_VALUEs representing the same variable, so we are avoiding + // duplicates here. + if (locations.size() == 1 && I != MBB->end() && + shouldSkipThisDbgValue(MBB, *I, Variable, locations[0], + DbgValue.getExpression(), dl)) + return; + // Undef values don't exist in locations so create new "noreg" register MOs // for them. See getLocationNo(). SmallVector MOs; 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/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/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/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}