forked from OSchip/llvm-project
[DebugInfo] Correctly update debug users of SSA values in tail duplication
During tail duplication, SSA values may be updated and have their uses replaced with a virtual register, and any debug instructions that use that value are deleted. This patch fixes the implementation of the debug instruction deletion to work correctly for debug instructions that use the SSA value multiple times, by batching deletions so that we don't attempt to delete the same instruction twice. Differential Revision: https://reviews.llvm.org/D106557
This commit is contained in:
parent
240dde9482
commit
31e7551217
|
@ -216,6 +216,9 @@ bool TailDuplicator::tailDuplicateAndUpdate(
|
|||
|
||||
// Rewrite uses that are outside of the original def's block.
|
||||
MachineRegisterInfo::use_iterator UI = MRI->use_begin(VReg);
|
||||
// Only remove instructions after loop, as DBG_VALUE_LISTs with multiple
|
||||
// uses of VReg may invalidate the use iterator when erased.
|
||||
SmallPtrSet<MachineInstr *, 4> InstrsToRemove;
|
||||
while (UI != MRI->use_end()) {
|
||||
MachineOperand &UseMO = *UI;
|
||||
MachineInstr *UseMI = UseMO.getParent();
|
||||
|
@ -225,13 +228,15 @@ bool TailDuplicator::tailDuplicateAndUpdate(
|
|||
// a debug instruction that is a kill.
|
||||
// FIXME: Should it SSAUpdate job to delete debug instructions
|
||||
// instead of replacing the use with undef?
|
||||
UseMI->eraseFromParent();
|
||||
InstrsToRemove.insert(UseMI);
|
||||
continue;
|
||||
}
|
||||
if (UseMI->getParent() == DefBB && !UseMI->isPHI())
|
||||
continue;
|
||||
SSAUpdate.RewriteUse(UseMO);
|
||||
}
|
||||
for (auto *MI : InstrsToRemove)
|
||||
MI->eraseFromParent();
|
||||
}
|
||||
|
||||
SSAUpdateVRs.clear();
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
# RUN: llc -run-pass=early-tailduplication -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s
|
||||
|
||||
# Tail Duplication may update SSA values and invalidate any DBG_VALUEs that
|
||||
# use those values; those DBG_VALUEs should be deleted. This behaviour is tested
|
||||
# for DBG_VALUE users, and DBG_VALUE_LISTs that use the value multiple times.
|
||||
|
||||
# CHECK-NOT: DBG_VALUE
|
||||
--- |
|
||||
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"
|
||||
|
||||
define dso_local void @main() local_unnamed_addr #0 !dbg !15 {
|
||||
entry:
|
||||
br label %L.outer
|
||||
|
||||
L: ; preds = %L, %L.outer
|
||||
%tobool2.not = icmp eq i32 undef, 0
|
||||
br i1 %tobool2.not, label %if.end4, label %L
|
||||
|
||||
if.end4: ; preds = %L
|
||||
call void @llvm.dbg.value(metadata !DIArgList(i32 %f.0.ph, i32 1, i32 %f.0.ph), metadata !19, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_LLVM_arg, 2, DW_OP_and, DW_OP_or, DW_OP_stack_value)), !dbg !21
|
||||
%cmp = icmp slt i32 %f.0.ph, undef
|
||||
br i1 %cmp, label %if.then5, label %if.end6
|
||||
|
||||
if.then5: ; preds = %if.end4
|
||||
call void @h() #2
|
||||
br label %L.outer
|
||||
|
||||
L.outer: ; preds = %if.then5, %entry
|
||||
%f.0.ph = phi i32 [ 0, %if.then5 ], [ 1, %entry ]
|
||||
br label %L
|
||||
|
||||
if.end6: ; preds = %if.end4
|
||||
ret void
|
||||
}
|
||||
|
||||
declare dso_local void @h() local_unnamed_addr
|
||||
|
||||
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!13, !14}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "tail-dup-debugvalue.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{!4, !7, !9, !11}
|
||||
!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
|
||||
!5 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true)
|
||||
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
|
||||
!8 = distinct !DIGlobalVariable(name: "b", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true)
|
||||
!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
|
||||
!10 = distinct !DIGlobalVariable(name: "c", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true)
|
||||
!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())
|
||||
!12 = distinct !DIGlobalVariable(name: "d", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true)
|
||||
!13 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!14 = !{i32 7, !"uwtable", i32 1}
|
||||
!15 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !16, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !18)
|
||||
!16 = !DISubroutineType(types: !17)
|
||||
!17 = !{!6}
|
||||
!18 = !{!19, !20}
|
||||
!19 = !DILocalVariable(name: "j", scope: !15, file: !1, line: 14, type: !6)
|
||||
!20 = !DILocalVariable(name: "k", scope: !15, file: !1, line: 14, type: !6)
|
||||
!21 = !DILocation(line: 0, scope: !15)
|
||||
|
||||
...
|
||||
---
|
||||
name: main
|
||||
alignment: 16
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: gr32 }
|
||||
- { id: 1, class: gr32 }
|
||||
- { id: 2, class: gr32 }
|
||||
- { id: 3, class: gr8 }
|
||||
- { id: 4, class: gr32 }
|
||||
- { id: 5, class: gr32 }
|
||||
- { id: 6, class: gr32 }
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
hasCalls: true
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0.entry:
|
||||
successors: %bb.4(0x80000000)
|
||||
|
||||
%1:gr32 = MOV32ri 1
|
||||
JMP_1 %bb.4
|
||||
|
||||
bb.1.L:
|
||||
successors: %bb.2(0x04000000), %bb.1(0x7c000000)
|
||||
|
||||
%2:gr32 = MOV32r0 implicit-def dead $eflags
|
||||
%3:gr8 = COPY %2.sub_8bit
|
||||
TEST8rr %3, %3, implicit-def $eflags
|
||||
JCC_1 %bb.1, 5, implicit $eflags
|
||||
JMP_1 %bb.2
|
||||
|
||||
bb.2.if.end4:
|
||||
successors: %bb.3(0x783e0f0f), %bb.5(0x07c1f0f1)
|
||||
|
||||
DBG_VALUE_LIST !19, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_LLVM_arg, 2, DW_OP_and, DW_OP_or, DW_OP_stack_value), %0, 1, %0, debug-location !21
|
||||
DBG_VALUE %0, $noreg, !20, !DIExpression(), debug-location !21
|
||||
%5:gr32 = IMPLICIT_DEF
|
||||
%4:gr32 = SUB32rr %0, killed %5, implicit-def $eflags
|
||||
JCC_1 %bb.5, 13, implicit $eflags
|
||||
JMP_1 %bb.3
|
||||
|
||||
bb.3.if.then5:
|
||||
successors: %bb.4(0x80000000)
|
||||
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
||||
CALL64pcrel32 @h, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
||||
%6:gr32 = MOV32r0 implicit-def dead $eflags
|
||||
|
||||
bb.4.L.outer:
|
||||
successors: %bb.1(0x80000000)
|
||||
|
||||
%0:gr32 = PHI %1, %bb.0, %6, %bb.3
|
||||
JMP_1 %bb.1
|
||||
|
||||
bb.5.if.end6:
|
||||
RET 0
|
||||
|
||||
...
|
Loading…
Reference in New Issue