[llvm] r327303 - [SelectionDAG] Improve handling of dangling debug info

Bjorn Pettersson via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 12 11:02:40 PDT 2018


Author: bjope
Date: Mon Mar 12 11:02:39 2018
New Revision: 327303

URL: http://llvm.org/viewvc/llvm-project?rev=327303&view=rev
Log:
[SelectionDAG] Improve handling of dangling debug info

Summary:
1) Make sure to discard dangling debug info if the variable (or
variable fragment) is mapped to something new before we had a
chance to resolve the dangling debug info.

2) When resolving debug info, make sure to bump the associated
SDNodeOrder to ensure that the DBG_VALUE is emitted after the
instruction that defines the value used in the DBG_VALUE.
This will avoid a debug-use before def scenario as seen in
https://bugs.llvm.org/show_bug.cgi?id=36417.

The new test case, test/DebugInfo/X86/sdag-dangling-dbgvalue.ll,
show some other limitations in how dangling debug info is
handled in the SelectionDAG. Since we currently only support
having one dangling dbg.value per Value, we will end up dropping
debug info when there are more than one variable that is described
by the same "dangling value".

Reviewers: aprantl

Reviewed By: aprantl

Subscribers: aprantl, eraman, llvm-commits, JDevlieghere

Tags: #debug-info

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

Added:
    llvm/trunk/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll
Modified:
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
    llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Mon Mar 12 11:02:39 2018
@@ -2415,6 +2415,32 @@ public:
   static Optional<DIExpression *>
   createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits,
                            unsigned SizeInBits);
+
+  /// Determine the relative position of the fragments described by this
+  /// DIExpression and \p Other.
+  /// Returns -1 if this is entirely before Other, 0 if this and Other overlap,
+  /// 1 if this is entirely after Other.
+  int fragmentCmp(const DIExpression *Other) const {
+    auto Fragment1 = *getFragmentInfo();
+    auto Fragment2 = *Other->getFragmentInfo();
+    unsigned l1 = Fragment1.OffsetInBits;
+    unsigned l2 = Fragment2.OffsetInBits;
+    unsigned r1 = l1 + Fragment1.SizeInBits;
+    unsigned r2 = l2 + Fragment2.SizeInBits;
+    if (r1 <= l2)
+      return -1;
+    else if (r2 <= l1)
+      return 1;
+    else
+      return 0;
+  }
+
+  /// Check if fragments overlap between this DIExpression and \p Other.
+  bool fragmentsOverlap(const DIExpression *Other) const {
+    if (!isFragment() || !Other->isFragment())
+      return true;
+    return fragmentCmp(Other) == 0;
+  }
 };
 
 /// Global variables.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Mon Mar 12 11:02:39 2018
@@ -1107,7 +1107,7 @@ void CodeViewDebug::calculateRanges(
       auto J = std::next(I);
       const DIExpression *DIExpr = DVInst->getDebugExpression();
       while (J != E &&
-             !fragmentsOverlap(DIExpr, J->first->getDebugExpression()))
+             !DIExpr->fragmentsOverlap(J->first->getDebugExpression()))
         ++J;
       if (J != E)
         End = getLabelBeforeInsn(J->first);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp Mon Mar 12 11:02:39 2018
@@ -123,29 +123,6 @@ MCSymbol *DebugHandlerBase::getLabelAfte
   return LabelsAfterInsn.lookup(MI);
 }
 
-int DebugHandlerBase::fragmentCmp(const DIExpression *P1,
-                                  const DIExpression *P2) {
-  auto Fragment1 = *P1->getFragmentInfo();
-  auto Fragment2 = *P2->getFragmentInfo();
-  unsigned l1 = Fragment1.OffsetInBits;
-  unsigned l2 = Fragment2.OffsetInBits;
-  unsigned r1 = l1 + Fragment1.SizeInBits;
-  unsigned r2 = l2 + Fragment2.SizeInBits;
-  if (r1 <= l2)
-    return -1;
-  else if (r2 <= l1)
-    return 1;
-  else
-    return 0;
-}
-
-bool DebugHandlerBase::fragmentsOverlap(const DIExpression *P1,
-                                        const DIExpression *P2) {
-  if (!P1->isFragment() || !P2->isFragment())
-    return true;
-  return fragmentCmp(P1, P2) == 0;
-}
-
 /// If this type is derived from a base type then return base type size.
 uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) {
   DIType *Ty = TyRef.resolve();
@@ -232,8 +209,8 @@ void DebugHandlerBase::beginFunction(con
           const DIExpression *Fragment = I->first->getDebugExpression();
           if (std::all_of(Ranges.begin(), I,
                           [&](DbgValueHistoryMap::InstrRange Pred) {
-                            return !fragmentsOverlap(
-                                Fragment, Pred.first->getDebugExpression());
+                            return !Fragment->fragmentsOverlap(
+                                Pred.first->getDebugExpression());
                           }))
             LabelsBeforeInsn[I->first] = Asm->getFunctionBegin();
           else

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h Mon Mar 12 11:02:39 2018
@@ -122,14 +122,6 @@ public:
   /// Return Label immediately following the instruction.
   MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
 
-  /// Determine the relative position of the fragments described by P1 and P2.
-  /// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, 1 if P1 is
-  /// entirely after P2.
-  static int fragmentCmp(const DIExpression *P1, const DIExpression *P2);
-
-  /// Determine whether two variable fragments overlap.
-  static bool fragmentsOverlap(const DIExpression *P1, const DIExpression *P2);
-
   /// If this type is derived from a base type then return base type size.
   static uint64_t getBaseTypeSize(const DITypeRef TyRef);
 };

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Mon Mar 12 11:02:39 2018
@@ -919,8 +919,7 @@ bool DebugLocEntry::MergeValues(const De
     // sorted.
     for (unsigned i = 0, j = 0; i < Values.size(); ++i) {
       for (; j < Next.Values.size(); ++j) {
-        int res = DebugHandlerBase::fragmentCmp(
-            cast<DIExpression>(Values[i].Expression),
+        int res = cast<DIExpression>(Values[i].Expression)->fragmentCmp(
             cast<DIExpression>(Next.Values[j].Expression));
         if (res == 0) // The two expressions overlap, we can't merge.
           return false;
@@ -983,7 +982,7 @@ DwarfDebug::buildLocationList(SmallVecto
     // If this fragment overlaps with any open ranges, truncate them.
     const DIExpression *DIExpr = Begin->getDebugExpression();
     auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) {
-      return fragmentsOverlap(DIExpr, R.getExpression());
+      return DIExpr->fragmentsOverlap(R.getExpression());
     });
     OpenRanges.erase(Last, OpenRanges.end());
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Mon Mar 12 11:02:39 2018
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SelectionDAGBuilder.h"
+#include "SDNodeDbgValue.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -1077,29 +1078,64 @@ void SelectionDAGBuilder::visit(unsigned
   }
 }
 
+void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
+                                                const DIExpression *Expr) {
+  SmallVector<const Value *, 4> ToRemove;
+  for (auto &DMI : DanglingDebugInfoMap) {
+    DanglingDebugInfo &DDI = DMI.second;
+    if (DDI.getDI()) {
+      const DbgValueInst *DI = DDI.getDI();
+      DIVariable *DanglingVariable = DI->getVariable();
+      DIExpression *DanglingExpr = DI->getExpression();
+      if (DanglingVariable == Variable &&
+          Expr->fragmentsOverlap(DanglingExpr)) {
+        DEBUG(dbgs() << "Dropping dangling debug info for " << *DI << "\n");
+        ToRemove.push_back(DMI.first);
+      }
+    }
+  }
+
+  for (auto V : ToRemove)
+    DanglingDebugInfoMap[V] = DanglingDebugInfo();
+}
+
 // resolveDanglingDebugInfo - if we saw an earlier dbg_value referring to V,
 // generate the debug data structures now that we've seen its definition.
 void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
                                                    SDValue Val) {
   DanglingDebugInfo &DDI = DanglingDebugInfoMap[V];
-  if (DDI.getDI()) {
-    const DbgValueInst *DI = DDI.getDI();
-    DebugLoc dl = DDI.getdl();
-    unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
-    DILocalVariable *Variable = DI->getVariable();
-    DIExpression *Expr = DI->getExpression();
-    assert(Variable->isValidLocationForIntrinsic(dl) &&
-           "Expected inlined-at fields to agree");
-    SDDbgValue *SDV;
-    if (Val.getNode()) {
-      if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, false, Val)) {
-        SDV = getDbgValue(Val, Variable, Expr, dl, DbgSDNodeOrder);
-        DAG.AddDbgValue(SDV, Val.getNode(), false);
-      }
+  if (!DDI.getDI())
+    return;
+  const DbgValueInst *DI = DDI.getDI();
+  DebugLoc dl = DDI.getdl();
+  unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
+  unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
+  DILocalVariable *Variable = DI->getVariable();
+  DIExpression *Expr = DI->getExpression();
+  assert(Variable->isValidLocationForIntrinsic(dl) &&
+         "Expected inlined-at fields to agree");
+  SDDbgValue *SDV;
+  if (Val.getNode()) {
+    if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, false, Val)) {
+      DEBUG(dbgs() << "Resolve dangling debug info [order=" << DbgSDNodeOrder
+            << "] for:\n  " << *DI << "\n");
+      DEBUG(dbgs() << "  By mapping to:\n    "; Val.dump());
+      // Increase the SDNodeOrder for the DbgValue here to make sure it is
+      // inserted after the definition of Val when emitting the instructions
+      // after ISel. An alternative could be to teach
+      // ScheduleDAGSDNodes::EmitSchedule to delay the insertion properly.
+      DEBUG(if (ValSDNodeOrder > DbgSDNodeOrder)
+              dbgs() << "changing SDNodeOrder from " << DbgSDNodeOrder
+                     << " to " << ValSDNodeOrder << "\n");
+      SDV = getDbgValue(Val, Variable, Expr, dl,
+                        std::max(DbgSDNodeOrder, ValSDNodeOrder));
+      DAG.AddDbgValue(SDV, Val.getNode(), false);
     } else
-      DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
-    DanglingDebugInfoMap[V] = DanglingDebugInfo();
-  }
+      DEBUG(dbgs() << "Resolved dangling debug info for " << *DI
+            << "in EmitFuncArgumentDbgValue\n");
+  } else
+    DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
+  DanglingDebugInfoMap[V] = DanglingDebugInfo();
 }
 
 /// getCopyFromRegs - If there was virtual register allocated for the value V
@@ -5178,6 +5214,7 @@ SelectionDAGBuilder::visitIntrinsicCall(
     const DbgInfoIntrinsic &DI = cast<DbgInfoIntrinsic>(I);
     DILocalVariable *Variable = DI.getVariable();
     DIExpression *Expression = DI.getExpression();
+    dropDanglingDebugInfo(Variable, Expression);
     assert(Variable && "Missing variable");
 
     // Check if address has undef value.
@@ -5209,10 +5246,11 @@ SelectionDAGBuilder::visitIntrinsicCall(
     // DBG_VALUE instructions. llvm.dbg.declare is handled as a frame index in
     // the MachineFunction variable table.
     if (FI != std::numeric_limits<int>::max()) {
-      if (Intrinsic == Intrinsic::dbg_addr)
-        DAG.AddDbgValue(DAG.getFrameIndexDbgValue(Variable, Expression, FI, dl,
-                                                  SDNodeOrder),
-                        getRoot().getNode(), isParameter);
+      if (Intrinsic == Intrinsic::dbg_addr) {
+         SDDbgValue *SDV = DAG.getFrameIndexDbgValue(Variable, Expression,
+                                                     FI, dl, SDNodeOrder);
+         DAG.AddDbgValue(SDV, getRoot().getNode(), isParameter);
+      }
       return nullptr;
     }
 
@@ -5256,6 +5294,7 @@ SelectionDAGBuilder::visitIntrinsicCall(
 
     DILocalVariable *Variable = DI.getVariable();
     DIExpression *Expression = DI.getExpression();
+    dropDanglingDebugInfo(Variable, Expression);
     const Value *V = DI.getValue();
     if (!V)
       return nullptr;
@@ -5280,6 +5319,12 @@ SelectionDAGBuilder::visitIntrinsicCall(
       return nullptr;
     }
 
+    // TODO: When we get here we will either drop the dbg.value completely, or
+    // we try to move it forward by letting it dangle for awhile. So we should
+    // probably add an extra DbgValue to the DAG here, with a reference to
+    // "noreg", to indicate that we have lost the debug location for the
+    // variable.
+
     if (!V->use_empty() ) {
       // Do not call getValue(V) yet, as we don't want to generate code.
       // Remember it for later.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h Mon Mar 12 11:02:39 2018
@@ -671,6 +671,12 @@ public:
   /// emit CopyFromReg of the specified type Ty. Return empty SDValue() otherwise.
   SDValue getCopyFromRegs(const Value *V, Type *Ty);
 
+  /// If we have dangling debug info that describes \p Variable, or an
+  /// overlapping part of variable considering the \p Expr, then this method
+  /// weill drop that debug info as it isn't valid any longer.
+  void dropDanglingDebugInfo(const DILocalVariable *Variable,
+                             const DIExpression *Expr);
+
   // resolveDanglingDebugInfo - if we saw an earlier dbg_value referring to V,
   // generate the debug data structures now that we've seen its definition.
   void resolveDanglingDebugInfo(const Value *V, SDValue Val);

Modified: llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll?rev=327303&r1=327302&r2=327303&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll (original)
+++ llvm/trunk/test/DebugInfo/X86/dbg-value-inlined-parameter.ll Mon Mar 12 11:02:39 2018
@@ -32,10 +32,10 @@
 ;CHECK-NEXT: DW_AT_call_line
 
 ;CHECK: DW_TAG_formal_parameter
+;FIXME: Linux shouldn't drop this parameter either...
 ;CHECK-NOT: DW_TAG
-;FIXME: Shouldn't drop this parameter...
-;XCHECK:   DW_AT_abstract_origin {{.*}} "sp"
-;XCHECK: DW_TAG_formal_parameter
+;DARWIN:   DW_AT_abstract_origin {{.*}} "sp"
+;DARWIN: DW_TAG_formal_parameter
 ;CHECK: DW_AT_abstract_origin {{.*}} "nums"
 ;CHECK-NOT: DW_TAG_formal_parameter
 

Added: llvm/trunk/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll?rev=327303&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/sdag-dangling-dbgvalue.ll Mon Mar 12 11:02:39 2018
@@ -0,0 +1,201 @@
+; RUN: llc %s -stop-before expand-isel-pseudos -o - | FileCheck %s
+
+;--------------------------------------------------------------------
+; This test case is basically generated from the following C code.
+; Compiled with "--target=x86_64-apple-darwin -S -g -O3" to get debug
+; info for optimized code.
+;
+; struct SS {
+;   int a;
+;   int b;
+; } S = { .a = 23, .b = -17 };
+;
+; int test1() {
+;   struct SS* foo1 = &S;
+;   return (int)foo1;
+; }
+;
+; int test2() {
+;   struct SS* foo2 = &S;
+;   struct SS* bar2 = &S;
+;   return (int)foo2 + (int)bar2;
+; }
+;
+; int test3() {
+;   struct SS* bar3 = &S;
+;   struct SS* foo3 = &S;
+;   return (int)foo3 + (int)bar3;
+; }
+;
+; int test4() {
+;   struct SS* foo4 = &S;
+;   struct SS* bar4 = &S;
+;   foo = 0;
+;   return (int)foo4 + (int)bar4;
+; }
+;
+; int test5() {
+;   struct SS* bar5 = &S;
+;   struct SS* foo5 = &S;
+;   foo5 = 0;
+;   return (int)foo5 + (int)bar5;
+; }
+;--------------------------------------------------------------------
+
+; CHECK:  ![[FOO1:.*]] = !DILocalVariable(name: "foo1"
+; CHECK:  ![[BAR1:.*]] = !DILocalVariable(name: "bar1"
+; CHECK:  ![[FOO2:.*]] = !DILocalVariable(name: "foo2"
+; CHECK:  ![[BAR2:.*]] = !DILocalVariable(name: "bar2"
+; CHECK:  ![[FOO3:.*]] = !DILocalVariable(name: "bar3"
+; CHECK:  ![[BAR3:.*]] = !DILocalVariable(name: "foo3"
+; CHECK:  ![[FOO4:.*]] = !DILocalVariable(name: "foo4"
+; CHECK:  ![[BAR4:.*]] = !DILocalVariable(name: "bar4"
+; CHECK:  ![[FOO5:.*]] = !DILocalVariable(name: "bar5"
+; CHECK:  ![[BAR5:.*]] = !DILocalVariable(name: "foo5"
+
+
+source_filename = "sdag-dangling-dbgvalue.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.4.0"
+
+%struct.SS = type { i32, i32 }
+
+ at S = global %struct.SS { i32 23, i32 -17 }, align 4, !dbg !0
+
+; Verify that the def comes before the debug-use for foo1.
+; TODO: Currently dbg.value for bar1 is dropped(?), is that expected?
+define i32 @test1() local_unnamed_addr #0 !dbg !17 {
+; CHECK-LABEL: bb.0.entry1
+; CHECK-NEXT:    [[REG1:%[0-9]+]]:gr64 =
+; CHECK-NEXT:    DBG_VALUE debug-use [[REG1]], debug-use $noreg, ![[FOO1]], !DIExpression()
+entry1:
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !20, metadata !DIExpression()), !dbg !23
+  call void @llvm.dbg.value(metadata %struct.SS* null, metadata !22, metadata !DIExpression()), !dbg !24
+  ret i32 ptrtoint (%struct.SS* @S to i32), !dbg !25
+}
+
+; Verify that the def comes before the debug-use for bar2.
+; TODO: Currently dbg.value for foo2 is dropped. Seems to be a bug. The
+;       SelectionDAGBuilder should support several dangling dbg.value for the
+;       same value.
+define i32 @test2() local_unnamed_addr #0 !dbg !26 {
+; CHECK-LABEL: bb.0.entry2
+; CHECK-NEXT:    [[REG2:%[0-9]+]]:gr64 =
+; CHECK-NEXT:    DBG_VALUE debug-use [[REG2]], debug-use $noreg, ![[BAR2]], !DIExpression()
+entry2:
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !28, metadata !DIExpression()), !dbg !30
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !29, metadata !DIExpression()), !dbg !31
+  ret i32 add (i32 ptrtoint (%struct.SS* @S to i32), i32 ptrtoint (%struct.SS* @S to i32)), !dbg !32
+}
+
+; Verify that the def comes before the debug-use for foo3.
+; TODO: Currently dbg.value for bar3 is dropped. Seems to be a bug. The
+;       SelectionDAGBuilder should support several dangling dbg.value for the
+;       same value.
+define i32 @test3() local_unnamed_addr #0 !dbg !33 {
+; CHECK-LABEL: bb.0.entry3
+; CHECK-NEXT:    [[REG3:%[0-9]+]]:gr64 =
+; CHECK-NEXT:    DBG_VALUE debug-use [[REG3]], debug-use $noreg, ![[FOO3]], !DIExpression()
+entry3:
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !36, metadata !DIExpression()), !dbg !38
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !35, metadata !DIExpression()), !dbg !37
+  ret i32 add (i32 ptrtoint (%struct.SS* @S to i32), i32 ptrtoint (%struct.SS* @S to i32)), !dbg !39
+}
+
+; Verify that the def comes before the debug-use for bar4.
+; TODO: Currently dbg.value for foo4 is dropped. It is set to null and not
+;       used. Just like in test1 it can be discussed if there should be a
+;       DBG_VALUE for foo4 here.
+define i32 @test4() local_unnamed_addr #0 !dbg !40 {
+; CHECK-LABEL: bb.0.entry4
+; CHECK-NEXT:    [[REG4:%[0-9]+]]:gr64 =
+; CHECK-NEXT:    DBG_VALUE debug-use [[REG4]], debug-use $noreg, ![[BAR4]], !DIExpression()
+entry4:
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !42, metadata !DIExpression()), !dbg !44
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !43, metadata !DIExpression()), !dbg !45
+  call void @llvm.dbg.value(metadata %struct.SS* null, metadata !42, metadata !DIExpression()), !dbg !44
+  ret i32 ptrtoint (%struct.SS* @S to i32), !dbg !46
+}
+
+; Verify that we do not get a DBG_VALUE that maps foo5 to @S here.
+; TODO: At the moment we do not get any DBG_VALUE at all here. If
+;       SelectionDAGBuilder should support several dangling dbg.value for the
+;       same value it would be possible to at least get a DBG_VALUE for
+;       bar5.
+; TODO: foo5 is set to null, and it is not really used. Just like in test1 it
+;       can be discussed if there should be a DBG_VALUE for foo5 here.
+define i32 @test5() local_unnamed_addr #0 !dbg !47 {
+; CHECK-LABEL: bb.0.entry5:
+; CHECK-NOT:     DBG_VALUE
+; CHECK:         RET
+entry5:
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !49, metadata !DIExpression()), !dbg !51
+  call void @llvm.dbg.value(metadata %struct.SS* @S, metadata !50, metadata !DIExpression()), !dbg !52
+  call void @llvm.dbg.value(metadata %struct.SS* null, metadata !50, metadata !DIExpression()), !dbg !52
+  ret i32 ptrtoint (%struct.SS* @S to i32), !dbg !53
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind readnone uwtable }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!12, !13, !14, !15}
+!llvm.ident = !{!16}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "S", scope: !2, file: !3, line: 4, type: !8, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 327229) (llvm/trunk 327239)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !7)
+!3 = !DIFile(filename: "sdag-dangling-dbgvalue.c", directory: "/repo/uabbpet/llvm-master")
+!4 = !{}
+!5 = !{!6}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{!0}
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SS", file: !3, line: 1, size: 64, elements: !9)
+!9 = !{!10, !11}
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !8, file: !3, line: 2, baseType: !6, size: 32)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !8, file: !3, line: 3, baseType: !6, size: 32, offset: 32)
+!12 = !{i32 2, !"Dwarf Version", i32 2}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+!14 = !{i32 1, !"wchar_size", i32 4}
+!15 = !{i32 7, !"PIC Level", i32 2}
+!16 = !{!"clang version 7.0.0 (trunk 327229) (llvm/trunk 327239)"}
+!17 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 6, type: !18, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: true, unit: !2, variables: !19)
+!18 = !DISubroutineType(types: !5)
+!19 = !{!20, !22}
+!20 = !DILocalVariable(name: "foo1", scope: !17, file: !3, line: 7, type: !21)
+!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!22 = !DILocalVariable(name: "bar1", scope: !17, file: !3, line: 8, type: !21)
+!23 = !DILocation(line: 7, column: 14, scope: !17)
+!24 = !DILocation(line: 8, column: 14, scope: !17)
+!25 = !DILocation(line: 9, column: 3, scope: !17)
+!26 = distinct !DISubprogram(name: "test2", scope: !3, file: !3, line: 12, type: !18, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !2, variables: !27)
+!27 = !{!28, !29}
+!28 = !DILocalVariable(name: "foo2", scope: !26, file: !3, line: 13, type: !21)
+!29 = !DILocalVariable(name: "bar2", scope: !26, file: !3, line: 14, type: !21)
+!30 = !DILocation(line: 13, column: 14, scope: !26)
+!31 = !DILocation(line: 14, column: 14, scope: !26)
+!32 = !DILocation(line: 15, column: 3, scope: !26)
+!33 = distinct !DISubprogram(name: "test3", scope: !3, file: !3, line: 18, type: !18, isLocal: false, isDefinition: true, scopeLine: 18, isOptimized: true, unit: !2, variables: !34)
+!34 = !{!35, !36}
+!35 = !DILocalVariable(name: "bar3", scope: !33, file: !3, line: 19, type: !21)
+!36 = !DILocalVariable(name: "foo3", scope: !33, file: !3, line: 20, type: !21)
+!37 = !DILocation(line: 19, column: 14, scope: !33)
+!38 = !DILocation(line: 20, column: 14, scope: !33)
+!39 = !DILocation(line: 21, column: 3, scope: !33)
+!40 = distinct !DISubprogram(name: "test4", scope: !3, file: !3, line: 24, type: !18, isLocal: false, isDefinition: true, scopeLine: 24, isOptimized: true, unit: !2, variables: !41)
+!41 = !{!42, !43}
+!42 = !DILocalVariable(name: "foo4", scope: !40, file: !3, line: 25, type: !21)
+!43 = !DILocalVariable(name: "bar4", scope: !40, file: !3, line: 26, type: !21)
+!44 = !DILocation(line: 25, column: 14, scope: !40)
+!45 = !DILocation(line: 26, column: 14, scope: !40)
+!46 = !DILocation(line: 28, column: 3, scope: !40)
+!47 = distinct !DISubprogram(name: "test5", scope: !3, file: !3, line: 31, type: !18, isLocal: false, isDefinition: true, scopeLine: 31, isOptimized: true, unit: !2, variables: !48)
+!48 = !{!49, !50}
+!49 = !DILocalVariable(name: "bar5", scope: !47, file: !3, line: 32, type: !21)
+!50 = !DILocalVariable(name: "foo5", scope: !47, file: !3, line: 33, type: !21)
+!51 = !DILocation(line: 32, column: 14, scope: !47)
+!52 = !DILocation(line: 33, column: 14, scope: !47)
+!53 = !DILocation(line: 35, column: 3, scope: !47)




More information about the llvm-commits mailing list