xref: /src/contrib/llvm-project/llvm/lib/CodeGen/LexicalScopes.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
130815c53SDimitry Andric //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
230815c53SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630815c53SDimitry Andric //
730815c53SDimitry Andric //===----------------------------------------------------------------------===//
830815c53SDimitry Andric //
930815c53SDimitry Andric // This file implements LexicalScopes analysis.
1030815c53SDimitry Andric //
1130815c53SDimitry Andric // This pass collects lexical scope information and maps machine instructions
1230815c53SDimitry Andric // to respective lexical scopes.
1330815c53SDimitry Andric //
1430815c53SDimitry Andric //===----------------------------------------------------------------------===//
1530815c53SDimitry Andric 
167ab83427SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h"
1771d5a254SDimitry Andric #include "llvm/ADT/DenseMap.h"
1871d5a254SDimitry Andric #include "llvm/ADT/SmallVector.h"
1971d5a254SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
2030815c53SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
2130815c53SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
22eb11fae6SDimitry Andric #include "llvm/Config/llvm-config.h"
2371d5a254SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
241d5ae102SDimitry Andric #include "llvm/IR/Function.h"
2571d5a254SDimitry Andric #include "llvm/IR/Metadata.h"
2671d5a254SDimitry Andric #include "llvm/Support/Casting.h"
2771d5a254SDimitry Andric #include "llvm/Support/Compiler.h"
2830815c53SDimitry Andric #include "llvm/Support/Debug.h"
2971d5a254SDimitry Andric #include "llvm/Support/raw_ostream.h"
3071d5a254SDimitry Andric #include <cassert>
3171d5a254SDimitry Andric #include <string>
3271d5a254SDimitry Andric #include <tuple>
3371d5a254SDimitry Andric #include <utility>
3471d5a254SDimitry Andric 
3530815c53SDimitry Andric using namespace llvm;
3630815c53SDimitry Andric 
375ca98fd9SDimitry Andric #define DEBUG_TYPE "lexicalscopes"
3830815c53SDimitry Andric 
395ca98fd9SDimitry Andric /// reset - Reset the instance so that it's prepared for another function.
reset()405ca98fd9SDimitry Andric void LexicalScopes::reset() {
415ca98fd9SDimitry Andric   MF = nullptr;
425ca98fd9SDimitry Andric   CurrentFnLexicalScope = nullptr;
435ca98fd9SDimitry Andric   LexicalScopeMap.clear();
445ca98fd9SDimitry Andric   AbstractScopeMap.clear();
4530815c53SDimitry Andric   InlinedLexicalScopeMap.clear();
4630815c53SDimitry Andric   AbstractScopesList.clear();
47cfca06d7SDimitry Andric   DominatedBlocks.clear();
4830815c53SDimitry Andric }
4930815c53SDimitry Andric 
5030815c53SDimitry Andric /// initialize - Scan machine function and constuct lexical scope nest.
initialize(const MachineFunction & Fn)5130815c53SDimitry Andric void LexicalScopes::initialize(const MachineFunction &Fn) {
52044eb2f6SDimitry Andric   reset();
5371d5a254SDimitry Andric   // Don't attempt any lexical scope creation for a NoDebug compile unit.
54044eb2f6SDimitry Andric   if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
5571d5a254SDimitry Andric       DICompileUnit::NoDebug)
5671d5a254SDimitry Andric     return;
5730815c53SDimitry Andric   MF = &Fn;
5830815c53SDimitry Andric   SmallVector<InsnRange, 4> MIRanges;
5930815c53SDimitry Andric   DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
6030815c53SDimitry Andric   extractLexicalScopes(MIRanges, MI2ScopeMap);
6130815c53SDimitry Andric   if (CurrentFnLexicalScope) {
6230815c53SDimitry Andric     constructScopeNest(CurrentFnLexicalScope);
6330815c53SDimitry Andric     assignInstructionRanges(MIRanges, MI2ScopeMap);
6430815c53SDimitry Andric   }
6530815c53SDimitry Andric }
6630815c53SDimitry Andric 
6730815c53SDimitry Andric /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
6830815c53SDimitry Andric /// for the given machine function.
extractLexicalScopes(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)695ca98fd9SDimitry Andric void LexicalScopes::extractLexicalScopes(
705ca98fd9SDimitry Andric     SmallVectorImpl<InsnRange> &MIRanges,
7130815c53SDimitry Andric     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
7230815c53SDimitry Andric   // Scan each instruction and create scopes. First build working set of scopes.
735ca98fd9SDimitry Andric   for (const auto &MBB : *MF) {
745ca98fd9SDimitry Andric     const MachineInstr *RangeBeginMI = nullptr;
755ca98fd9SDimitry Andric     const MachineInstr *PrevMI = nullptr;
765a5ac124SDimitry Andric     const DILocation *PrevDL = nullptr;
775ca98fd9SDimitry Andric     for (const auto &MInsn : MBB) {
78344a3780SDimitry Andric       // Ignore DBG_VALUE and similar instruction that do not contribute to any
79344a3780SDimitry Andric       // instruction in the output.
80344a3780SDimitry Andric       if (MInsn.isMetaInstruction())
81344a3780SDimitry Andric         continue;
82344a3780SDimitry Andric 
8330815c53SDimitry Andric       // Check if instruction has valid location information.
845a5ac124SDimitry Andric       const DILocation *MIDL = MInsn.getDebugLoc();
855a5ac124SDimitry Andric       if (!MIDL) {
865ca98fd9SDimitry Andric         PrevMI = &MInsn;
8730815c53SDimitry Andric         continue;
8830815c53SDimitry Andric       }
8930815c53SDimitry Andric 
9030815c53SDimitry Andric       // If scope has not changed then skip this instruction.
9130815c53SDimitry Andric       if (MIDL == PrevDL) {
925ca98fd9SDimitry Andric         PrevMI = &MInsn;
9330815c53SDimitry Andric         continue;
9430815c53SDimitry Andric       }
9530815c53SDimitry Andric 
9630815c53SDimitry Andric       if (RangeBeginMI) {
9730815c53SDimitry Andric         // If we have already seen a beginning of an instruction range and
9830815c53SDimitry Andric         // current instruction scope does not match scope of first instruction
9930815c53SDimitry Andric         // in this range then create a new instruction range.
10030815c53SDimitry Andric         InsnRange R(RangeBeginMI, PrevMI);
10130815c53SDimitry Andric         MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
10230815c53SDimitry Andric         MIRanges.push_back(R);
10330815c53SDimitry Andric       }
10430815c53SDimitry Andric 
10530815c53SDimitry Andric       // This is a beginning of a new instruction range.
1065ca98fd9SDimitry Andric       RangeBeginMI = &MInsn;
10730815c53SDimitry Andric 
10830815c53SDimitry Andric       // Reset previous markers.
1095ca98fd9SDimitry Andric       PrevMI = &MInsn;
11030815c53SDimitry Andric       PrevDL = MIDL;
11130815c53SDimitry Andric     }
11230815c53SDimitry Andric 
11330815c53SDimitry Andric     // Create last instruction range.
1145a5ac124SDimitry Andric     if (RangeBeginMI && PrevMI && PrevDL) {
11530815c53SDimitry Andric       InsnRange R(RangeBeginMI, PrevMI);
11630815c53SDimitry Andric       MIRanges.push_back(R);
11730815c53SDimitry Andric       MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
11830815c53SDimitry Andric     }
11930815c53SDimitry Andric   }
12030815c53SDimitry Andric }
12130815c53SDimitry Andric 
12230815c53SDimitry Andric /// findLexicalScope - Find lexical scope, either regular or inlined, for the
12330815c53SDimitry Andric /// given DebugLoc. Return NULL if not found.
findLexicalScope(const DILocation * DL)1245a5ac124SDimitry Andric LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
1255a5ac124SDimitry Andric   DILocalScope *Scope = DL->getScope();
1265ca98fd9SDimitry Andric   if (!Scope)
1275ca98fd9SDimitry Andric     return nullptr;
12830815c53SDimitry Andric 
12930815c53SDimitry Andric   // The scope that we were created with could have an extra file - which
13030815c53SDimitry Andric   // isn't what we care about in this case.
13101095a5dSDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
13230815c53SDimitry Andric 
1335a5ac124SDimitry Andric   if (auto *IA = DL->getInlinedAt()) {
1345ca98fd9SDimitry Andric     auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
1355ca98fd9SDimitry Andric     return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
1365ca98fd9SDimitry Andric   }
1375ca98fd9SDimitry Andric   return findLexicalScope(Scope);
13830815c53SDimitry Andric }
13930815c53SDimitry Andric 
14030815c53SDimitry Andric /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
14130815c53SDimitry Andric /// not available then create new lexical scope.
getOrCreateLexicalScope(const DILocalScope * Scope,const DILocation * IA)1425a5ac124SDimitry Andric LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
1435a5ac124SDimitry Andric                                                      const DILocation *IA) {
1445a5ac124SDimitry Andric   if (IA) {
14571d5a254SDimitry Andric     // Skip scopes inlined from a NoDebug compile unit.
14671d5a254SDimitry Andric     if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
14771d5a254SDimitry Andric         DICompileUnit::NoDebug)
14871d5a254SDimitry Andric       return getOrCreateLexicalScope(IA);
14930815c53SDimitry Andric     // Create an abstract scope for inlined function.
15030815c53SDimitry Andric     getOrCreateAbstractScope(Scope);
15130815c53SDimitry Andric     // Create an inlined scope for inlined function.
1525a5ac124SDimitry Andric     return getOrCreateInlinedScope(Scope, IA);
15330815c53SDimitry Andric   }
15430815c53SDimitry Andric 
15530815c53SDimitry Andric   return getOrCreateRegularScope(Scope);
15630815c53SDimitry Andric }
15730815c53SDimitry Andric 
15830815c53SDimitry Andric /// getOrCreateRegularScope - Find or create a regular lexical scope.
1595a5ac124SDimitry Andric LexicalScope *
getOrCreateRegularScope(const DILocalScope * Scope)1605a5ac124SDimitry Andric LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
16101095a5dSDimitry Andric   assert(Scope && "Invalid Scope encoding!");
16201095a5dSDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
16330815c53SDimitry Andric 
1645ca98fd9SDimitry Andric   auto I = LexicalScopeMap.find(Scope);
1655ca98fd9SDimitry Andric   if (I != LexicalScopeMap.end())
1665ca98fd9SDimitry Andric     return &I->second;
16730815c53SDimitry Andric 
1685a5ac124SDimitry Andric   // FIXME: Should the following dyn_cast be DILexicalBlock?
1695ca98fd9SDimitry Andric   LexicalScope *Parent = nullptr;
1705a5ac124SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
1715a5ac124SDimitry Andric     Parent = getOrCreateLexicalScope(Block->getScope());
1725a5ac124SDimitry Andric   I = LexicalScopeMap.emplace(std::piecewise_construct,
1735a5ac124SDimitry Andric                               std::forward_as_tuple(Scope),
1745a5ac124SDimitry Andric                               std::forward_as_tuple(Parent, Scope, nullptr,
1755a5ac124SDimitry Andric                                                     false)).first;
17630815c53SDimitry Andric 
17767c32a98SDimitry Andric   if (!Parent) {
178044eb2f6SDimitry Andric     assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
17967c32a98SDimitry Andric     assert(!CurrentFnLexicalScope);
1805ca98fd9SDimitry Andric     CurrentFnLexicalScope = &I->second;
18167c32a98SDimitry Andric   }
1825ca98fd9SDimitry Andric 
1835ca98fd9SDimitry Andric   return &I->second;
18430815c53SDimitry Andric }
18530815c53SDimitry Andric 
18630815c53SDimitry Andric /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
1875a5ac124SDimitry Andric LexicalScope *
getOrCreateInlinedScope(const DILocalScope * Scope,const DILocation * InlinedAt)1885a5ac124SDimitry Andric LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
1895a5ac124SDimitry Andric                                        const DILocation *InlinedAt) {
19001095a5dSDimitry Andric   assert(Scope && "Invalid Scope encoding!");
19101095a5dSDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
1925a5ac124SDimitry Andric   std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
1935ca98fd9SDimitry Andric   auto I = InlinedLexicalScopeMap.find(P);
1945ca98fd9SDimitry Andric   if (I != InlinedLexicalScopeMap.end())
1955ca98fd9SDimitry Andric     return &I->second;
19630815c53SDimitry Andric 
1975ca98fd9SDimitry Andric   LexicalScope *Parent;
1985a5ac124SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
1995a5ac124SDimitry Andric     Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
2005ca98fd9SDimitry Andric   else
2015a5ac124SDimitry Andric     Parent = getOrCreateLexicalScope(InlinedAt);
2025ca98fd9SDimitry Andric 
20371d5a254SDimitry Andric   I = InlinedLexicalScopeMap
20471d5a254SDimitry Andric           .emplace(std::piecewise_construct, std::forward_as_tuple(P),
20571d5a254SDimitry Andric                    std::forward_as_tuple(Parent, Scope, InlinedAt, false))
2065a5ac124SDimitry Andric           .first;
2075ca98fd9SDimitry Andric   return &I->second;
20830815c53SDimitry Andric }
20930815c53SDimitry Andric 
21030815c53SDimitry Andric /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
2115a5ac124SDimitry Andric LexicalScope *
getOrCreateAbstractScope(const DILocalScope * Scope)2125a5ac124SDimitry Andric LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
2135a5ac124SDimitry Andric   assert(Scope && "Invalid Scope encoding!");
21401095a5dSDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
2155ca98fd9SDimitry Andric   auto I = AbstractScopeMap.find(Scope);
2165ca98fd9SDimitry Andric   if (I != AbstractScopeMap.end())
2175ca98fd9SDimitry Andric     return &I->second;
21830815c53SDimitry Andric 
2195a5ac124SDimitry Andric   // FIXME: Should the following isa be DILexicalBlock?
2205ca98fd9SDimitry Andric   LexicalScope *Parent = nullptr;
2215a5ac124SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
2225a5ac124SDimitry Andric     Parent = getOrCreateAbstractScope(Block->getScope());
2235a5ac124SDimitry Andric 
2245ca98fd9SDimitry Andric   I = AbstractScopeMap.emplace(std::piecewise_construct,
2255ca98fd9SDimitry Andric                                std::forward_as_tuple(Scope),
2265ca98fd9SDimitry Andric                                std::forward_as_tuple(Parent, Scope,
2275ca98fd9SDimitry Andric                                                      nullptr, true)).first;
2285a5ac124SDimitry Andric   if (isa<DISubprogram>(Scope))
2295ca98fd9SDimitry Andric     AbstractScopesList.push_back(&I->second);
2305ca98fd9SDimitry Andric   return &I->second;
23130815c53SDimitry Andric }
23230815c53SDimitry Andric 
233cfca06d7SDimitry Andric /// constructScopeNest - Traverse the Scope tree depth-first, storing
234cfca06d7SDimitry Andric /// traversal state in WorkStack and recording the depth-first
235cfca06d7SDimitry Andric /// numbering (setDFSIn, setDFSOut) for edge classification.
constructScopeNest(LexicalScope * Scope)23630815c53SDimitry Andric void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
23730815c53SDimitry Andric   assert(Scope && "Unable to calculate scope dominance graph!");
238cfca06d7SDimitry Andric   SmallVector<std::pair<LexicalScope *, size_t>, 4> WorkStack;
239cfca06d7SDimitry Andric   WorkStack.push_back(std::make_pair(Scope, 0));
24030815c53SDimitry Andric   unsigned Counter = 0;
24130815c53SDimitry Andric   while (!WorkStack.empty()) {
242cfca06d7SDimitry Andric     auto &ScopePosition = WorkStack.back();
243cfca06d7SDimitry Andric     LexicalScope *WS = ScopePosition.first;
244cfca06d7SDimitry Andric     size_t ChildNum = ScopePosition.second++;
245f8af5cf6SDimitry Andric     const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
246cfca06d7SDimitry Andric     if (ChildNum < Children.size()) {
247cfca06d7SDimitry Andric       auto &ChildScope = Children[ChildNum];
248cfca06d7SDimitry Andric       WorkStack.push_back(std::make_pair(ChildScope, 0));
24930815c53SDimitry Andric       ChildScope->setDFSIn(++Counter);
250cfca06d7SDimitry Andric     } else {
25130815c53SDimitry Andric       WorkStack.pop_back();
25230815c53SDimitry Andric       WS->setDFSOut(++Counter);
25330815c53SDimitry Andric     }
25430815c53SDimitry Andric   }
25530815c53SDimitry Andric }
25630815c53SDimitry Andric 
25730815c53SDimitry Andric /// assignInstructionRanges - Find ranges of instructions covered by each
25830815c53SDimitry Andric /// lexical scope.
assignInstructionRanges(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)2595ca98fd9SDimitry Andric void LexicalScopes::assignInstructionRanges(
2605ca98fd9SDimitry Andric     SmallVectorImpl<InsnRange> &MIRanges,
2615ca98fd9SDimitry Andric     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
2625ca98fd9SDimitry Andric   LexicalScope *PrevLexicalScope = nullptr;
263b915e9e0SDimitry Andric   for (const auto &R : MIRanges) {
26430815c53SDimitry Andric     LexicalScope *S = MI2ScopeMap.lookup(R.first);
26530815c53SDimitry Andric     assert(S && "Lost LexicalScope for a machine instruction!");
26630815c53SDimitry Andric     if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
26730815c53SDimitry Andric       PrevLexicalScope->closeInsnRange(S);
26830815c53SDimitry Andric     S->openInsnRange(R.first);
26930815c53SDimitry Andric     S->extendInsnRange(R.second);
27030815c53SDimitry Andric     PrevLexicalScope = S;
27130815c53SDimitry Andric   }
27230815c53SDimitry Andric 
27330815c53SDimitry Andric   if (PrevLexicalScope)
27430815c53SDimitry Andric     PrevLexicalScope->closeInsnRange();
27530815c53SDimitry Andric }
27630815c53SDimitry Andric 
27730815c53SDimitry Andric /// getMachineBasicBlocks - Populate given set using machine basic blocks which
27830815c53SDimitry Andric /// have machine instructions that belong to lexical scope identified by
27930815c53SDimitry Andric /// DebugLoc.
getMachineBasicBlocks(const DILocation * DL,SmallPtrSetImpl<const MachineBasicBlock * > & MBBs)2805ca98fd9SDimitry Andric void LexicalScopes::getMachineBasicBlocks(
2815a5ac124SDimitry Andric     const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
282044eb2f6SDimitry Andric   assert(MF && "Method called on a uninitialized LexicalScopes object!");
28330815c53SDimitry Andric   MBBs.clear();
284044eb2f6SDimitry Andric 
28530815c53SDimitry Andric   LexicalScope *Scope = getOrCreateLexicalScope(DL);
28630815c53SDimitry Andric   if (!Scope)
28730815c53SDimitry Andric     return;
28830815c53SDimitry Andric 
28930815c53SDimitry Andric   if (Scope == CurrentFnLexicalScope) {
2905ca98fd9SDimitry Andric     for (const auto &MBB : *MF)
2915ca98fd9SDimitry Andric       MBBs.insert(&MBB);
29230815c53SDimitry Andric     return;
29330815c53SDimitry Andric   }
29430815c53SDimitry Andric 
295cfca06d7SDimitry Andric   // The scope ranges can cover multiple basic blocks in each span. Iterate over
296cfca06d7SDimitry Andric   // all blocks (in the order they are in the function) until we reach the one
297cfca06d7SDimitry Andric   // containing the end of the span.
298f8af5cf6SDimitry Andric   SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
299b915e9e0SDimitry Andric   for (auto &R : InsnRanges)
300cfca06d7SDimitry Andric     for (auto CurMBBIt = R.first->getParent()->getIterator(),
301cfca06d7SDimitry Andric               EndBBIt = std::next(R.second->getParent()->getIterator());
302cfca06d7SDimitry Andric          CurMBBIt != EndBBIt; CurMBBIt++)
303cfca06d7SDimitry Andric       MBBs.insert(&*CurMBBIt);
30430815c53SDimitry Andric }
30530815c53SDimitry Andric 
dominates(const DILocation * DL,MachineBasicBlock * MBB)3065a5ac124SDimitry Andric bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
307044eb2f6SDimitry Andric   assert(MF && "Unexpected uninitialized LexicalScopes object!");
30830815c53SDimitry Andric   LexicalScope *Scope = getOrCreateLexicalScope(DL);
30930815c53SDimitry Andric   if (!Scope)
31030815c53SDimitry Andric     return false;
31130815c53SDimitry Andric 
31230815c53SDimitry Andric   // Current function scope covers all basic blocks in the function.
31330815c53SDimitry Andric   if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
31430815c53SDimitry Andric     return true;
31530815c53SDimitry Andric 
316cfca06d7SDimitry Andric   // Fetch all the blocks in DLs scope. Because the range / block list also
317cfca06d7SDimitry Andric   // contain any subscopes, any instruction that DL dominates can be found in
318cfca06d7SDimitry Andric   // the block set.
319cfca06d7SDimitry Andric   //
320cfca06d7SDimitry Andric   // Cache the set of fetched blocks to avoid repeatedly recomputing the set in
321cfca06d7SDimitry Andric   // the LiveDebugValues pass.
322cfca06d7SDimitry Andric   std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL];
323cfca06d7SDimitry Andric   if (!Set) {
324cfca06d7SDimitry Andric     Set = std::make_unique<BlockSetT>();
325cfca06d7SDimitry Andric     getMachineBasicBlocks(DL, *Set);
32630815c53SDimitry Andric   }
327b60736ecSDimitry Andric   return Set->contains(MBB);
32830815c53SDimitry Andric }
32930815c53SDimitry Andric 
33071d5a254SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump(unsigned Indent) const33171d5a254SDimitry Andric LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
33230815c53SDimitry Andric   raw_ostream &err = dbgs();
3334a16efa3SDimitry Andric   err.indent(Indent);
33430815c53SDimitry Andric   err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
33530815c53SDimitry Andric   const MDNode *N = Desc;
3364a16efa3SDimitry Andric   err.indent(Indent);
33730815c53SDimitry Andric   N->dump();
33830815c53SDimitry Andric   if (AbstractScope)
3394a16efa3SDimitry Andric     err << std::string(Indent, ' ') << "Abstract Scope\n";
34030815c53SDimitry Andric 
34130815c53SDimitry Andric   if (!Children.empty())
3424a16efa3SDimitry Andric     err << std::string(Indent + 2, ' ') << "Children ...\n";
343ac9a064cSDimitry Andric   for (const LexicalScope *Child : Children)
344ac9a064cSDimitry Andric     if (Child != this)
345ac9a064cSDimitry Andric       Child->dump(Indent + 2);
34630815c53SDimitry Andric }
34771d5a254SDimitry Andric #endif
348