2011-08-11 03:04:06 +08:00
|
|
|
//===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-08-11 03:04:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements LexicalScopes analysis.
|
|
|
|
//
|
|
|
|
// This pass collects lexical scope information and maps machine instructions
|
|
|
|
// to respective lexical scopes.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/CodeGen/LexicalScopes.h"
|
2017-02-18 05:43:25 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2011-08-11 03:04:06 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2018-04-30 22:59:11 +08:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2017-02-18 05:43:25 +08:00
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2019-10-19 08:22:07 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
2017-02-18 05:43:25 +08:00
|
|
|
#include "llvm/IR/Metadata.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2011-08-11 03:04:06 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2017-02-18 05:43:25 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
|
2011-08-11 03:04:06 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:02:50 +08:00
|
|
|
#define DEBUG_TYPE "lexicalscopes"
|
|
|
|
|
2013-11-20 08:54:28 +08:00
|
|
|
/// reset - Reset the instance so that it's prepared for another function.
|
|
|
|
void LexicalScopes::reset() {
|
2014-04-14 08:51:57 +08:00
|
|
|
MF = nullptr;
|
|
|
|
CurrentFnLexicalScope = nullptr;
|
2014-05-09 06:24:51 +08:00
|
|
|
LexicalScopeMap.clear();
|
|
|
|
AbstractScopeMap.clear();
|
2011-08-11 03:04:06 +08:00
|
|
|
InlinedLexicalScopeMap.clear();
|
|
|
|
AbstractScopesList.clear();
|
[LiveDebugValues] Cache LexicalScopes::getMachineBasicBlocks, NFCI
Summary:
Cache the results from getMachineBasicBlocks in LexicalScopes to speed
up UserValueScopes::dominates queries. This replaces the caching done
in UserValueScopes. Compared to the old caching method, this reduces
memory traffic when a VarLoc is copied (e.g. when a VarLocMap grows),
and enables caching across basic blocks.
When compiling sqlite 3.5.7 (CTMark version), this patch reduces the
number of calls to getMachineBasicBlocks from 10,207 to 1,093. I also
measured a small compile-time reduction (~ 0.1% of total wall time, on
average, on my machine).
As a drive-by, I made the DebugLoc in UserValueScopes a const reference
to cut down on MetadataTracking traffic.
Reviewers: jmorse, Orlando, aprantl, nikic
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D80957
2020-05-29 06:57:11 +08:00
|
|
|
DominatedBlocks.clear();
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// initialize - Scan machine function and constuct lexical scope nest.
|
|
|
|
void LexicalScopes::initialize(const MachineFunction &Fn) {
|
2017-07-20 03:36:40 +08:00
|
|
|
reset();
|
2017-02-17 08:21:19 +08:00
|
|
|
// Don't attempt any lexical scope creation for a NoDebug compile unit.
|
2017-12-16 06:22:58 +08:00
|
|
|
if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
|
2017-02-17 08:21:19 +08:00
|
|
|
DICompileUnit::NoDebug)
|
|
|
|
return;
|
2011-08-11 03:04:06 +08:00
|
|
|
MF = &Fn;
|
|
|
|
SmallVector<InsnRange, 4> MIRanges;
|
|
|
|
DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
|
|
|
|
extractLexicalScopes(MIRanges, MI2ScopeMap);
|
|
|
|
if (CurrentFnLexicalScope) {
|
|
|
|
constructScopeNest(CurrentFnLexicalScope);
|
|
|
|
assignInstructionRanges(MIRanges, MI2ScopeMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
|
|
|
|
/// for the given machine function.
|
2013-11-20 08:54:19 +08:00
|
|
|
void LexicalScopes::extractLexicalScopes(
|
|
|
|
SmallVectorImpl<InsnRange> &MIRanges,
|
|
|
|
DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
|
2011-08-11 03:04:06 +08:00
|
|
|
// Scan each instruction and create scopes. First build working set of scopes.
|
2014-05-01 02:29:51 +08:00
|
|
|
for (const auto &MBB : *MF) {
|
2014-04-14 08:51:57 +08:00
|
|
|
const MachineInstr *RangeBeginMI = nullptr;
|
|
|
|
const MachineInstr *PrevMI = nullptr;
|
2015-04-30 00:38:44 +08:00
|
|
|
const DILocation *PrevDL = nullptr;
|
2014-05-01 06:17:38 +08:00
|
|
|
for (const auto &MInsn : MBB) {
|
2021-04-13 14:51:44 +08:00
|
|
|
// Ignore DBG_VALUE and similar instruction that do not contribute to any
|
|
|
|
// instruction in the output.
|
|
|
|
if (MInsn.isMetaInstruction())
|
|
|
|
continue;
|
|
|
|
|
2011-08-11 03:04:06 +08:00
|
|
|
// Check if instruction has valid location information.
|
2015-04-30 00:38:44 +08:00
|
|
|
const DILocation *MIDL = MInsn.getDebugLoc();
|
2015-03-31 03:14:47 +08:00
|
|
|
if (!MIDL) {
|
2014-05-01 06:17:38 +08:00
|
|
|
PrevMI = &MInsn;
|
2011-08-11 03:04:06 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If scope has not changed then skip this instruction.
|
|
|
|
if (MIDL == PrevDL) {
|
2014-05-01 06:17:38 +08:00
|
|
|
PrevMI = &MInsn;
|
2011-08-11 03:04:06 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RangeBeginMI) {
|
|
|
|
// If we have already seen a beginning of an instruction range and
|
|
|
|
// current instruction scope does not match scope of first instruction
|
|
|
|
// in this range then create a new instruction range.
|
|
|
|
InsnRange R(RangeBeginMI, PrevMI);
|
|
|
|
MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
|
|
|
|
MIRanges.push_back(R);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a beginning of a new instruction range.
|
2014-05-01 06:17:38 +08:00
|
|
|
RangeBeginMI = &MInsn;
|
2011-08-11 03:04:06 +08:00
|
|
|
|
|
|
|
// Reset previous markers.
|
2014-05-01 06:17:38 +08:00
|
|
|
PrevMI = &MInsn;
|
2011-08-11 03:04:06 +08:00
|
|
|
PrevDL = MIDL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create last instruction range.
|
2015-03-31 03:14:47 +08:00
|
|
|
if (RangeBeginMI && PrevMI && PrevDL) {
|
2011-08-11 03:04:06 +08:00
|
|
|
InsnRange R(RangeBeginMI, PrevMI);
|
|
|
|
MIRanges.push_back(R);
|
|
|
|
MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// findLexicalScope - Find lexical scope, either regular or inlined, for the
|
|
|
|
/// given DebugLoc. Return NULL if not found.
|
2015-04-30 00:38:44 +08:00
|
|
|
LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
|
|
|
|
DILocalScope *Scope = DL->getScope();
|
2013-11-20 08:54:19 +08:00
|
|
|
if (!Scope)
|
2014-04-14 08:51:57 +08:00
|
|
|
return nullptr;
|
2011-10-12 06:59:11 +08:00
|
|
|
|
|
|
|
// The scope that we were created with could have an extra file - which
|
|
|
|
// isn't what we care about in this case.
|
2016-04-22 00:58:49 +08:00
|
|
|
Scope = Scope->getNonLexicalBlockFileScope();
|
2013-11-20 08:54:19 +08:00
|
|
|
|
2015-03-31 05:54:46 +08:00
|
|
|
if (auto *IA = DL->getInlinedAt()) {
|
2014-05-14 09:08:28 +08:00
|
|
|
auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
|
|
|
|
return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
|
|
|
|
}
|
2014-05-09 06:24:51 +08:00
|
|
|
return findLexicalScope(Scope);
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
|
|
|
|
/// not available then create new lexical scope.
|
2015-04-30 00:38:44 +08:00
|
|
|
LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
|
|
|
|
const DILocation *IA) {
|
2015-03-31 07:47:26 +08:00
|
|
|
if (IA) {
|
2017-02-17 08:21:19 +08:00
|
|
|
// Skip scopes inlined from a NoDebug compile unit.
|
|
|
|
if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
|
|
|
|
DICompileUnit::NoDebug)
|
|
|
|
return getOrCreateLexicalScope(IA);
|
2011-08-11 03:04:06 +08:00
|
|
|
// Create an abstract scope for inlined function.
|
|
|
|
getOrCreateAbstractScope(Scope);
|
|
|
|
// Create an inlined scope for inlined function.
|
2015-03-31 07:47:26 +08:00
|
|
|
return getOrCreateInlinedScope(Scope, IA);
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
2013-11-20 08:54:19 +08:00
|
|
|
|
2011-08-11 03:04:06 +08:00
|
|
|
return getOrCreateRegularScope(Scope);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateRegularScope - Find or create a regular lexical scope.
|
2015-03-31 07:21:21 +08:00
|
|
|
LexicalScope *
|
2015-04-30 00:38:44 +08:00
|
|
|
LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
|
2016-04-22 00:58:49 +08:00
|
|
|
assert(Scope && "Invalid Scope encoding!");
|
|
|
|
Scope = Scope->getNonLexicalBlockFileScope();
|
2013-11-20 08:54:19 +08:00
|
|
|
|
2014-05-09 06:24:51 +08:00
|
|
|
auto I = LexicalScopeMap.find(Scope);
|
|
|
|
if (I != LexicalScopeMap.end())
|
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
// FIXME: Should the following dyn_cast be DILexicalBlock?
|
2014-04-14 08:51:57 +08:00
|
|
|
LexicalScope *Parent = nullptr;
|
2015-04-30 00:38:44 +08:00
|
|
|
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
|
2015-03-31 07:47:26 +08:00
|
|
|
Parent = getOrCreateLexicalScope(Block->getScope());
|
2015-02-17 02:21:19 +08:00
|
|
|
I = LexicalScopeMap.emplace(std::piecewise_construct,
|
|
|
|
std::forward_as_tuple(Scope),
|
2015-03-31 07:21:21 +08:00
|
|
|
std::forward_as_tuple(Parent, Scope, nullptr,
|
|
|
|
false)).first;
|
2014-05-09 06:24:51 +08:00
|
|
|
|
DebugInfo: Ensure that all debug location scope chains from instructions within a function, lead to the function itself.
Let me tell you a tale...
Originally committed in r211723 after discovering a nasty case of weird
scoping due to inlining, this was reverted in r211724 after it fired in
ASan/compiler-rt.
(minor diversion where I accidentally committed/reverted again in
r211871/r211873)
After further testing and fixing bugs in ArgumentPromotion (r211872) and
Inlining (r212065) it was recommitted in r212085. Reverted in r212089
after the sanitizer buildbots still showed problems.
Fixed another bug in ArgumentPromotion (r212128) found by this
assertion.
Recommitted in r212205, reverted in r212226 after it crashed some more
on sanitizer buildbots.
Fix clang some more in r212761.
Recommitted in r212776, reverted in r212793. ASan failures.
Recommitted in r213391, reverted in r213432, trying to reproduce flakey
ASan build failure.
Fixed bugs in r213805 (ArgPromo + DebugInfo), r213952
(LiveDebugVariables strips dbg_value intrinsics in functions not
described by debug info).
Recommitted in r214761, reverted in r214999, flakey failure on Windows
buildbot.
Fixed DeadArgElimination + DebugInfo bug in r219210.
Recommitted in r219215, reverted in r219512, failure on ObjC++ atomic
properties in the test-suite on Darwin.
Fixed ObjC++ atomic properties issue in Clang in r219690.
[This commit is provided 'as is' with no hope that this is the last time
I commit this change either expressed or implied]
llvm-svn: 219702
2014-10-15 02:22:52 +08:00
|
|
|
if (!Parent) {
|
2017-12-16 06:22:58 +08:00
|
|
|
assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
|
DebugInfo: Ensure that all debug location scope chains from instructions within a function, lead to the function itself.
Let me tell you a tale...
Originally committed in r211723 after discovering a nasty case of weird
scoping due to inlining, this was reverted in r211724 after it fired in
ASan/compiler-rt.
(minor diversion where I accidentally committed/reverted again in
r211871/r211873)
After further testing and fixing bugs in ArgumentPromotion (r211872) and
Inlining (r212065) it was recommitted in r212085. Reverted in r212089
after the sanitizer buildbots still showed problems.
Fixed another bug in ArgumentPromotion (r212128) found by this
assertion.
Recommitted in r212205, reverted in r212226 after it crashed some more
on sanitizer buildbots.
Fix clang some more in r212761.
Recommitted in r212776, reverted in r212793. ASan failures.
Recommitted in r213391, reverted in r213432, trying to reproduce flakey
ASan build failure.
Fixed bugs in r213805 (ArgPromo + DebugInfo), r213952
(LiveDebugVariables strips dbg_value intrinsics in functions not
described by debug info).
Recommitted in r214761, reverted in r214999, flakey failure on Windows
buildbot.
Fixed DeadArgElimination + DebugInfo bug in r219210.
Recommitted in r219215, reverted in r219512, failure on ObjC++ atomic
properties in the test-suite on Darwin.
Fixed ObjC++ atomic properties issue in Clang in r219690.
[This commit is provided 'as is' with no hope that this is the last time
I commit this change either expressed or implied]
llvm-svn: 219702
2014-10-15 02:22:52 +08:00
|
|
|
assert(!CurrentFnLexicalScope);
|
2014-05-09 06:24:51 +08:00
|
|
|
CurrentFnLexicalScope = &I->second;
|
DebugInfo: Ensure that all debug location scope chains from instructions within a function, lead to the function itself.
Let me tell you a tale...
Originally committed in r211723 after discovering a nasty case of weird
scoping due to inlining, this was reverted in r211724 after it fired in
ASan/compiler-rt.
(minor diversion where I accidentally committed/reverted again in
r211871/r211873)
After further testing and fixing bugs in ArgumentPromotion (r211872) and
Inlining (r212065) it was recommitted in r212085. Reverted in r212089
after the sanitizer buildbots still showed problems.
Fixed another bug in ArgumentPromotion (r212128) found by this
assertion.
Recommitted in r212205, reverted in r212226 after it crashed some more
on sanitizer buildbots.
Fix clang some more in r212761.
Recommitted in r212776, reverted in r212793. ASan failures.
Recommitted in r213391, reverted in r213432, trying to reproduce flakey
ASan build failure.
Fixed bugs in r213805 (ArgPromo + DebugInfo), r213952
(LiveDebugVariables strips dbg_value intrinsics in functions not
described by debug info).
Recommitted in r214761, reverted in r214999, flakey failure on Windows
buildbot.
Fixed DeadArgElimination + DebugInfo bug in r219210.
Recommitted in r219215, reverted in r219512, failure on ObjC++ atomic
properties in the test-suite on Darwin.
Fixed ObjC++ atomic properties issue in Clang in r219690.
[This commit is provided 'as is' with no hope that this is the last time
I commit this change either expressed or implied]
llvm-svn: 219702
2014-10-15 02:22:52 +08:00
|
|
|
}
|
2013-11-20 08:54:19 +08:00
|
|
|
|
2014-05-09 06:24:51 +08:00
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
|
2015-03-31 07:21:21 +08:00
|
|
|
LexicalScope *
|
2015-04-30 00:38:44 +08:00
|
|
|
LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
|
|
|
|
const DILocation *InlinedAt) {
|
2016-04-22 00:58:49 +08:00
|
|
|
assert(Scope && "Invalid Scope encoding!");
|
|
|
|
Scope = Scope->getNonLexicalBlockFileScope();
|
2015-04-30 00:38:44 +08:00
|
|
|
std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
|
2014-05-14 09:08:28 +08:00
|
|
|
auto I = InlinedLexicalScopeMap.find(P);
|
|
|
|
if (I != InlinedLexicalScopeMap.end())
|
2014-05-09 06:24:51 +08:00
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
|
2014-05-14 09:08:28 +08:00
|
|
|
LexicalScope *Parent;
|
2015-04-30 00:38:44 +08:00
|
|
|
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
|
2015-03-31 07:21:21 +08:00
|
|
|
Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
|
2014-05-14 09:08:28 +08:00
|
|
|
else
|
2015-03-31 07:21:21 +08:00
|
|
|
Parent = getOrCreateLexicalScope(InlinedAt);
|
2014-05-14 09:08:28 +08:00
|
|
|
|
2017-02-15 03:43:50 +08:00
|
|
|
I = InlinedLexicalScopeMap
|
|
|
|
.emplace(std::piecewise_construct, std::forward_as_tuple(P),
|
|
|
|
std::forward_as_tuple(Parent, Scope, InlinedAt, false))
|
2015-02-17 02:21:19 +08:00
|
|
|
.first;
|
2014-05-09 06:24:51 +08:00
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
|
2015-03-31 07:21:21 +08:00
|
|
|
LexicalScope *
|
2015-04-30 00:38:44 +08:00
|
|
|
LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
|
2015-03-31 07:21:21 +08:00
|
|
|
assert(Scope && "Invalid Scope encoding!");
|
2016-04-22 00:58:49 +08:00
|
|
|
Scope = Scope->getNonLexicalBlockFileScope();
|
2014-05-26 02:11:35 +08:00
|
|
|
auto I = AbstractScopeMap.find(Scope);
|
2014-05-09 06:24:51 +08:00
|
|
|
if (I != AbstractScopeMap.end())
|
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
// FIXME: Should the following isa be DILexicalBlock?
|
2014-04-14 08:51:57 +08:00
|
|
|
LexicalScope *Parent = nullptr;
|
2015-04-30 00:38:44 +08:00
|
|
|
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
|
2015-03-31 07:21:21 +08:00
|
|
|
Parent = getOrCreateAbstractScope(Block->getScope());
|
|
|
|
|
2014-05-09 06:24:51 +08:00
|
|
|
I = AbstractScopeMap.emplace(std::piecewise_construct,
|
2014-05-26 02:11:35 +08:00
|
|
|
std::forward_as_tuple(Scope),
|
|
|
|
std::forward_as_tuple(Parent, Scope,
|
2014-05-09 06:24:51 +08:00
|
|
|
nullptr, true)).first;
|
2015-04-30 00:38:44 +08:00
|
|
|
if (isa<DISubprogram>(Scope))
|
2014-05-09 06:24:51 +08:00
|
|
|
AbstractScopesList.push_back(&I->second);
|
|
|
|
return &I->second;
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
2020-06-09 01:38:16 +08:00
|
|
|
/// constructScopeNest - Traverse the Scope tree depth-first, storing
|
|
|
|
/// traversal state in WorkStack and recording the depth-first
|
|
|
|
/// numbering (setDFSIn, setDFSOut) for edge classification.
|
2011-08-11 03:04:06 +08:00
|
|
|
void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
|
2013-11-20 08:54:19 +08:00
|
|
|
assert(Scope && "Unable to calculate scope dominance graph!");
|
2020-06-09 01:38:16 +08:00
|
|
|
SmallVector<std::pair<LexicalScope *, size_t>, 4> WorkStack;
|
|
|
|
WorkStack.push_back(std::make_pair(Scope, 0));
|
2011-08-11 03:04:06 +08:00
|
|
|
unsigned Counter = 0;
|
|
|
|
while (!WorkStack.empty()) {
|
2020-06-09 01:38:16 +08:00
|
|
|
auto &ScopePosition = WorkStack.back();
|
|
|
|
LexicalScope *WS = ScopePosition.first;
|
|
|
|
size_t ChildNum = ScopePosition.second++;
|
2013-07-03 12:30:58 +08:00
|
|
|
const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
|
2020-06-09 01:38:16 +08:00
|
|
|
if (ChildNum < Children.size()) {
|
|
|
|
auto &ChildScope = Children[ChildNum];
|
|
|
|
WorkStack.push_back(std::make_pair(ChildScope, 0));
|
|
|
|
ChildScope->setDFSIn(++Counter);
|
|
|
|
} else {
|
2011-08-11 03:04:06 +08:00
|
|
|
WorkStack.pop_back();
|
|
|
|
WS->setDFSOut(++Counter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-11 07:58:09 +08:00
|
|
|
/// assignInstructionRanges - Find ranges of instructions covered by each
|
|
|
|
/// lexical scope.
|
2013-11-20 08:54:19 +08:00
|
|
|
void LexicalScopes::assignInstructionRanges(
|
|
|
|
SmallVectorImpl<InsnRange> &MIRanges,
|
|
|
|
DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
|
2014-04-14 08:51:57 +08:00
|
|
|
LexicalScope *PrevLexicalScope = nullptr;
|
2016-09-29 01:31:17 +08:00
|
|
|
for (const auto &R : MIRanges) {
|
2011-08-11 03:04:06 +08:00
|
|
|
LexicalScope *S = MI2ScopeMap.lookup(R.first);
|
2013-11-20 08:54:19 +08:00
|
|
|
assert(S && "Lost LexicalScope for a machine instruction!");
|
2011-08-11 03:04:06 +08:00
|
|
|
if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
|
|
|
|
PrevLexicalScope->closeInsnRange(S);
|
|
|
|
S->openInsnRange(R.first);
|
|
|
|
S->extendInsnRange(R.second);
|
|
|
|
PrevLexicalScope = S;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PrevLexicalScope)
|
|
|
|
PrevLexicalScope->closeInsnRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getMachineBasicBlocks - Populate given set using machine basic blocks which
|
2013-11-20 08:54:19 +08:00
|
|
|
/// have machine instructions that belong to lexical scope identified by
|
2011-08-11 03:04:06 +08:00
|
|
|
/// DebugLoc.
|
2013-11-20 08:54:19 +08:00
|
|
|
void LexicalScopes::getMachineBasicBlocks(
|
2015-04-30 00:38:44 +08:00
|
|
|
const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
|
2017-07-20 03:36:40 +08:00
|
|
|
assert(MF && "Method called on a uninitialized LexicalScopes object!");
|
2011-08-11 03:04:06 +08:00
|
|
|
MBBs.clear();
|
2017-07-20 03:36:40 +08:00
|
|
|
|
2011-08-11 03:04:06 +08:00
|
|
|
LexicalScope *Scope = getOrCreateLexicalScope(DL);
|
|
|
|
if (!Scope)
|
|
|
|
return;
|
2013-11-20 08:54:19 +08:00
|
|
|
|
2011-08-13 02:01:34 +08:00
|
|
|
if (Scope == CurrentFnLexicalScope) {
|
2014-05-01 02:29:51 +08:00
|
|
|
for (const auto &MBB : *MF)
|
|
|
|
MBBs.insert(&MBB);
|
2011-08-13 02:01:34 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[DebugInfo] Re-implement LexicalScopes dominance method, add unit tests
Way back in D24994, the combination of LexicalScopes::dominates and
LiveDebugValues was identified as having worst-case quadratic complexity,
but it wasn't triggered by any code path at the time. I've since run into a
scenario where this occurs, in a very large basic block where large numbers
of inlined DBG_VALUEs are present.
The quadratic-ness comes from LiveDebugValues::join calling "dominates" on
every variable location, and LexicalScopes::dominates potentially touching
every instruction in a block to test for the presence of a scope. We have,
however, already computed the presence of scopes in blocks, in the
"InstrRanges" of each scope. This patch switches the dominates method to
examine whether a block is present in a scope's InsnRanges, avoiding
walking through the whole block.
At the same time, fix getMachineBasicBlocks to account for the fact that
InsnRanges can cover multiple blocks, and add some unit tests, as Lexical
Scopes didn't have any.
Differential revision: https://reviews.llvm.org/D73725
2020-02-28 18:41:23 +08:00
|
|
|
// The scope ranges can cover multiple basic blocks in each span. Iterate over
|
|
|
|
// all blocks (in the order they are in the function) until we reach the one
|
|
|
|
// containing the end of the span.
|
2013-07-03 12:30:58 +08:00
|
|
|
SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
|
2016-09-29 01:31:17 +08:00
|
|
|
for (auto &R : InsnRanges)
|
[DebugInfo] Re-implement LexicalScopes dominance method, add unit tests
Way back in D24994, the combination of LexicalScopes::dominates and
LiveDebugValues was identified as having worst-case quadratic complexity,
but it wasn't triggered by any code path at the time. I've since run into a
scenario where this occurs, in a very large basic block where large numbers
of inlined DBG_VALUEs are present.
The quadratic-ness comes from LiveDebugValues::join calling "dominates" on
every variable location, and LexicalScopes::dominates potentially touching
every instruction in a block to test for the presence of a scope. We have,
however, already computed the presence of scopes in blocks, in the
"InstrRanges" of each scope. This patch switches the dominates method to
examine whether a block is present in a scope's InsnRanges, avoiding
walking through the whole block.
At the same time, fix getMachineBasicBlocks to account for the fact that
InsnRanges can cover multiple blocks, and add some unit tests, as Lexical
Scopes didn't have any.
Differential revision: https://reviews.llvm.org/D73725
2020-02-28 18:41:23 +08:00
|
|
|
for (auto CurMBBIt = R.first->getParent()->getIterator(),
|
|
|
|
EndBBIt = std::next(R.second->getParent()->getIterator());
|
|
|
|
CurMBBIt != EndBBIt; CurMBBIt++)
|
|
|
|
MBBs.insert(&*CurMBBIt);
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
|
2017-07-20 03:36:40 +08:00
|
|
|
assert(MF && "Unexpected uninitialized LexicalScopes object!");
|
2011-08-11 03:04:06 +08:00
|
|
|
LexicalScope *Scope = getOrCreateLexicalScope(DL);
|
|
|
|
if (!Scope)
|
|
|
|
return false;
|
2011-08-13 02:01:34 +08:00
|
|
|
|
|
|
|
// Current function scope covers all basic blocks in the function.
|
|
|
|
if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
|
|
|
|
return true;
|
|
|
|
|
[DebugInfo] Re-implement LexicalScopes dominance method, add unit tests
Way back in D24994, the combination of LexicalScopes::dominates and
LiveDebugValues was identified as having worst-case quadratic complexity,
but it wasn't triggered by any code path at the time. I've since run into a
scenario where this occurs, in a very large basic block where large numbers
of inlined DBG_VALUEs are present.
The quadratic-ness comes from LiveDebugValues::join calling "dominates" on
every variable location, and LexicalScopes::dominates potentially touching
every instruction in a block to test for the presence of a scope. We have,
however, already computed the presence of scopes in blocks, in the
"InstrRanges" of each scope. This patch switches the dominates method to
examine whether a block is present in a scope's InsnRanges, avoiding
walking through the whole block.
At the same time, fix getMachineBasicBlocks to account for the fact that
InsnRanges can cover multiple blocks, and add some unit tests, as Lexical
Scopes didn't have any.
Differential revision: https://reviews.llvm.org/D73725
2020-02-28 18:41:23 +08:00
|
|
|
// Fetch all the blocks in DLs scope. Because the range / block list also
|
[LiveDebugValues] Cache LexicalScopes::getMachineBasicBlocks, NFCI
Summary:
Cache the results from getMachineBasicBlocks in LexicalScopes to speed
up UserValueScopes::dominates queries. This replaces the caching done
in UserValueScopes. Compared to the old caching method, this reduces
memory traffic when a VarLoc is copied (e.g. when a VarLocMap grows),
and enables caching across basic blocks.
When compiling sqlite 3.5.7 (CTMark version), this patch reduces the
number of calls to getMachineBasicBlocks from 10,207 to 1,093. I also
measured a small compile-time reduction (~ 0.1% of total wall time, on
average, on my machine).
As a drive-by, I made the DebugLoc in UserValueScopes a const reference
to cut down on MetadataTracking traffic.
Reviewers: jmorse, Orlando, aprantl, nikic
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D80957
2020-05-29 06:57:11 +08:00
|
|
|
// contain any subscopes, any instruction that DL dominates can be found in
|
|
|
|
// the block set.
|
|
|
|
//
|
|
|
|
// Cache the set of fetched blocks to avoid repeatedly recomputing the set in
|
|
|
|
// the LiveDebugValues pass.
|
|
|
|
std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL];
|
|
|
|
if (!Set) {
|
|
|
|
Set = std::make_unique<BlockSetT>();
|
|
|
|
getMachineBasicBlocks(DL, *Set);
|
|
|
|
}
|
2021-01-09 10:39:53 +08:00
|
|
|
return Set->contains(MBB);
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
|
|
|
|
2017-10-15 22:32:27 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2017-01-28 10:02:38 +08:00
|
|
|
LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
|
2011-08-11 03:04:06 +08:00
|
|
|
raw_ostream &err = dbgs();
|
2013-02-02 08:02:03 +08:00
|
|
|
err.indent(Indent);
|
2011-08-11 03:04:06 +08:00
|
|
|
err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
|
|
|
|
const MDNode *N = Desc;
|
2013-02-02 08:02:03 +08:00
|
|
|
err.indent(Indent);
|
2011-08-11 03:04:06 +08:00
|
|
|
N->dump();
|
|
|
|
if (AbstractScope)
|
2013-02-02 08:02:03 +08:00
|
|
|
err << std::string(Indent, ' ') << "Abstract Scope\n";
|
2011-08-11 03:04:06 +08:00
|
|
|
|
|
|
|
if (!Children.empty())
|
2013-02-02 08:02:03 +08:00
|
|
|
err << std::string(Indent + 2, ' ') << "Children ...\n";
|
2011-08-11 03:04:06 +08:00
|
|
|
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
|
|
|
if (Children[i] != this)
|
2013-02-02 08:02:03 +08:00
|
|
|
Children[i]->dump(Indent + 2);
|
2011-08-11 03:04:06 +08:00
|
|
|
}
|
2017-01-28 10:02:38 +08:00
|
|
|
#endif
|