@@ -2075,7 +2075,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20752075 bool PrevInstInSameSection =
20762076 (!PrevInstBB ||
20772077 PrevInstBB->getSectionID () == MI->getParent ()->getSectionID ());
2078- if (DL == PrevInstLoc && PrevInstInSameSection) {
2078+ bool ForceIsStmt = ForceIsStmtInstrs.contains (MI);
2079+ if (DL == PrevInstLoc && PrevInstInSameSection && !ForceIsStmt) {
20792080 // If we have an ongoing unspecified location, nothing to do here.
20802081 if (!DL)
20812082 return ;
@@ -2132,7 +2133,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
21322133 // If the line changed, we call that a new statement; unless we went to
21332134 // line 0 and came back, in which case it is not a new statement.
21342135 unsigned OldLine = PrevInstLoc ? PrevInstLoc.getLine () : LastAsmLine;
2135- if (DL.getLine () && DL.getLine () != OldLine)
2136+ if (DL.getLine () && ( DL.getLine () != OldLine || ForceIsStmt) )
21362137 Flags |= DWARF2_FLAG_IS_STMT;
21372138
21382139 const MDNode *Scope = DL.getScope ();
@@ -2308,6 +2309,143 @@ DwarfDebug::emitInitialLocDirective(const MachineFunction &MF, unsigned CUID) {
23082309 return PrologEndLoc;
23092310}
23102311
2312+ // / For the function \p MF, finds the set of instructions which may represent a
2313+ // / change in line number from one or more of the preceding MBBs. Stores the
2314+ // / resulting set of instructions, which should have is_stmt set, in
2315+ // / ForceIsStmtInstrs.
2316+ void DwarfDebug::findForceIsStmtInstrs (const MachineFunction *MF) {
2317+ ForceIsStmtInstrs.clear ();
2318+
2319+ // For this function, we try to find MBBs where the last source line in every
2320+ // block predecessor matches the first line seen in the block itself; for
2321+ // every such MBB, we set is_stmt=false on the first line in the block, and
2322+ // for every other block we set is_stmt=true on the first line.
2323+ // For example, if we have the block %bb.3, which has 2 predecesors %bb.1 and
2324+ // %bb.2:
2325+ // bb.1:
2326+ // $r3 = MOV64ri 12, debug-location !DILocation(line: 4)
2327+ // JMP %bb.3, debug-location !DILocation(line: 5)
2328+ // bb.2:
2329+ // $r3 = MOV64ri 24, debug-location !DILocation(line: 5)
2330+ // JMP %bb.3
2331+ // bb.3:
2332+ // $r2 = MOV64ri 1
2333+ // $r1 = ADD $r2, $r3, debug-location !DILocation(line: 5)
2334+ // When we examine %bb.3, we first check to see if it contains any
2335+ // instructions with debug locations, and select the first such instruction;
2336+ // in this case, the ADD, with line=5. We then examine both of its
2337+ // predecessors to see what the last debug-location in them is. For each
2338+ // predecessor, if they do not contain any debug-locations, or if the last
2339+ // debug-location before jumping to %bb.3 does not have line=5, then the ADD
2340+ // in %bb.3 must use IsStmt. In this case, all predecessors have a
2341+ // debug-location with line=5 as the last debug-location before jumping to
2342+ // %bb.3, so we do not set is_stmt for the ADD instruction - we know that
2343+ // whichever MBB we have arrived from, the line has not changed.
2344+
2345+ const auto *TII = MF->getSubtarget ().getInstrInfo ();
2346+
2347+ // We only need to the predecessors of MBBs that could have is_stmt set by
2348+ // this logic.
2349+ SmallDenseSet<MachineBasicBlock *, 4 > PredMBBsToExamine;
2350+ SmallDenseMap<MachineBasicBlock *, MachineInstr *> PotentialIsStmtMBBInstrs;
2351+ // We use const_cast even though we won't actually modify MF, because some
2352+ // methods we need take a non-const MBB.
2353+ for (auto &MBB : *const_cast <MachineFunction *>(MF)) {
2354+ if (MBB.empty () || MBB.pred_empty ())
2355+ continue ;
2356+ for (auto &MI : MBB) {
2357+ if (MI.getDebugLoc () && MI.getDebugLoc ()->getLine ()) {
2358+ for (auto *Pred : MBB.predecessors ())
2359+ PredMBBsToExamine.insert (Pred);
2360+ PotentialIsStmtMBBInstrs.insert ({&MBB, &MI});
2361+ break ;
2362+ }
2363+ }
2364+ }
2365+
2366+ // For each predecessor MBB, we examine the last line seen before each branch
2367+ // or logical fallthrough. We use analyzeBranch to handle cases where
2368+ // different branches have different outgoing lines (i.e. if there are
2369+ // multiple branches that each have their own source location); otherwise we
2370+ // just use the last line in the block.
2371+ for (auto *MBB : PredMBBsToExamine) {
2372+ auto CheckMBBEdge = [&](MachineBasicBlock *Succ, unsigned OutgoingLine) {
2373+ auto MBBInstrIt = PotentialIsStmtMBBInstrs.find (Succ);
2374+ if (MBBInstrIt == PotentialIsStmtMBBInstrs.end ())
2375+ return ;
2376+ MachineInstr *MI = MBBInstrIt->second ;
2377+ if (MI->getDebugLoc ()->getLine () == OutgoingLine)
2378+ return ;
2379+ PotentialIsStmtMBBInstrs.erase (MBBInstrIt);
2380+ ForceIsStmtInstrs.insert (MI);
2381+ };
2382+ // If this block is empty, we conservatively assume that its fallthrough
2383+ // successor needs is_stmt; we could check MBB's predecessors to see if it
2384+ // has a consistent entry line, but this seems unlikely to be worthwhile.
2385+ if (MBB->empty ()) {
2386+ for (auto *Succ : MBB->successors ())
2387+ CheckMBBEdge (Succ, 0 );
2388+ continue ;
2389+ }
2390+ // If MBB has no successors that are in the "potential" set, due to one or
2391+ // more of them having confirmed is_stmt, we can skip this check early.
2392+ if (none_of (MBB->successors (), [&](auto *SuccMBB) {
2393+ return PotentialIsStmtMBBInstrs.contains (SuccMBB);
2394+ }))
2395+ continue ;
2396+ // If we can't determine what DLs this branch's successors use, just treat
2397+ // all the successors as coming from the last DebugLoc.
2398+ SmallVector<MachineBasicBlock *, 2 > SuccessorBBs;
2399+ auto MIIt = MBB->rbegin ();
2400+ {
2401+ MachineBasicBlock *TBB = nullptr , *FBB = nullptr ;
2402+ SmallVector<MachineOperand, 4 > Cond;
2403+ bool AnalyzeFailed = TII->analyzeBranch (*MBB, TBB, FBB, Cond);
2404+ // For a conditional branch followed by unconditional branch where the
2405+ // unconditional branch has a DebugLoc, that loc is the outgoing loc to
2406+ // the the false destination only; otherwise, both destinations share an
2407+ // outgoing loc.
2408+ if (!AnalyzeFailed && !Cond.empty () && FBB != nullptr &&
2409+ MBB->back ().getDebugLoc () && MBB->back ().getDebugLoc ()->getLine ()) {
2410+ unsigned FBBLine = MBB->back ().getDebugLoc ()->getLine ();
2411+ assert (MIIt->isBranch () && " Bad result from analyzeBranch?" );
2412+ CheckMBBEdge (FBB, FBBLine);
2413+ ++MIIt;
2414+ SuccessorBBs.push_back (TBB);
2415+ } else {
2416+ // For all other cases, all successors share the last outgoing DebugLoc.
2417+ SuccessorBBs.assign (MBB->succ_begin (), MBB->succ_end ());
2418+ }
2419+ }
2420+
2421+ // If we don't find an outgoing loc, this block will start with a line 0.
2422+ // It is possible that we have a block that has no DebugLoc, but acts as a
2423+ // simple passthrough between two blocks that end and start with the same
2424+ // line, e.g.:
2425+ // bb.1:
2426+ // JMP %bb.2, debug-location !10
2427+ // bb.2:
2428+ // JMP %bb.3
2429+ // bb.3:
2430+ // $r1 = ADD $r2, $r3, debug-location !10
2431+ // If these blocks were merged into a single block, we would not attach
2432+ // is_stmt to the ADD, but with this logic that only checks the immediate
2433+ // predecessor, we will; we make this tradeoff because doing a full dataflow
2434+ // analysis would be expensive, and these situations are probably not common
2435+ // enough for this to be worthwhile.
2436+ unsigned LastLine = 0 ;
2437+ while (MIIt != MBB->rend ()) {
2438+ if (auto DL = MIIt->getDebugLoc (); DL && DL->getLine ()) {
2439+ LastLine = DL->getLine ();
2440+ break ;
2441+ }
2442+ ++MIIt;
2443+ }
2444+ for (auto *Succ : SuccessorBBs)
2445+ CheckMBBEdge (Succ, LastLine);
2446+ }
2447+ }
2448+
23112449// Gather pre-function debug information. Assumes being called immediately
23122450// after the function entry point has been emitted.
23132451void DwarfDebug::beginFunctionImpl (const MachineFunction *MF) {
@@ -2326,6 +2464,8 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
23262464 // Record beginning of function.
23272465 PrologEndLoc = emitInitialLocDirective (
23282466 *MF, Asm->OutStreamer ->getContext ().getDwarfCompileUnitID ());
2467+
2468+ findForceIsStmtInstrs (MF);
23292469}
23302470
23312471unsigned
0 commit comments