Skip to content

Commit ce1b243

Browse files
authored
[DebugInfo][RemoveDIs] Instrument loop-deletion for DPValues (#73042)
Loop deletion identifies dbg.value intrinsics in the loop, sets them to undef/poison, and sinks them to the exit of the loop, to ensure that any variable assignments that happen in a deleted loop are "optimised out". This needs to be replicated for DPValues, the non-instruction replacement for dbg.value intrinsics. The movement API for DPValues is (deliberately) more limited than dbg.values, which is tricky because inserting the collection of dbg.values at an arbitrary iterator can insert a dbg.value in the middle of a sequence of dbg.values. A big no-no for DPValues. This patch replicates the order by inserting DPValues in reverse at the head-iterator of the block, to ensure the same output as dbg.value mode. Technically the order isn't important, but we're trying to ensure identical outputs from optimisation passes right now. Add more CHECK lines for dbg.values in diundef.ll to ensure that we don't create any spurious dbg.values, and to ensure that sequences of dbg.values come out of the optimisation in the correct order.
1 parent 6248c24 commit ce1b243

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

llvm/lib/Transforms/Utils/LoopUtils.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
604604
// Use a map to unique and a vector to guarantee deterministic ordering.
605605
llvm::SmallDenseSet<DebugVariable, 4> DeadDebugSet;
606606
llvm::SmallVector<DbgVariableIntrinsic *, 4> DeadDebugInst;
607+
llvm::SmallVector<DPValue *, 4> DeadDPValues;
607608

608609
if (ExitBlock) {
609610
// Given LCSSA form is satisfied, we should not have users of instructions
@@ -628,6 +629,24 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
628629
"Unexpected user in reachable block");
629630
U.set(Poison);
630631
}
632+
633+
// RemoveDIs: do the same as below for DPValues.
634+
if (Block->IsNewDbgInfoFormat) {
635+
for (DPValue &DPV :
636+
llvm::make_early_inc_range(I.getDbgValueRange())) {
637+
DebugVariable Key(DPV.getVariable(), DPV.getExpression(),
638+
DPV.getDebugLoc().get());
639+
if (!DeadDebugSet.insert(Key).second)
640+
continue;
641+
// Unlinks the DPV from it's container, for later insertion.
642+
DPV.removeFromParent();
643+
DeadDPValues.push_back(&DPV);
644+
}
645+
}
646+
647+
// For one of each variable encountered, preserve a debug intrinsic (set
648+
// to Poison) and transfer it to the loop exit. This terminates any
649+
// variable locations that were set during the loop.
631650
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I);
632651
if (!DVI)
633652
continue;
@@ -642,12 +661,22 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
642661
// be be replaced with undef. Loop invariant values will still be available.
643662
// Move dbg.values out the loop so that earlier location ranges are still
644663
// terminated and loop invariant assignments are preserved.
645-
Instruction *InsertDbgValueBefore = ExitBlock->getFirstNonPHI();
646-
assert(InsertDbgValueBefore &&
664+
DIBuilder DIB(*ExitBlock->getModule());
665+
BasicBlock::iterator InsertDbgValueBefore =
666+
ExitBlock->getFirstInsertionPt();
667+
assert(InsertDbgValueBefore != ExitBlock->end() &&
647668
"There should be a non-PHI instruction in exit block, else these "
648669
"instructions will have no parent.");
670+
649671
for (auto *DVI : DeadDebugInst)
650-
DVI->moveBefore(InsertDbgValueBefore);
672+
DVI->moveBefore(*ExitBlock, InsertDbgValueBefore);
673+
674+
// Due to the "head" bit in BasicBlock::iterator, we're going to insert
675+
// each DPValue right at the start of the block, wheras dbg.values would be
676+
// repeatedly inserted before the first instruction. To replicate this
677+
// behaviour, do it backwards.
678+
for (DPValue *DPV : llvm::reverse(DeadDPValues))
679+
ExitBlock->insertDPValueBefore(DPV, InsertDbgValueBefore);
651680
}
652681

653682
// Remove the block from the reference counting scheme, so that we can

llvm/test/Transforms/LoopDeletion/crashbc.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; Make sure we don't crash when writing bitcode.
22
; RUN: opt < %s -passes=loop-deletion -o /dev/null
3+
; RUN: opt < %s -passes=loop-deletion -o /dev/null --try-experimental-debuginfo-iterators
34

45
define void @f() {
56
br label %bb1

llvm/test/Transforms/LoopDeletion/diundef.ll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
; RUN: opt %s -passes=loop-deletion -S | FileCheck %s
1+
; RUN: opt %s -passes=loop-deletion -S | FileCheck %s --implicit-check-not=dbg.value
2+
; RUN: opt %s -passes=loop-deletion -S --try-experimental-debuginfo-iterators | FileCheck %s --implicit-check-not=dbg.value
23

34
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
45
target triple = "x86_64-apple-macosx10.14.0"
56

67
@a = common local_unnamed_addr global i32 0, align 4, !dbg !0
78

89
define i32 @b() local_unnamed_addr !dbg !12 {
10+
; CHECK-LABEL: entry
11+
; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[IVAR:[0-9]+]],
12+
; CHECK-LABEL: for.end:
13+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 undef, metadata ![[IVAR]], metadata !DIExpression()), !dbg !17
14+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 undef, metadata ![[JVAR:[0-9]+]], metadata !DIExpression()), !dbg !17
15+
; CHECK-NEXT: %call = tail call i32 {{.*}} @patatino()
916
entry:
1017
call void @llvm.dbg.value(metadata i32 0, metadata !16, metadata !DIExpression()), !dbg !17
1118
br label %for.cond, !dbg !18
@@ -15,11 +22,10 @@ for.cond: ; preds = %for.cond, %entry
1522
call void @llvm.dbg.value(metadata i32 %i.0, metadata !16, metadata !DIExpression()), !dbg !17
1623
%inc = add nuw nsw i32 %i.0, 1, !dbg !21
1724
call void @llvm.dbg.value(metadata i32 %inc, metadata !16, metadata !DIExpression()), !dbg !17
25+
call void @llvm.dbg.value(metadata i32 %inc, metadata !37, metadata !DIExpression()), !dbg !17
1826
%exitcond = icmp ne i32 %inc, 3, !dbg !23
1927
br i1 %exitcond, label %for.cond, label %for.end, !dbg !24, !llvm.loop !25
2028

21-
; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata !16, metadata !DIExpression()), !dbg !17
22-
; CHECK-NEXT: %call = tail call i32 {{.*}} @patatino()
2329
for.end: ; preds = %for.cond
2430
%call = tail call i32 (...) @patatino() #3, !dbg !27
2531
%0 = load i32, ptr @a, align 4, !dbg !28
@@ -34,6 +40,11 @@ entry:
3440
ret i32 0, !dbg !36
3541
}
3642

43+
; CHECK: declare void @llvm.dbg.value(metadata,
44+
45+
; CHECK: ![[IVAR]] = !DILocalVariable(name: "i",
46+
; CHECK: ![[JVAR]] = !DILocalVariable(name: "j",
47+
3748
declare void @llvm.dbg.value(metadata, metadata, metadata)
3849

3950
!llvm.dbg.cu = !{!2}
@@ -73,3 +84,4 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
7384
!34 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !13, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
7485
!35 = !DILocation(line: 9, column: 14, scope: !34)
7586
!36 = !DILocation(line: 9, column: 19, scope: !34)
87+
!37 = !DILocalVariable(name: "j", scope: !12, file: !3, line: 3, type: !6)

llvm/test/Transforms/LoopDeletion/over-defensive-undefing-dbg-values.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt -S %s -passes=loop-deletion | FileCheck %s
2+
; RUN: opt -S %s -passes=loop-deletion --try-experimental-debuginfo-iterators | FileCheck %s
23

34
;; static int foo(int Param) __attribute__((always_inline));
45
;; static int foo(int Param) { return Param * Param * 2; }

0 commit comments

Comments
 (0)