[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