Index: lib/CodeGen/LiveDebugVariables.cpp =================================================================== --- lib/CodeGen/LiveDebugVariables.cpp +++ lib/CodeGen/LiveDebugVariables.cpp @@ -71,6 +71,7 @@ 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; @@ -334,6 +335,37 @@ void print(raw_ostream &, const TargetRegisterInfo *); }; +/// UserLabel - 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. + + /// insertDebugLabel - Insert a DBG_LABEL into MBB at Idx. + void insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS, const TargetInstrInfo &TII); + +public: + /// UserLabel - Create a new UserLabel. + UserLabel(const DILabel *label, DebugLoc L, SlotIndex Idx) + : Label(label), dl(std::move(L)), loc(Idx) {} + + /// match - 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; + } + + /// emitDebugLabels - Recreate DBG_LABEL instruction from data structures. + void emitDebugLabels(LiveIntervals &LIS, const TargetInstrInfo &TII); + + /// getDebugLoc - Return DebugLoc of this UserLabel. + DebugLoc getDebugLoc() { return dl; } + + void print(raw_ostream &, const TargetRegisterInfo *); +}; + /// LDVImpl - Implementation of the LiveDebugVariables pass. class LDVImpl { LiveDebugVariables &pass; @@ -351,6 +383,9 @@ /// userValues - All allocated UserValue instances. SmallVector, 8> userValues; + /// userLabels - All allocated UserLabel instances. + SmallVector, 2> userLabels; + /// Map virtual register to eq class leader. using VRMap = DenseMap; VRMap virtRegToEqClass; @@ -363,6 +398,10 @@ UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr, const DebugLoc &DL); + /// getUserLabel - Find or create a UserLabel. + UserLabel *getUserLabel(const DILabel *Label, const DebugLoc &DL, + const SlotIndex Idx); + /// lookupVirtReg - Find the EC leader for VirtReg or null. UserValue *lookupVirtReg(unsigned VirtReg); @@ -372,6 +411,12 @@ /// @return True if the DBG_VALUE instruction should be deleted. bool handleDebugValue(MachineInstr &MI, SlotIndex Idx); + /// handleDebugLabel - Add DBG_LABEL instruction to UserLabel. + /// @param MI DBG_LABEL instruction + /// @param Idx Last valid SlotIndex before instruction. + /// @return True if the DBG_LABEL instruction should be deleted. + bool handleDebugLabel(MachineInstr &MI, SlotIndex Idx); + /// collectDebugValues - Collect and erase all DBG_VALUE instructions, adding /// a UserValue def for each instruction. /// @param mf MachineFunction to be scanned. @@ -391,6 +436,7 @@ void clear() { MF = nullptr; userValues.clear(); + userLabels.clear(); virtRegToEqClass.clear(); userVarMap.clear(); // Make sure we call emitDebugValues if the machine function was modified. @@ -474,10 +520,38 @@ OS << '\n'; } +static void printLabelName(raw_ostream &OS, const DILabel *L, + const DILocation *DL) { + const LLVMContext &Ctx = L->getContext(); + StringRef Res = L->getName(); + if (!Res.empty()) + OS << Res << "," << L->getLine(); + if (auto *InlinedAt = DL->getInlinedAt()) { + if (DebugLoc InlinedAtDL = InlinedAt) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} + +void UserLabel::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { + auto *DL = cast(Label); + OS << "!\""; + printLabelName(OS, DL, 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); + OS << "********** DEBUG LABELS **********\n"; + for (unsigned i = 0, e = userLabels.size(); i != e; ++i) + userLabels[i]->print(OS, TRI); } #endif @@ -506,6 +580,18 @@ return UV; } +UserLabel *LDVImpl::getUserLabel(const DILabel *Label, const DebugLoc &DL, + const SlotIndex Idx) { + for (auto const &L : userLabels) { + if (L->match(Label, DL->getInlinedAt(), Idx)) + return L.get(); + } + + userLabels.push_back(llvm::make_unique(Label, DL, Idx)); + UserLabel *UL = userLabels.back().get(); + return UL; +} + void LDVImpl::mapVirtReg(unsigned VirtReg, UserValue *EC) { assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && "Only map VirtRegs"); UserValue *&Leader = virtRegToEqClass[VirtReg]; @@ -578,6 +664,19 @@ 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(); + getUserLabel(Label, MI.getDebugLoc(), Idx); + return true; +} + bool LDVImpl::collectDebugValues(MachineFunction &mf) { bool Changed = false; for (MachineFunction::iterator MFI = mf.begin(), MFE = mf.end(); MFI != MFE; @@ -601,7 +700,8 @@ 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 @@ -1240,6 +1340,15 @@ } 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, @@ -1288,6 +1397,17 @@ } } +void UserLabel::emitDebugLabels(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) @@ -1299,6 +1419,11 @@ userValues[i]->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets); userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets); } + LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG LABELS **********\n"); + for (unsigned i = 0, e = userLabels.size(); i != e; ++i) { + LLVM_DEBUG(userLabels[i]->print(dbgs(), TRI)); + userLabels[i]->emitDebugLabels(*LIS, *TII); + } EmitDone = true; } Index: test/CodeGen/Generic/live-debug-label.ll =================================================================== --- /dev/null +++ test/CodeGen/Generic/live-debug-label.ll @@ -0,0 +1,107 @@ +; RUN: llc < %s -stop-after=virtregrewriter -o - | FileCheck %s +; +; CHECK-LABEL: {{^body:}} +; CHECK-LABEL: bye.thread21: +; CHECK: DBG_LABEL !14 +; CHECK-LABEL: 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 + +;