1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[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
This commit is contained in:
Djordje Todorovic 2021-07-14 23:45:19 -07:00 committed by Djordje Todorovic
parent 57b2fbab2e
commit 140c795b75
3 changed files with 245 additions and 4 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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