[llvm] r351525 - [CodeGen] Fix bugs in LiveDebugVariables when debug labels are generated.

Hsiangkai Wang via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 17 23:17:10 PST 2019


Author: hsiangkai
Date: Thu Jan 17 23:17:09 2019
New Revision: 351525

URL: http://llvm.org/viewvc/llvm-project?rev=351525&view=rev
Log:
[CodeGen] Fix bugs in LiveDebugVariables when debug labels are generated.

Remove DBG_LABELs in LiveDebugVariables and generate them in
VirtRegRewriter.

This bug is reported in
https://bugs.chromium.org/p/chromium/issues/detail?id=898152.

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

Added:
    llvm/trunk/test/CodeGen/Generic/live-debug-label.ll
Modified:
    llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp

Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp?rev=351525&r1=351524&r2=351525&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Thu Jan 17 23:17:09 2019
@@ -71,6 +71,7 @@ EnableLDV("live-debug-variables", cl::in
           cl::desc("Enable the live debug variables pass"), cl::Hidden);
 
 STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted");
+STATISTIC(NumInsertedDebugLabels, "Number of DBG_LABELs inserted");
 
 char LiveDebugVariables::ID = 0;
 
@@ -339,6 +340,37 @@ public:
   void print(raw_ostream &, const TargetRegisterInfo *);
 };
 
+/// A user label is a part of a debug info user label.
+class UserLabel {
+  const DILabel *Label; ///< The debug info label we are part of.
+  DebugLoc dl;          ///< The debug location for the label. This is
+                        ///< used by dwarf writer to find lexical scope.
+  SlotIndex loc;        ///< Slot used by the debug label.
+
+  /// Insert a DBG_LABEL into MBB at Idx.
+  void insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx,
+                        LiveIntervals &LIS, const TargetInstrInfo &TII);
+
+public:
+  /// Create a new UserLabel.
+  UserLabel(const DILabel *label, DebugLoc L, SlotIndex Idx)
+      : Label(label), dl(std::move(L)), loc(Idx) {}
+
+  /// Does this UserLabel match the parameters?
+  bool match(const DILabel *L, const DILocation *IA,
+             const SlotIndex Index) const {
+    return Label == L && dl->getInlinedAt() == IA && loc == Index;
+  }
+
+  /// Recreate DBG_LABEL instruction from data structures.
+  void emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII);
+
+  /// Return DebugLoc of this UserLabel.
+  DebugLoc getDebugLoc() { return dl; }
+
+  void print(raw_ostream &, const TargetRegisterInfo *);
+};
+
 /// Implementation of the LiveDebugVariables pass.
 class LDVImpl {
   LiveDebugVariables &pass;
@@ -356,6 +388,9 @@ class LDVImpl {
   /// All allocated UserValue instances.
   SmallVector<std::unique_ptr<UserValue>, 8> userValues;
 
+  /// All allocated UserLabel instances.
+  SmallVector<std::unique_ptr<UserLabel>, 2> userLabels;
+
   /// Map virtual register to eq class leader.
   using VRMap = DenseMap<unsigned, UserValue *>;
   VRMap virtRegToEqClass;
@@ -379,6 +414,14 @@ class LDVImpl {
   /// \returns True if the DBG_VALUE instruction should be deleted.
   bool handleDebugValue(MachineInstr &MI, SlotIndex Idx);
 
+  /// Add DBG_LABEL instruction to UserLabel.
+  ///
+  /// \param MI DBG_LABEL instruction
+  /// \param Idx Last valid SlotIndex before instruction.
+  ///
+  /// \returns True if the DBG_LABEL instruction should be deleted.
+  bool handleDebugLabel(MachineInstr &MI, SlotIndex Idx);
+
   /// Collect and erase all DBG_VALUE instructions, adding a UserValue def
   /// for each instruction.
   ///
@@ -400,6 +443,7 @@ public:
   void clear() {
     MF = nullptr;
     userValues.clear();
+    userLabels.clear();
     virtRegToEqClass.clear();
     userVarMap.clear();
     // Make sure we call emitDebugValues if the machine function was modified.
@@ -445,12 +489,21 @@ static void printDebugLoc(const DebugLoc
   CommentOS << " ]";
 }
 
-static void printExtendedName(raw_ostream &OS, const DILocalVariable *V,
+static void printExtendedName(raw_ostream &OS, const DINode *Node,
                               const DILocation *DL) {
-  const LLVMContext &Ctx = V->getContext();
-  StringRef Res = V->getName();
+  const LLVMContext &Ctx = Node->getContext();
+  StringRef Res;
+  unsigned Line;
+  if (const auto *V = dyn_cast<const DILocalVariable>(Node)) {
+    Res = V->getName();
+    Line = V->getLine();
+  } else if (const auto *L = dyn_cast<const DILabel>(Node)) {
+    Res = L->getName();
+    Line = L->getLine();
+  }
+
   if (!Res.empty())
-    OS << Res << "," << V->getLine();
+    OS << Res << "," << Line;
   if (auto *InlinedAt = DL->getInlinedAt()) {
     if (DebugLoc InlinedAtDL = InlinedAt) {
       OS << " @[";
@@ -461,9 +514,8 @@ static void printExtendedName(raw_ostrea
 }
 
 void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
-  auto *DV = cast<DILocalVariable>(Variable);
   OS << "!\"";
-  printExtendedName(OS, DV, dl);
+  printExtendedName(OS, Variable, dl);
 
   OS << "\"\t";
   for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) {
@@ -483,10 +535,22 @@ void UserValue::print(raw_ostream &OS, c
   OS << '\n';
 }
 
+void UserLabel::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
+  OS << "!\"";
+  printExtendedName(OS, Label, dl);
+
+  OS << "\"\t";
+  OS << loc;
+  OS << '\n';
+}
+
 void LDVImpl::print(raw_ostream &OS) {
   OS << "********** DEBUG VARIABLES **********\n";
-  for (unsigned i = 0, e = userValues.size(); i != e; ++i)
-    userValues[i]->print(OS, TRI);
+  for (auto &userValue : userValues)
+    userValue->print(OS, TRI);
+  OS << "********** DEBUG LABELS **********\n";
+  for (auto &userLabel : userLabels)
+    userLabel->print(OS, TRI);
 }
 #endif
 
@@ -587,6 +651,29 @@ bool LDVImpl::handleDebugValue(MachineIn
   return true;
 }
 
+bool LDVImpl::handleDebugLabel(MachineInstr &MI, SlotIndex Idx) {
+  // DBG_LABEL label
+  if (MI.getNumOperands() != 1 || !MI.getOperand(0).isMetadata()) {
+    LLVM_DEBUG(dbgs() << "Can't handle " << MI);
+    return false;
+  }
+
+  // Get or create the UserLabel for label here.
+  const DILabel *Label = MI.getDebugLabel();
+  const DebugLoc &DL = MI.getDebugLoc();
+  bool Found = false;
+  for (auto const &L : userLabels) {
+    if (L->match(Label, DL->getInlinedAt(), Idx)) {
+      Found = true;
+      break;
+    }
+  }
+  if (!Found)
+    userLabels.push_back(llvm::make_unique<UserLabel>(Label, DL, Idx));
+
+  return true;
+}
+
 bool LDVImpl::collectDebugValues(MachineFunction &mf) {
   bool Changed = false;
   for (MachineFunction::iterator MFI = mf.begin(), MFE = mf.end(); MFI != MFE;
@@ -610,7 +697,8 @@ bool LDVImpl::collectDebugValues(Machine
       do {
         // Only handle DBG_VALUE in handleDebugValue(). Skip all other
         // kinds of debug instructions.
-        if (MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) {
+        if ((MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) ||
+            (MBBI->isDebugLabel() && handleDebugLabel(*MBBI, Idx))) {
           MBBI = MBB->erase(MBBI);
           Changed = true;
         } else
@@ -1247,6 +1335,15 @@ void UserValue::insertDebugValue(Machine
   } while (I != MBB->end());
 }
 
+void UserLabel::insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx,
+                                 LiveIntervals &LIS,
+                                 const TargetInstrInfo &TII) {
+  MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);
+  ++NumInsertedDebugLabels;
+  BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_LABEL))
+      .addMetadata(Label);
+}
+
 void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
                                 const TargetInstrInfo &TII,
                                 const TargetRegisterInfo &TRI,
@@ -1295,16 +1392,31 @@ void UserValue::emitDebugValues(VirtRegM
   }
 }
 
+void UserLabel::emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII) {
+  LLVM_DEBUG(dbgs() << "\t" << loc);
+  MachineFunction::iterator MBB = LIS.getMBBFromIndex(loc)->getIterator();
+
+  LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB));
+  insertDebugLabel(&*MBB, loc, LIS, TII);
+
+  LLVM_DEBUG(dbgs() << '\n');
+}
+
 void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
   LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG VARIABLES **********\n");
   if (!MF)
     return;
   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
   SpillOffsetMap SpillOffsets;
-  for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
-    LLVM_DEBUG(userValues[i]->print(dbgs(), TRI));
-    userValues[i]->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets);
-    userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets);
+  for (auto &userValue : userValues) {
+    LLVM_DEBUG(userValue->print(dbgs(), TRI));
+    userValue->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets);
+    userValue->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets);
+  }
+  LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG LABELS **********\n");
+  for (auto &userLabel : userLabels) {
+    LLVM_DEBUG(userLabel->print(dbgs(), TRI));
+    userLabel->emitDebugLabel(*LIS, *TII);
   }
   EmitDone = true;
 }

Added: llvm/trunk/test/CodeGen/Generic/live-debug-label.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/live-debug-label.ll?rev=351525&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Generic/live-debug-label.ll (added)
+++ llvm/trunk/test/CodeGen/Generic/live-debug-label.ll Thu Jan 17 23:17:09 2019
@@ -0,0 +1,141 @@
+; RUN: llc < %s -stop-after=virtregrewriter -o - | FileCheck %s
+;
+; Generated with "clang++ -g -O1 -S -emit-llvm"
+;
+; inline bool bar(char c) {
+;   return c >= '0' && c <= '9';
+; }
+;
+; unsigned foo(const char* data,
+;              int length,
+;              int* parsing_result) {
+;   unsigned value = 0;
+;   int result = 1;
+;   bool overflow = 0;
+;
+;   while (bar(*data)) {
+;     if (value > 1) {
+;       result = 2;
+;       overflow = 1;
+;     }
+;
+;     if (!overflow)
+;       value = value + 1;
+;   }
+;
+;   if (length == 0 || value) {
+;     if (!overflow)
+;       result = 0;
+;   } else {
+;     result = 1;
+;   }
+; bye:
+;   *parsing_result = result;
+;   return result == 0 ? value : 0;
+; }
+;
+; CHECK: {{^body:}}
+; CHECK: bye.thread21:
+; CHECK: DBG_LABEL !14
+; CHECK: if.then5:
+; CHECK: DBG_LABEL !14
+; CHECK-NOT: DBG_LABEL !14
+
+$_Z3barc = comdat any
+
+; Function Attrs: nounwind uwtable
+define dso_local i32 @_Z3fooPKciPi(i8* nocapture readonly %data, i32 %length, i32* nocapture %parsing_result) local_unnamed_addr !dbg !4 {
+entry:
+  %0 = load i8, i8* %data, align 1
+  %call23 = tail call zeroext i1 @_Z3barc(i8 signext %0), !dbg !15
+  br i1 %call23, label %while.body, label %while.end
+
+while.body:                                       ; preds = %entry, %while.body
+  %overflow.026 = phi i8 [ %spec.select18, %while.body ], [ 0, %entry ]
+  %result.025 = phi i32 [ %spec.select, %while.body ], [ 1, %entry ]
+  %value.024 = phi i32 [ %value.1, %while.body ], [ 0, %entry ]
+  %cmp = icmp ugt i32 %value.024, 1
+  %spec.select = select i1 %cmp, i32 2, i32 %result.025
+  %spec.select18 = select i1 %cmp, i8 1, i8 %overflow.026
+  %1 = and i8 %spec.select18, 1
+  %2 = xor i8 %1, 1
+  %3 = zext i8 %2 to i32
+  %value.1 = add i32 %value.024, %3
+  %4 = load i8, i8* %data, align 1
+  %call = tail call zeroext i1 @_Z3barc(i8 signext %4), !dbg !15
+  br i1 %call, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:                               ; preds = %while.body
+  %phitmp = and i8 %spec.select18, 1
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %entry
+  %value.0.lcssa = phi i32 [ 0, %entry ], [ %value.1, %while.end.loopexit ]
+  %result.0.lcssa = phi i32 [ 1, %entry ], [ %spec.select, %while.end.loopexit ]
+  %overflow.0.lcssa = phi i8 [ 0, %entry ], [ %phitmp, %while.end.loopexit ]
+  %cmp3 = icmp eq i32 %length, 0
+  %tobool4 = icmp ne i32 %value.0.lcssa, 0
+  %or.cond = or i1 %cmp3, %tobool4
+  br i1 %or.cond, label %if.then5, label %bye.thread21
+
+bye.thread21:                                     ; preds = %while.end
+  call void @llvm.dbg.label(metadata !14), !dbg !16
+  store i32 1, i32* %parsing_result, align 4
+  br label %6
+
+if.then5:                                         ; preds = %while.end
+  %tobool6 = icmp eq i8 %overflow.0.lcssa, 0
+  call void @llvm.dbg.label(metadata !14), !dbg !16
+  call void @llvm.dbg.label(metadata !14), !dbg !16
+  br i1 %tobool6, label %bye.thread, label %bye
+
+bye.thread:                                       ; preds = %if.then5
+  store i32 0, i32* %parsing_result, align 4
+  br label %5
+
+bye:                                              ; preds = %if.then5
+  store i32 %result.0.lcssa, i32* %parsing_result, align 4
+  %cmp10 = icmp eq i32 %result.0.lcssa, 0
+  br i1 %cmp10, label %5, label %6
+
+; <label>:5:                                      ; preds = %bye.thread, %bye
+  br label %6
+
+; <label>:6:                                      ; preds = %bye.thread21, %bye, %5
+  %7 = phi i32 [ %value.0.lcssa, %5 ], [ 0, %bye ], [ 0, %bye.thread21 ]
+  ret i32 %7
+}
+
+; Function Attrs: inlinehint nounwind uwtable
+define linkonce_odr dso_local zeroext i1 @_Z3barc(i8 signext %c) local_unnamed_addr comdat {
+entry:
+  %c.off = add i8 %c, -48
+  %0 = icmp ult i8 %c.off, 10
+  ret i1 %0
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.label(metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "live-debug-label.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooPKciPi", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !13)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7, !8, !11, !12}
+!7 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
+!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10)
+!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
+!13 = !{!14}
+!14 = !DILabel(scope: !4, name: "bye", file: !1, line: 28)
+!15 = !DILocation(line: 12, column: 10, scope: !4)
+!16 = !DILocation(line: 28, column: 1, scope: !4)




More information about the llvm-commits mailing list