[llvm] [DebugInfo][RemoveDIs] Instrument loop-deletion for DPValues (PR #73042)

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 23 04:21:21 PST 2023


https://github.com/jmorse updated https://github.com/llvm/llvm-project/pull/73042

>From 8470224c78ba92a197097a00c2166b3c6850acdb Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Wed, 7 Jun 2023 16:04:13 +0100
Subject: [PATCH 1/3] [DebugInfo][RemoveDIs] Instrument loop-deletion for
 DPValues

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 arbitary iterator can insert a dbg.value in the middle of a sequence
of dbg.values. 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.
---
 llvm/lib/Transforms/Utils/LoopUtils.cpp       | 34 +++++++++++++++++--
 llvm/test/Transforms/LoopDeletion/crashbc.ll  |  1 +
 llvm/test/Transforms/LoopDeletion/diundef.ll  | 18 ++++++++--
 .../over-defensive-undefing-dbg-values.ll     |  1 +
 4 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 8bb4e17b99dd629..bf1e37a97c2d542 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -604,6 +604,7 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
   // Use a map to unique and a vector to guarantee deterministic ordering.
   llvm::SmallDenseSet<DebugVariable, 4> DeadDebugSet;
   llvm::SmallVector<DbgVariableIntrinsic *, 4> DeadDebugInst;
+  llvm::SmallVector<DPValue *, 4> DeadDPValues;
 
   if (ExitBlock) {
     // 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,
                    "Unexpected user in reachable block");
           U.set(Poison);
         }
+
+        // RemoveDIs: do the same as below for DPValues.
+        if (Block->IsNewDbgInfoFormat) {
+          for (DPValue &DPV : llvm::make_early_inc_range(I.getDbgValueRange())) {
+            auto Key =
+                DeadDebugSet.find(DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
+            if (Key != DeadDebugSet.end())
+              continue;
+            // Unlinks the DPV from it's container, for later insertion.
+            DPV.removeFromParent();
+            DeadDebugSet.insert(DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
+            DeadDPValues.push_back(&DPV);
+          }
+        }
+
+        // For one of each variable encountered, preserve a debug intrinsic (set
+        // to Poison) and transfer it to the loop exit. This terminates any
+        // variable locations that were set during the loop.
         auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I);
         if (!DVI)
           continue;
@@ -642,12 +661,21 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
     // be be replaced with undef. Loop invariant values will still be available.
     // Move dbg.values out the loop so that earlier location ranges are still
     // terminated and loop invariant assignments are preserved.
-    Instruction *InsertDbgValueBefore = ExitBlock->getFirstNonPHI();
-    assert(InsertDbgValueBefore &&
+    DIBuilder DIB(*ExitBlock->getModule());
+    BasicBlock::iterator InsertDbgValueBefore = ExitBlock->getFirstInsertionPt();
+    assert(InsertDbgValueBefore != ExitBlock->end() &&
            "There should be a non-PHI instruction in exit block, else these "
            "instructions will have no parent.");
+
     for (auto *DVI : DeadDebugInst)
-      DVI->moveBefore(InsertDbgValueBefore);
+      DVI->moveBefore(*ExitBlock, InsertDbgValueBefore);
+
+    // Due to the "head" bit in BasicBlock::iterator, we're going to insert
+    // each DPValue right at the start of the block, wheras dbg.values would be
+    // repeatedly inserted before the first instruction. To replicate this
+    // behaviour, do it backwards.
+    for (DPValue *DPV : llvm::reverse(DeadDPValues))
+      ExitBlock->insertDPValueBefore(DPV, InsertDbgValueBefore);
   }
 
   // Remove the block from the reference counting scheme, so that we can
diff --git a/llvm/test/Transforms/LoopDeletion/crashbc.ll b/llvm/test/Transforms/LoopDeletion/crashbc.ll
index 2ba5e2ca902a194..c01453bbda81710 100644
--- a/llvm/test/Transforms/LoopDeletion/crashbc.ll
+++ b/llvm/test/Transforms/LoopDeletion/crashbc.ll
@@ -1,5 +1,6 @@
 ; Make sure we don't crash when writing bitcode.
 ; RUN: opt < %s -passes=loop-deletion -o /dev/null
+; RUN: opt < %s -passes=loop-deletion -o /dev/null --try-experimental-debuginfo-iterators
 
 define void @f() {
   br label %bb1
diff --git a/llvm/test/Transforms/LoopDeletion/diundef.ll b/llvm/test/Transforms/LoopDeletion/diundef.ll
index 14a6e401f9c6f15..7b6178bcc2ae3dd 100644
--- a/llvm/test/Transforms/LoopDeletion/diundef.ll
+++ b/llvm/test/Transforms/LoopDeletion/diundef.ll
@@ -1,4 +1,5 @@
-; RUN: opt %s -passes=loop-deletion -S | FileCheck %s
+; RUN: opt %s -passes=loop-deletion -S | FileCheck %s --implicit-check-not=dbg.value
+; RUN: opt %s -passes=loop-deletion -S --try-experimental-debuginfo-iterators | FileCheck %s --implicit-check-not=dbg.value
 
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-apple-macosx10.14.0"
@@ -6,6 +7,12 @@ target triple = "x86_64-apple-macosx10.14.0"
 @a = common local_unnamed_addr global i32 0, align 4, !dbg !0
 
 define i32 @b() local_unnamed_addr !dbg !12 {
+; CHECK-LABEL: entry
+; CHECK:       call void @llvm.dbg.value(metadata i32 0, metadata ![[IVAR:[0-9]+]],
+; CHECK-LABEL: for.end:
+; CHECK-NEXT:  call void @llvm.dbg.value(metadata i32 undef, metadata ![[IVAR]], metadata !DIExpression()), !dbg !17
+; CHECK-NEXT:  call void @llvm.dbg.value(metadata i32 undef, metadata ![[JVAR:[0-9]+]], metadata !DIExpression()), !dbg !17
+; CHECK-NEXT:  %call = tail call i32 {{.*}} @patatino()
 entry:
   call void @llvm.dbg.value(metadata i32 0, metadata !16, metadata !DIExpression()), !dbg !17
   br label %for.cond, !dbg !18
@@ -15,11 +22,10 @@ for.cond:                                         ; preds = %for.cond, %entry
   call void @llvm.dbg.value(metadata i32 %i.0, metadata !16, metadata !DIExpression()), !dbg !17
   %inc = add nuw nsw i32 %i.0, 1, !dbg !21
   call void @llvm.dbg.value(metadata i32 %inc, metadata !16, metadata !DIExpression()), !dbg !17
+  call void @llvm.dbg.value(metadata i32 %inc, metadata !37, metadata !DIExpression()), !dbg !17
   %exitcond = icmp ne i32 %inc, 3, !dbg !23
   br i1 %exitcond, label %for.cond, label %for.end, !dbg !24, !llvm.loop !25
 
-; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata !16, metadata !DIExpression()), !dbg !17
-; CHECK-NEXT: %call = tail call i32 {{.*}} @patatino()
 for.end:                                          ; preds = %for.cond
   %call = tail call i32 (...) @patatino() #3, !dbg !27
   %0 = load i32, ptr @a, align 4, !dbg !28
@@ -34,6 +40,11 @@ entry:
   ret i32 0, !dbg !36
 }
 
+; CHECK: declare void @llvm.dbg.value(metadata,
+
+; CHECK: ![[IVAR]] = !DILocalVariable(name: "i",
+; CHECK: ![[JVAR]] = !DILocalVariable(name: "j",
+
 declare void @llvm.dbg.value(metadata, metadata, metadata)
 
 !llvm.dbg.cu = !{!2}
@@ -73,3 +84,4 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 !34 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !13, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
 !35 = !DILocation(line: 9, column: 14, scope: !34)
 !36 = !DILocation(line: 9, column: 19, scope: !34)
+!37 = !DILocalVariable(name: "j", scope: !12, file: !3, line: 3, type: !6)
diff --git a/llvm/test/Transforms/LoopDeletion/over-defensive-undefing-dbg-values.ll b/llvm/test/Transforms/LoopDeletion/over-defensive-undefing-dbg-values.ll
index 8eb1ef8ddd72a0a..6f71038a74672c4 100644
--- a/llvm/test/Transforms/LoopDeletion/over-defensive-undefing-dbg-values.ll
+++ b/llvm/test/Transforms/LoopDeletion/over-defensive-undefing-dbg-values.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S %s -passes=loop-deletion | FileCheck %s
+; RUN: opt -S %s -passes=loop-deletion --try-experimental-debuginfo-iterators | FileCheck %s
 
 ;; static int foo(int Param) __attribute__((always_inline));
 ;; static int foo(int Param) { return Param * Param * 2; }

>From b40da9f15c608d245b9d753fb33a4fd7adbdfc58 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Thu, 23 Nov 2023 12:01:00 +0000
Subject: [PATCH 2/3] clang-format

---
 llvm/lib/Transforms/Utils/LoopUtils.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index bf1e37a97c2d542..2d0e9f6f41a163e 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -632,14 +632,16 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
 
         // RemoveDIs: do the same as below for DPValues.
         if (Block->IsNewDbgInfoFormat) {
-          for (DPValue &DPV : llvm::make_early_inc_range(I.getDbgValueRange())) {
-            auto Key =
-                DeadDebugSet.find(DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
+          for (DPValue &DPV :
+               llvm::make_early_inc_range(I.getDbgValueRange())) {
+            auto Key = DeadDebugSet.find(
+                DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
             if (Key != DeadDebugSet.end())
               continue;
             // Unlinks the DPV from it's container, for later insertion.
             DPV.removeFromParent();
-            DeadDebugSet.insert(DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
+            DeadDebugSet.insert(
+                DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
             DeadDPValues.push_back(&DPV);
           }
         }
@@ -662,7 +664,8 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
     // Move dbg.values out the loop so that earlier location ranges are still
     // terminated and loop invariant assignments are preserved.
     DIBuilder DIB(*ExitBlock->getModule());
-    BasicBlock::iterator InsertDbgValueBefore = ExitBlock->getFirstInsertionPt();
+    BasicBlock::iterator InsertDbgValueBefore =
+        ExitBlock->getFirstInsertionPt();
     assert(InsertDbgValueBefore != ExitBlock->end() &&
            "There should be a non-PHI instruction in exit block, else these "
            "instructions will have no parent.");

>From 6e255fb8a6f1bbb491f148ec4ebeecd47a9397f9 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Thu, 23 Nov 2023 12:20:41 +0000
Subject: [PATCH 3/3] Switch to insert-testing a container

---
 llvm/lib/Transforms/Utils/LoopUtils.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 2d0e9f6f41a163e..4fb64bdf9035912 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -634,14 +634,12 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
         if (Block->IsNewDbgInfoFormat) {
           for (DPValue &DPV :
                llvm::make_early_inc_range(I.getDbgValueRange())) {
-            auto Key = DeadDebugSet.find(
-                DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
-            if (Key != DeadDebugSet.end())
+            DebugVariable Key(DPV.getVariable(), DPV.getExpression(),
+                              DPV.getDebugLoc().get());
+            if (!DeadDebugSet.insert(Key).second)
               continue;
             // Unlinks the DPV from it's container, for later insertion.
             DPV.removeFromParent();
-            DeadDebugSet.insert(
-                DebugVariable(DPV.getVariable(), DPV.getExpression(), nullptr));
             DeadDPValues.push_back(&DPV);
           }
         }



More information about the llvm-commits mailing list