[DebugInfo] Make debug intrinsics to track cloned values in JumpThreading
authorBen Mudd <Ben.Mudd@sony.com>
Mon, 23 Jan 2023 13:59:41 +0000 (13:59 +0000)
committerStephen Tozer <Stephen.Tozer@Sony.com>
Wed, 1 Feb 2023 12:52:37 +0000 (12:52 +0000)
This patch causes debug value intrinsics outside of cloned blocks in the
Jump Threading pass to correctly point towards any derived values. If it cannot,
it kills them.

Reviewed By: probinson, StephenTozer

Differential Revision: https://reviews.llvm.org/D140404

llvm/include/llvm/Transforms/Utils/SSAUpdater.h
llvm/lib/Transforms/Scalar/JumpThreading.cpp
llvm/lib/Transforms/Utils/SSAUpdater.cpp
llvm/test/Transforms/JumpThreading/thread-debug-info.ll

index c233e3d..36fbf53 100644 (file)
@@ -28,6 +28,7 @@ template <typename T> class SSAUpdaterTraits;
 class Type;
 class Use;
 class Value;
+class DbgValueInst;
 
 /// Helper class for SSA formation on a set of values defined in
 /// multiple blocks.
@@ -114,6 +115,15 @@ public:
   /// be below it.
   void RewriteUse(Use &U);
 
+  /// Rewrite debug value intrinsics to conform to a new SSA form.
+  ///
+  /// This will scout out all the debug value instrinsics associated with
+  /// the instruction. Anything outside of its block will have its
+  /// value set to the new SSA value if available, and undef if not.
+  void UpdateDebugValues(Instruction *I);
+  void UpdateDebugValues(Instruction *I,
+                         SmallVectorImpl<DbgValueInst *> &DbgValues);
+
   /// Rewrite a use like \c RewriteUse but handling in-block definitions.
   ///
   /// This version of the method can rewrite uses in the same block as
@@ -123,6 +133,7 @@ public:
 
 private:
   Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
+  void UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue);
 };
 
 /// Helper class for promoting a collection of loads and stores into SSA
index f41eaed..bd5d9ef 100644 (file)
@@ -40,6 +40,7 @@
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InstrTypes.h"
@@ -2038,6 +2039,7 @@ void JumpThreadingPass::updateSSA(
   // PHI insertion, of which we are prepared to do, clean these up now.
   SSAUpdater SSAUpdate;
   SmallVector<Use *, 16> UsesToRename;
+  SmallVector<DbgValueInst *, 4> DbgValues;
 
   for (Instruction &I : *BB) {
     // Scan all uses of this instruction to see if it is used outside of its
@@ -2053,8 +2055,16 @@ void JumpThreadingPass::updateSSA(
       UsesToRename.push_back(&U);
     }
 
+    // Find debug values outside of the block
+    findDbgValues(DbgValues, &I);
+    DbgValues.erase(remove_if(DbgValues,
+                              [&](const DbgValueInst *DbgVal) {
+                                return DbgVal->getParent() == BB;
+                              }),
+                    DbgValues.end());
+
     // If there are no uses outside the block, we're done with this instruction.
-    if (UsesToRename.empty())
+    if (UsesToRename.empty() && DbgValues.empty())
       continue;
     LLVM_DEBUG(dbgs() << "JT: Renaming non-local uses of: " << I << "\n");
 
@@ -2067,6 +2077,11 @@ void JumpThreadingPass::updateSSA(
 
     while (!UsesToRename.empty())
       SSAUpdate.RewriteUse(*UsesToRename.pop_back_val());
+    if (!DbgValues.empty()) {
+      SSAUpdate.UpdateDebugValues(&I, DbgValues);
+      DbgValues.clear();
+    }
+
     LLVM_DEBUG(dbgs() << "\n");
   }
 }
index 2520aa5..13975de 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -195,6 +196,33 @@ void SSAUpdater::RewriteUse(Use &U) {
   U.set(V);
 }
 
+void SSAUpdater::UpdateDebugValues(Instruction *I) {
+  SmallVector<DbgValueInst *, 4> DbgValues;
+  llvm::findDbgValues(DbgValues, I);
+  for (auto &DbgValue : DbgValues) {
+    if (DbgValue->getParent() == I->getParent())
+      continue;
+    UpdateDebugValue(I, DbgValue);
+  }
+}
+
+void SSAUpdater::UpdateDebugValues(Instruction *I,
+                                   SmallVectorImpl<DbgValueInst *> &DbgValues) {
+  for (auto &DbgValue : DbgValues) {
+    UpdateDebugValue(I, DbgValue);
+  }
+}
+
+void SSAUpdater::UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue) {
+  BasicBlock *UserBB = DbgValue->getParent();
+  if (HasValueForBlock(UserBB)) {
+    Value *NewVal = GetValueInMiddleOfBlock(UserBB);
+    DbgValue->replaceVariableLocationOp(I, NewVal);
+  }
+  else
+    DbgValue->setKillLocation();
+}
+
 void SSAUpdater::RewriteUseAfterInsertions(Use &U) {
   Instruction *User = cast<Instruction>(U.getUser());
 
index b85a8fb..0347829 100644 (file)
@@ -3,7 +3,7 @@
 @a = global i32 0, align 4
 ; Test that the llvm.dbg.value calls in a threaded block are correctly updated to
 ; target the locals in their threaded block, and not the unthreaded one.
-define void @test2(i32 %cond1, i32 %cond2) {
+define void @test1(i32 %cond1, i32 %cond2) {
 ; CHECK: [[globalptr:@.*]] = global i32 0, align 4
 ; CHECK: bb.cond2:
 ; CHECK: call void @llvm.dbg.value(metadata ptr null, metadata ![[DBG1ptr:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG2ptr:[0-9]+]]
@@ -49,6 +49,48 @@ exit:                                             ; preds = %bb.f4, %bb.f3, %bb.
   ret void, !dbg !29
 }
 
+; This is testing for debug value instrinsics outside of the threaded block pointing to a value
+; inside to correctly take any new definitions.
+define void @test2(i32 %cond1, i32 %cond2) !dbg !5 {
+; CHECK: bb.f3
+; CHECK: call void @llvm.dbg.value(metadata ptr @a, metadata !{{[0-9]+}}, metadata !DIExpression()), !dbg !{{[0-9]+}}
+; CHECK: bb.f4
+; CHECK-NEXT: [[PTR3:%.*]] = phi ptr [ null, %bb.cond2 ]
+; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[PTR3]], metadata !{{[0-9]+}}, metadata !DIExpression()), !dbg !{{[0-9]+}}
+entry:
+  %tobool = icmp eq i32 %cond1, 0, !dbg !15
+  br i1 %tobool, label %bb.cond2, label %bb.f1, !dbg !16
+
+bb.f1:                                            ; preds = %entry
+  call void @f1(), !dbg !17
+  br label %bb.cond2, !dbg !18
+
+bb.cond2:                                         ; preds = %bb.f1, %entry
+  %ptr = phi ptr [ null, %bb.f1 ], [ @a, %entry ], !dbg !19
+  %tobool1 = icmp eq i32 %cond2, 0, !dbg !20
+  br i1 %tobool1, label %bb.file, label %bb.f2, !dbg !21
+
+bb.f2:                                            ; preds = %bb.cond2
+  call void @f2(), !dbg !22
+  br label %exit, !dbg !23
+
+bb.file:                                          ; preds = %bb.cond2
+  %cmp = icmp eq ptr %ptr, null, !dbg !24
+  call void @llvm.dbg.value(metadata ptr %ptr, metadata !14, metadata !DIExpression()), !dbg !21
+  br i1 %cmp, label %bb.f4, label %bb.f3, !dbg !25
+
+bb.f3:                                            ; preds = %bb.file
+  call void @f3(), !dbg !26
+  br label %exit, !dbg !27
+
+bb.f4:                                            ; preds = %bb.file
+  call void @f4(), !dbg !28
+  br label %exit, !dbg !29
+
+exit:                                             ; preds = %bb.f4, %bb.f3, %bb.f2
+  ret void, !dbg !29
+}
+
 declare void @f1()
 
 declare void @f2()
@@ -95,4 +137,4 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo
 !26 = !DILocation(line: 12, column: 1, scope: !5)
 !27 = !DILocation(line: 13, column: 1, scope: !5)
 !28 = !DILocation(line: 14, column: 1, scope: !5)
-!29 = !DILocation(line: 15, column: 1, scope: !5)
\ No newline at end of file
+!29 = !DILocation(line: 15, column: 1, scope: !5)