[llvm] fa2daae - [2/2][RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
Djordje Todorovic via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 15 00:09:04 PDT 2021
Author: Djordje Todorovic
Date: 2021-07-15T00:08:31-07:00
New Revision: fa2daaeff82e3eb26fe7008715024f5bc11f7f1a
URL: https://github.com/llvm/llvm-project/commit/fa2daaeff82e3eb26fe7008715024f5bc11f7f1a
DIFF: https://github.com/llvm/llvm-project/commit/fa2daaeff82e3eb26fe7008715024f5bc11f7f1a.diff
LOG: [2/2][RemoveRedundantDebugValues] Add a Pass that removes redundant DBG_VALUEs
This patch adds the forward scan for finding redundant DBG_VALUEs.
This analysis aims to remove redundant DBG_VALUEs by going forward
in the basic block by considering the first DBG_VALUE as a valid
until its first (location) operand is not clobbered/modified.
For example:
(1) DBG_VALUE $edi, !"var1", ...
(2) <block of code that does affect $edi>
(3) DBG_VALUE $edi, !"var1", ...
...
in this case, we can remove (3).
Differential Revision: https://reviews.llvm.org/D105280
Added:
Modified:
llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll
llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
index fe71a5fb33de..de6129a912d3 100644
--- a/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
+++ b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
@@ -6,12 +6,15 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/DenseMap.h"
#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/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
@@ -27,6 +30,7 @@
using namespace llvm;
STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)");
+STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)");
namespace {
@@ -66,6 +70,81 @@ RemoveRedundantDebugValues::RemoveRedundantDebugValues()
initializeRemoveRedundantDebugValuesPass(*PassRegistry::getPassRegistry());
}
+// This analysis aims to remove redundant DBG_VALUEs by going forward
+// in the basic block by considering the first DBG_VALUE as a valid
+// until its first (location) operand is not clobbered/modified.
+// For example:
+// (1) DBG_VALUE $edi, !"var1", ...
+// (2) <block of code that does affect $edi>
+// (3) DBG_VALUE $edi, !"var1", ...
+// ...
+// in this case, we can remove (3).
+// TODO: Support DBG_VALUE_LIST and other debug instructions.
+static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) {
+ LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n");
+
+ SmallVector<MachineInstr *, 8> DbgValsToBeRemoved;
+ DenseMap<DebugVariable, std::pair<MachineOperand *, const DIExpression *>>
+ VariableMap;
+ const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
+
+ for (auto &MI : MBB) {
+ if (MI.isDebugValue()) {
+ DebugVariable Var(MI.getDebugVariable(), NoneType(),
+ MI.getDebugLoc()->getInlinedAt());
+ auto VMI = VariableMap.find(Var);
+ // Just stop tracking this variable, until we cover DBG_VALUE_LIST.
+ // 1 DBG_VALUE $rax, "x", DIExpression()
+ // ...
+ // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx
+ // ...
+ // 3 DBG_VALUE $rax, "x", DIExpression()
+ if (MI.isDebugValueList() && VMI != VariableMap.end()) {
+ VariableMap.erase(VMI);
+ continue;
+ }
+
+ MachineOperand &Loc = MI.getDebugOperand(0);
+ if (!Loc.isReg()) {
+ // If it it's not a register, just stop tracking such variable.
+ if (VMI != VariableMap.end())
+ VariableMap.erase(VMI);
+ continue;
+ }
+
+ // We have found a new value for a variable.
+ if (VMI == VariableMap.end() ||
+ VMI->second.first->getReg() != Loc.getReg() ||
+ VMI->second.second != MI.getDebugExpression()) {
+ VariableMap[Var] = {&Loc, MI.getDebugExpression()};
+ continue;
+ }
+
+ // Found an identical DBG_VALUE, so it can be considered
+ // for later removal.
+ DbgValsToBeRemoved.push_back(&MI);
+ }
+
+ if (MI.isMetaInstruction())
+ continue;
+
+ // Stop tracking any location that is clobbered by this instruction.
+ for (auto &Var : VariableMap) {
+ auto &LocOp = Var.second.first;
+ if (MI.modifiesRegister(LocOp->getReg(), TRI))
+ VariableMap.erase(Var.first);
+ }
+ }
+
+ for (auto &Instr : DbgValsToBeRemoved) {
+ LLVM_DEBUG(dbgs() << "removing "; Instr->dump());
+ Instr->eraseFromParent();
+ ++NumRemovedForward;
+ }
+
+ return !DbgValsToBeRemoved.empty();
+}
+
// This analysis aims to remove redundant DBG_VALUEs by going backward
// in the basic block and removing all but the last DBG_VALUE for any
// given variable in a set of consecutive DBG_VALUE instructions.
@@ -129,8 +208,10 @@ bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) {
bool Changed = false;
- for (auto &MBB : MF)
+ for (auto &MBB : MF) {
Changed |= reduceDbgValsBackwardScan(MBB);
+ Changed |= reduceDbgValsForwardScan(MBB);
+ }
return Changed;
}
diff --git a/llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll b/llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll
index af9476a06638..f87b3f945d13 100644
--- a/llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll
+++ b/llvm/test/CodeGen/PowerPC/non-debug-mi-search-frspxsrsp.ll
@@ -29,7 +29,6 @@ define dso_local void @test(float* nocapture readonly %Fptr, <4 x float>* nocapt
; CHECK-NEXT: xvcvdpsp 34, 0
; CHECK-NEXT: xvcvdpsp 35, 1
; CHECK-NEXT: vmrgew 2, 2, 3
-; CHECK-NEXT: #DEBUG_VALUE: test:Vptr <- $x4
; CHECK-NEXT: .loc 1 3 9 is_stmt 0
; CHECK-NEXT: stvx 2, 0, 4
; CHECK-NEXT: .loc 1 4 1 is_stmt 1
diff --git a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
index 6f71bf33492a..fba3d9ee1504 100644
--- a/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
+++ b/llvm/test/DebugInfo/MIR/X86/remove-redundant-dbg-vals.mir
@@ -1,13 +1,17 @@
-# RUN: llc %s -o - -run-pass=removeredundantdebugvalues | FileCheck %s
+# RUN: llc %s -o - -run-pass=removeredundantdebugvalues | FileCheck --implicit-check-not=DBG_VALUE %s
## This checks that the RemoveRedundantDebugValues removes redundant
-## DBG_VALUEs.
+## DBG_VALUEs. The MIR was hand-written, and foo{[2-6]}() are just
+## copies of foo(), with an extra instruction that modifies the $edi register
+## and extra (artificial) DBG_VALUE and DBG_VALUE_LIST instructions.
# CHECK-LABEL: foo
# CHECK-LABEL: bb.0.entry:
# CHECK: DBG_VALUE $edi
# CHECK-NOT: DBG_VALUE $edi
# CHECK: frame-setup PUSH64r
+# CHECK: MOV32mr $rip, 1, $noreg
+# CHECK-NOT: DBG_VALUE $edi
# CHECK-LABEL: foo6
# CHECK-LABEL: bb.0.entry:
@@ -15,6 +19,30 @@
# CHECK: DBG_VALUE 1
# CHECK: frame-setup PUSH64r
+# CHECK-LABEL: foo2
+# CHECK-LABEL: bb.0.entry:
+# CHECK: DBG_VALUE $edi
+# CHECK: MOV32mr $rip, 1, $noreg
+# CHECK: DBG_VALUE $edi
+
+# CHECK-LABEL: foo3
+# CHECK-LABEL: bb.0.entry:
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+# CHECK: DBG_VALUE $esi, {{.*}}, !DIExpression()
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+
+# CHECK-LABEL: foo4
+# CHECK-LABEL: bb.0.entry:
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+# CHECK: DBG_VALUE_LIST !{{.*}}
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+
+# CHECK-LABEL: foo5
+# CHECK-LABEL: bb.0.entry:
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+# CHECK: DBG_VALUE 0, {{.*}}, !DIExpression()
+# CHECK: DBG_VALUE $edi, {{.*}}, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+
--- |
; ModuleID = 'test.ll'
source_filename = "test.c"
@@ -43,6 +71,42 @@
ret i32 0, !dbg !35
}
+ ; Function Attrs: nounwind uwtable
+ define dso_local i32 @foo2(i32 %param) local_unnamed_addr !dbg !26 {
+ entry:
+ store i32 %param, i32* @side_effect, align 4, !dbg !27
+ %0 = load i32, i32* @value, align 4, !dbg !27
+ tail call void @bar(i32 %0), !dbg !27
+ ret i32 0, !dbg !27
+ }
+
+ ; Function Attrs: nounwind uwtable
+ define dso_local i32 @foo3(i32 %param) local_unnamed_addr !dbg !28 {
+ entry:
+ store i32 %param, i32* @side_effect, align 4, !dbg !29
+ %0 = load i32, i32* @value, align 4, !dbg !29
+ tail call void @bar(i32 %0), !dbg !29
+ ret i32 0, !dbg !29
+ }
+
+ ; Function Attrs: nounwind uwtable
+ define dso_local i32 @foo4(i32 %param) local_unnamed_addr !dbg !30 {
+ entry:
+ store i32 %param, i32* @side_effect, align 4, !dbg !31
+ %0 = load i32, i32* @value, align 4, !dbg !31
+ tail call void @bar(i32 %0), !dbg !31
+ ret i32 0, !dbg !31
+ }
+
+ ; Function Attrs: nounwind uwtable
+ define dso_local i32 @foo5(i32 %param) local_unnamed_addr !dbg !32 {
+ entry:
+ store i32 %param, i32* @side_effect, align 4, !dbg !33
+ %0 = load i32, i32* @value, align 4, !dbg !33
+ tail call void @bar(i32 %0), !dbg !33
+ ret i32 0, !dbg !33
+ }
+
declare !dbg !23 dso_local void @bar(i32) local_unnamed_addr
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
@@ -74,6 +138,14 @@
!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}
+ !26 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !27 = !DILocation(line: 0, scope: !26)
+ !28 = distinct !DISubprogram(name: "foo3", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !29 = !DILocation(line: 0, scope: !28)
+ !30 = distinct !DISubprogram(name: "foo4", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !31 = !DILocation(line: 0, scope: !30)
+ !32 = distinct !DISubprogram(name: "foo5", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !33 = !DILocation(line: 0, scope: !32)
!34 = distinct !DISubprogram(name: "foo6", scope: !1, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
!35 = !DILocation(line: 0, scope: !34)
@@ -99,6 +171,95 @@ body: |
CFI_INSTRUCTION def_cfa_offset 8, debug-location !22
RETQ killed $eax, debug-location !22
+...
+---
+name: foo2
+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)
+ renamable $edi = MOV32rm $rip, 1, $noreg, @value, $noreg, debug-location !20 :: (dereferenceable load 4 from @value)
+ 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
+
+...
+---
+name: foo3
+alignment: 16
+liveins:
+ - { reg: '$edi', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $edi, $esi
+
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), 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)
+ renamable $esi = MOV32rm $rip, 1, $noreg, @value, $noreg, debug-location !20 :: (dereferenceable load 4 from @value)
+ DBG_VALUE $esi, $noreg, !13, !DIExpression(), debug-location !14
+ $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !22
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !14
+ $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
+
+...
+---
+name: foo4
+alignment: 16
+liveins:
+ - { reg: '$edi', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $edi, $esi
+
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), 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)
+ renamable $esi = MOV32rm $rip, 1, $noreg, @value, $noreg, debug-location !20 :: (dereferenceable load 4 from @value)
+ DBG_VALUE_LIST !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), $edi, $esi, debug-location !14
+ $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !22
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !14
+ $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
+
+...
+---
+name: foo5
+alignment: 16
+liveins:
+ - { reg: '$edi', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $edi, $esi
+
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), 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)
+ renamable $esi = MOV32rm $rip, 1, $noreg, @value, $noreg, debug-location !20 :: (dereferenceable load 4 from @value)
+ DBG_VALUE 0, $noreg, !13, !DIExpression(), debug-location !14
+ $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, debug-location !22
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !14
+ $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
+
...
---
name: foo6
More information about the llvm-commits
mailing list