[llvm] [Transforms] Debug values are not remapped when cloning. (PR #87747)

Carlos Alberto Enciso via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 9 05:07:22 PDT 2024


https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/87747

>From 2722cf87c2d14019e35e21611207265fa25cb775 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso
 <47597242+CarlosAlbertoEnciso at users.noreply.github.com>
Date: Fri, 5 Apr 2024 07:27:37 +0100
Subject: [PATCH 1/2] [Transforms] Debug values are not remapped when cloning.

When cloning instructions from one basic block to another,
the debug values are not remapped, in the same was as the
normal instructions.
---
 llvm/include/llvm/IR/IntrinsicInst.h          |  3 +-
 llvm/lib/IR/IntrinsicInst.cpp                 |  5 ++-
 llvm/lib/Transforms/Scalar/JumpThreading.cpp  | 29 +++++++++++++++
 llvm/lib/Transforms/Utils/CloneFunction.cpp   | 29 +++++++++++++++
 .../CallSiteSplitting/callsite-split-debug.ll | 36 ++++++++++++++++++-
 5 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 4f22720f1c558d..e74bf15a21b9a2 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -311,7 +311,8 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
 
   Value *getVariableLocationOp(unsigned OpIdx) const;
 
-  void replaceVariableLocationOp(Value *OldValue, Value *NewValue);
+  void replaceVariableLocationOp(Value *OldValue, Value *NewValue,
+                                 bool AllowEmpty = false);
   void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue);
   /// Adding a new location operand will always result in this intrinsic using
   /// an ArgList, and must always be accompanied by a new expression that uses
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
index 89403e1d7fcb4d..cff716a8430992 100644
--- a/llvm/lib/IR/IntrinsicInst.cpp
+++ b/llvm/lib/IR/IntrinsicInst.cpp
@@ -119,7 +119,8 @@ static ValueAsMetadata *getAsMetadata(Value *V) {
 }
 
 void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
-                                                     Value *NewValue) {
+                                                     Value *NewValue,
+                                                     bool AllowEmpty) {
   // If OldValue is used as the address part of a dbg.assign intrinsic replace
   // it with NewValue and return true.
   auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
@@ -136,6 +137,8 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
   auto Locations = location_ops();
   auto OldIt = find(Locations, OldValue);
   if (OldIt == Locations.end()) {
+    if (AllowEmpty)
+      return;
     assert(DbgAssignAddrReplaced &&
            "OldValue must be dbg.assign addr if unused in DIArgList");
     return;
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index ffcb511e6a8312..d7936969011e66 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -2694,6 +2694,35 @@ bool JumpThreadingPass::duplicateCondBranchOnPHIIntoPred(
           New->setOperand(i, I->second);
       }
 
+    // Remap debug variable operands.
+    auto RemapDebugVariable = [](auto &Mapping, auto *Inst) {
+      auto RemapDebugOperands = [&Mapping](auto *DV, auto Set) {
+        for (auto *Op : Set)
+          if (Instruction *InstOp = dyn_cast<Instruction>(Op)) {
+            auto I = Mapping.find(InstOp);
+            if (I != Mapping.end())
+              DV->replaceVariableLocationOp(Op, I->second, /*AllowEmpty=*/true);
+          }
+      };
+      auto RemapAssignAddress = [&Mapping](auto *DA) {
+        if (Instruction *Addr = dyn_cast<Instruction>(DA->getAddress())) {
+          auto I = Mapping.find(Addr);
+          if (I != Mapping.end())
+            DA->setAddress(I->second);
+        }
+      };
+      if (auto DVI = dyn_cast<DbgVariableIntrinsic>(Inst))
+        RemapDebugOperands(DVI, DVI->location_ops());
+      if (auto DAI = dyn_cast<DbgAssignIntrinsic>(Inst))
+        RemapAssignAddress(DAI);
+      for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) {
+        RemapDebugOperands(&DVR, DVR.location_ops());
+        if (DVR.isDbgAssign())
+          RemapAssignAddress(&DVR);
+      }
+    };
+    RemapDebugVariable(ValueMapping, New);
+
     // If this instruction can be simplified after the operands are updated,
     // just use the simplified value instead.  This frequently happens due to
     // phi translation.
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 3eac726994ae13..de58e1b759f96b 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -1131,6 +1131,35 @@ BasicBlock *llvm::DuplicateInstructionsInSplitBetween(
         if (I != ValueMapping.end())
           New->setOperand(i, I->second);
       }
+
+    // Remap debug variable operands.
+    auto RemapDebugVariable = [](auto &Mapping, auto *Inst) {
+      auto RemapDebugOperands = [&Mapping](auto *DV, auto Set) {
+        for (auto *Op : Set)
+          if (Instruction *InstOp = dyn_cast<Instruction>(Op)) {
+            auto I = Mapping.find(InstOp);
+            if (I != Mapping.end())
+              DV->replaceVariableLocationOp(Op, I->second, /*AllowEmpty=*/true);
+          }
+      };
+      auto RemapAssignAddress = [&Mapping](auto *DA) {
+        if (Instruction *Addr = dyn_cast<Instruction>(DA->getAddress())) {
+          auto I = Mapping.find(Addr);
+          if (I != Mapping.end())
+            DA->setAddress(I->second);
+        }
+      };
+      if (auto DVI = dyn_cast<DbgVariableIntrinsic>(Inst))
+        RemapDebugOperands(DVI, DVI->location_ops());
+      if (auto DAI = dyn_cast<DbgAssignIntrinsic>(Inst))
+        RemapAssignAddress(DAI);
+      for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) {
+        RemapDebugOperands(&DVR, DVR.location_ops());
+        if (DVR.isDbgAssign())
+          RemapAssignAddress(&DVR);
+      }
+    };
+    RemapDebugVariable(ValueMapping, New);
   }
 
   return NewBB;
diff --git a/llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll b/llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
index 8f10dcb30d7bfd..68c906d616c92d 100644
--- a/llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=callsite-splitting -o - < %s | FileCheck %s
+; RUN: opt -S -passes=callsite-splitting -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DEBUG
 ; RUN: opt -S -strip-debug -passes=callsite-splitting -o - < %s | FileCheck %s
 
 define internal i16 @bar(i16 %p1, i16 %p2) {
@@ -8,6 +8,9 @@ define internal i16 @bar(i16 %p1, i16 %p2) {
 
 define i16 @foo(i16 %in) {
 bb0:
+  %a = alloca i16, align 4, !DIAssignID !12
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !12, metadata ptr %a, metadata !DIExpression()), !dbg !8
+  store i16 7, ptr %a, align 4, !DIAssignID !13
   br label %bb1
 
 bb1:
@@ -20,13 +23,21 @@ bb2:
 CallsiteBB:
   %1 = phi i16 [ 0, %bb1 ], [ 1, %bb2 ]
   %c = phi i16 [ 2, %bb1 ], [ 3, %bb2 ]
+  %p = phi ptr [ %a, %bb1 ], [ %a, %bb2 ]
+  call void @llvm.dbg.value(metadata i16 %1, metadata !7, metadata !DIExpression()), !dbg !8
   call void @llvm.dbg.value(metadata i16 %c, metadata !7, metadata !DIExpression()), !dbg !8
+  call void @llvm.dbg.value(metadata !DIArgList(i16 %1, i16 %c), metadata !7, metadata !DIExpression()), !dbg !8
+  call void @llvm.dbg.value(metadata !DIArgList(i16 %c, i16 %c), metadata !7, metadata !DIExpression()), !dbg !8
+  call void @llvm.dbg.assign(metadata i16 %1, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %a, metadata !DIExpression()), !dbg !8
+  call void @llvm.dbg.assign(metadata i16 %c, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %a, metadata !DIExpression()), !dbg !8
+  call void @llvm.dbg.assign(metadata i16 %1, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %p, metadata !DIExpression()), !dbg !8
   %2 = call i16 @bar(i16 %1, i16 5)
   ret i16 %2
 }
 
 ; Function Attrs: nounwind readnone speculatable
 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
 
 attributes #0 = { nounwind readnone speculatable }
 
@@ -43,14 +54,37 @@ attributes #0 = { nounwind readnone speculatable }
 !6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, unit: !0)
 !7 = !DILocalVariable(name: "c", scope: !6, line: 5, type: !5)
 !8 = !DILocation(line: 5, column: 7, scope: !6)
+!11 = !DILocalVariable(name: "a", scope: !6, line: 6, type: !5)
+!12 = distinct !DIAssignID()
+!13 = distinct !DIAssignID()
 
 ; The optimization should trigger even in the presence of the dbg.value in
 ; CallSiteBB.
 
 ; CHECK-LABEL: @foo
 ; CHECK-LABEL: bb1.split:
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 0, metadata ![[DBG_1:[0-9]+]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 2, metadata ![[DBG_1]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 0, i16 2), {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 2, i16 2), {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 0, metadata ![[DBG_2:[0-9]+]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 2, metadata ![[DBG_2]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 0, metadata ![[DBG_2]], metadata !DIExpression(), metadata ![[ID_1:[0-9]+]], metadata ptr %a, {{.*}}
 ; CHECK: [[TMP1:%[0-9]+]] = call i16 @bar(i16 0, i16 5)
+
 ; CHECK-LABEL: bb2.split:
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 1, metadata ![[DBG_1]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 3, metadata ![[DBG_1]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 1, i16 3), {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 3, i16 3), {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 1, metadata ![[DBG_2]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 3, metadata ![[DBG_2]], {{.*}}
+; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 1, metadata ![[DBG_2]], metadata !DIExpression(), metadata ![[ID_1:[0-9]+]], metadata ptr %a, {{.*}}
 ; CHECK: [[TMP2:%[0-9]+]] = call i16 @bar(i16 1, i16 5)
+
 ; CHECK-LABEL: CallsiteBB
 ; CHECK: %phi.call = phi i16 [ [[TMP2]], %bb2.split ], [ [[TMP1]], %bb1.split
+
+; CHECK-DEBUG-DAG: ![[DBG_1]] = !DILocalVariable(name: "c"{{.*}})
+; CHECK-DEBUG-DAG: ![[DBG_2]] = !DILocalVariable(name: "a"{{.*}})
+; CHECK-DEBUG-DAG: ![[ID_1]] = distinct !DIAssignID()

>From 21c102bbe103f56b6cc6843961ca5b18c17de91d Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso
 <47597242+CarlosAlbertoEnciso at users.noreply.github.com>
Date: Tue, 9 Apr 2024 13:01:44 +0100
Subject: [PATCH 2/2] [Transforms] Debug values are not remapped when cloning.

When cloning instructions from one basic block to another,
the debug values are not remapped, in the same was as the
normal instructions.

Missing condition '|| DbgAssignAddrReplaced' to account
for any 'dbg.assign' replacement.
---
 llvm/lib/IR/IntrinsicInst.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
index cff716a8430992..f7d360f4a453df 100644
--- a/llvm/lib/IR/IntrinsicInst.cpp
+++ b/llvm/lib/IR/IntrinsicInst.cpp
@@ -137,7 +137,7 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
   auto Locations = location_ops();
   auto OldIt = find(Locations, OldValue);
   if (OldIt == Locations.end()) {
-    if (AllowEmpty)
+    if (AllowEmpty || DbgAssignAddrReplaced)
       return;
     assert(DbgAssignAddrReplaced &&
            "OldValue must be dbg.assign addr if unused in DIArgList");



More information about the llvm-commits mailing list