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:
parent
57b2fbab2e
commit
140c795b75
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user