22#include "llvm/Config/llvm-config.h"
37#define DEBUG_TYPE "lexicalscopes"
42 CurrentFnLexicalScope =
nullptr;
43 LexicalScopeMap.clear();
44 AbstractScopeMap.clear();
45 InlinedLexicalScopeMap.clear();
46 AbstractScopesList.clear();
47 DominatedBlocks.clear();
60 extractLexicalScopes(MIRanges, MI2ScopeMap);
61 if (CurrentFnLexicalScope) {
62 constructScopeNest(CurrentFnLexicalScope);
63 assignInstructionRanges(MIRanges, MI2ScopeMap);
69void LexicalScopes::extractLexicalScopes(
73 for (
const auto &
MBB : *MF) {
77 for (
const auto &MInsn :
MBB) {
80 if (MInsn.isMetaInstruction())
101 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
106 RangeBeginMI = &MInsn;
114 if (RangeBeginMI && PrevMI && PrevDL) {
117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
131 Scope = Scope->getNonLexicalBlockFileScope();
133 if (
auto *IA =
DL->getInlinedAt()) {
134 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
135 return I != InlinedLexicalScopeMap.end() ? &
I->second :
nullptr;
146 if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
148 return getOrCreateLexicalScope(IA);
152 return getOrCreateInlinedScope(Scope, IA);
155 return getOrCreateRegularScope(Scope);
160LexicalScopes::getOrCreateRegularScope(
const DILocalScope *Scope) {
161 assert(Scope &&
"Invalid Scope encoding!");
164 auto I = LexicalScopeMap.find(Scope);
165 if (
I != LexicalScopeMap.end())
170 if (
auto *
Block = dyn_cast<DILexicalBlockBase>(Scope))
171 Parent = getOrCreateLexicalScope(
Block->getScope());
172 I = LexicalScopeMap.emplace(std::piecewise_construct,
173 std::forward_as_tuple(Scope),
174 std::forward_as_tuple(Parent, Scope,
nullptr,
178 assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
179 assert(!CurrentFnLexicalScope);
180 CurrentFnLexicalScope = &
I->second;
188LexicalScopes::getOrCreateInlinedScope(
const DILocalScope *Scope,
190 assert(Scope &&
"Invalid Scope encoding!");
192 std::pair<const DILocalScope *, const DILocation *>
P(Scope, InlinedAt);
193 auto I = InlinedLexicalScopeMap.find(
P);
194 if (
I != InlinedLexicalScopeMap.end())
198 if (
auto *
Block = dyn_cast<DILexicalBlockBase>(Scope))
199 Parent = getOrCreateInlinedScope(
Block->getScope(), InlinedAt);
201 Parent = getOrCreateLexicalScope(InlinedAt);
203 I = InlinedLexicalScopeMap
204 .emplace(std::piecewise_construct, std::forward_as_tuple(
P),
205 std::forward_as_tuple(Parent, Scope, InlinedAt,
false))
213 assert(Scope &&
"Invalid Scope encoding!");
214 Scope = Scope->getNonLexicalBlockFileScope();
215 auto I = AbstractScopeMap.find(Scope);
216 if (
I != AbstractScopeMap.end())
221 if (
auto *
Block = dyn_cast<DILexicalBlockBase>(Scope))
224 I = AbstractScopeMap.emplace(std::piecewise_construct,
225 std::forward_as_tuple(Scope),
226 std::forward_as_tuple(Parent, Scope,
227 nullptr,
true)).first;
228 if (isa<DISubprogram>(Scope))
229 AbstractScopesList.push_back(&
I->second);
236void LexicalScopes::constructScopeNest(
LexicalScope *Scope) {
237 assert(Scope &&
"Unable to calculate scope dominance graph!");
239 WorkStack.
push_back(std::make_pair(Scope, 0));
240 unsigned Counter = 0;
241 while (!WorkStack.
empty()) {
242 auto &ScopePosition = WorkStack.
back();
244 size_t ChildNum = ScopePosition.second++;
246 if (ChildNum < Children.size()) {
247 auto &ChildScope = Children[ChildNum];
248 WorkStack.
push_back(std::make_pair(ChildScope, 0));
249 ChildScope->setDFSIn(++Counter);
259void LexicalScopes::assignInstructionRanges(
263 for (
const auto &R : MIRanges) {
265 assert(S &&
"Lost LexicalScope for a machine instruction!");
266 if (PrevLexicalScope && !PrevLexicalScope->
dominates(S))
270 PrevLexicalScope = S;
273 if (PrevLexicalScope)
282 assert(MF &&
"Method called on a uninitialized LexicalScopes object!");
289 if (Scope == CurrentFnLexicalScope) {
290 for (
const auto &
MBB : *MF)
299 for (
auto &R : InsnRanges)
300 for (
auto CurMBBIt = R.first->getParent()->getIterator(),
301 EndBBIt = std::next(R.second->getParent()->getIterator());
302 CurMBBIt != EndBBIt; CurMBBIt++)
307 assert(MF &&
"Unexpected uninitialized LexicalScopes object!");
313 if (Scope == CurrentFnLexicalScope &&
MBB->
getParent() == MF)
322 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[
DL];
324 Set = std::make_unique<BlockSetT>();
327 return Set->contains(
MBB);
330#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
334 err <<
"DFSIn: " << DFSIn <<
" DFSOut: " << DFSOut <<
"\n";
339 err << std::string(Indent,
' ') <<
"Abstract Scope\n";
341 if (!Children.empty())
342 err << std::string(Indent + 2,
' ') <<
"Children ...\n";
345 Child->dump(Indent + 2);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
DISubprogram * getSubprogram() const
Get the attached subprogram.
LexicalScope - This class is used to track scope information.
void extendInsnRange(const MachineInstr *MI)
extendInsnRange - Extend the current instruction range covered by this scope.
SmallVectorImpl< LexicalScope * > & getChildren()
void setDFSOut(unsigned O)
void openInsnRange(const MachineInstr *MI)
openInsnRange - This scope covers instruction range starting from MI.
void dump(unsigned Indent=0) const
dump - print lexical scope.
bool dominates(const LexicalScope *S) const
dominates - Return true if current scope dominates given lexical scope.
void closeInsnRange(LexicalScope *NewScope=nullptr)
closeInsnRange - Create a range based on FirstInsn and LastInsn collected until now.
void reset()
releaseMemory - release memory.
LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)
getOrCreateAbstractScope - Find or create an abstract lexical scope.
void initialize(const MachineFunction &)
initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock * > &MBBs)
getMachineBasicBlocks - Populate given set using machine basic blocks which have machine instructions...
bool dominates(const DILocation *DL, MachineBasicBlock *MBB)
Return true if DebugLoc's lexical scope dominates at least one machine instruction's lexical scope in...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
InsnRange - This is used to track range of instructions with identical lexical scope.
Description of the encoding of one expression Op.