Skip to content

Commit 8821621

Browse files
committed
[silmem2reg] Compute DomTreeLevels lazily.
We previously were computing this eagerly meaning that if we did not actually need the DomTreeLevel map, we would calculate it and additionally incur a relatively large malloc for the DenseMap (which stores by default IIRC 64 key value pairs). Now, we do it lazily ensuring that we only compute this if we actually need it (when promoting non-single block stack allocations).
1 parent 8c9d402 commit 8821621

File tree

1 file changed

+39
-28
lines changed

1 file changed

+39
-28
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,13 @@ namespace {
741741

742742
/// Promote memory to registers
743743
class MemoryToRegisters {
744+
/// Lazily initialized map from DomTreeNode to DomTreeLevel.
745+
///
746+
/// DomTreeLevelMap is a DenseMap implying that if we initialize it, we always
747+
/// will initialize a heap object with 64 objects. Thus by using an optional,
748+
/// computing this lazily, we only do this if we actually need to do so.
749+
Optional<DomTreeLevelMap> domTreeLevels;
750+
744751
/// The function that we are optimizing.
745752
SILFunction &f;
746753

@@ -751,6 +758,32 @@ class MemoryToRegisters {
751758
/// promotion.
752759
SILBuilderContext ctx;
753760

761+
/// Returns the dom tree levels for the current function. Computes these
762+
/// lazily.
763+
DomTreeLevelMap &getDomTreeLevels() {
764+
// If we already computed our levels, just return it.
765+
if (auto &levels = domTreeLevels) {
766+
return *levels;
767+
}
768+
769+
// Otherwise, emplace the map and compute it.
770+
domTreeLevels.emplace();
771+
auto &levels = *domTreeLevels;
772+
SmallVector<DomTreeNode *, 32> worklist;
773+
DomTreeNode *rootNode = domInfo->getRootNode();
774+
levels[rootNode] = 0;
775+
worklist.push_back(rootNode);
776+
while (!worklist.empty()) {
777+
DomTreeNode *domNode = worklist.pop_back_val();
778+
unsigned childLevel = levels[domNode] + 1;
779+
for (auto *childNode : domNode->children()) {
780+
levels[childNode] = childLevel;
781+
worklist.push_back(childNode);
782+
}
783+
}
784+
return *domTreeLevels;
785+
}
786+
754787
/// Check if the AllocStackInst \p ASI is only written into.
755788
bool isWriteOnlyAllocation(AllocStackInst *asi);
756789

@@ -763,8 +796,7 @@ class MemoryToRegisters {
763796
/// Attempt to promote the specified stack allocation, returning true if so
764797
/// or false if not. On success, all uses of the AllocStackInst have been
765798
/// removed, but the ASI itself is still in the program.
766-
bool promoteSingleAllocation(AllocStackInst *asi,
767-
DomTreeLevelMap &domTreeLevels);
799+
bool promoteSingleAllocation(AllocStackInst *asi);
768800

769801
public:
770802
/// C'tor
@@ -1001,30 +1033,11 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
10011033
}
10021034
}
10031035

1004-
/// Compute the dominator tree levels for domInfo.
1005-
static void computeDomTreeLevels(DominanceInfo *domInfo,
1006-
DomTreeLevelMap &domTreeLevels) {
1007-
// TODO: This should happen once per function.
1008-
SmallVector<DomTreeNode *, 32> worklist;
1009-
DomTreeNode *rootNode = domInfo->getRootNode();
1010-
domTreeLevels[rootNode] = 0;
1011-
worklist.push_back(rootNode);
1012-
while (!worklist.empty()) {
1013-
DomTreeNode *domNode = worklist.pop_back_val();
1014-
unsigned childLevel = domTreeLevels[domNode] + 1;
1015-
for (auto *childNode : domNode->children()) {
1016-
domTreeLevels[childNode] = childLevel;
1017-
worklist.push_back(childNode);
1018-
}
1019-
}
1020-
}
1021-
10221036
/// Attempt to promote the specified stack allocation, returning true if so
10231037
/// or false if not. On success, this returns true and usually drops all of the
10241038
/// uses of the AllocStackInst, but never deletes the ASI itself. Callers
10251039
/// should check to see if the ASI is dead after this and remove it if so.
1026-
bool MemoryToRegisters::promoteSingleAllocation(
1027-
AllocStackInst *alloc, DomTreeLevelMap &domTreeLevels) {
1040+
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) {
10281041
LLVM_DEBUG(llvm::dbgs() << "*** Memory to register looking at: " << *alloc);
10291042
++NumAllocStackFound;
10301043

@@ -1064,7 +1077,9 @@ bool MemoryToRegisters::promoteSingleAllocation(
10641077

10651078
LLVM_DEBUG(llvm::dbgs() << "*** Need to insert BB arguments for " << *alloc);
10661079

1067-
// Promote this allocation.
1080+
// Promote this allocation, lazily computing dom tree levels for this function
1081+
// if we have not done so yet.
1082+
auto &domTreeLevels = getDomTreeLevels();
10681083
StackAllocationPromoter(alloc, domInfo, domTreeLevels, ctx).run();
10691084

10701085
// Make sure that all of the allocations were promoted into registers.
@@ -1080,10 +1095,6 @@ bool MemoryToRegisters::run() {
10801095
if (f.getModule().getOptions().VerifyAll)
10811096
f.verifyCriticalEdges();
10821097

1083-
// Compute dominator tree node levels for the function.
1084-
DomTreeLevelMap domTreeLevels;
1085-
computeDomTreeLevels(domInfo, domTreeLevels);
1086-
10871098
for (auto &block : f) {
10881099
auto ii = block.begin(), ie = block.end();
10891100
while (ii != ie) {
@@ -1094,7 +1105,7 @@ bool MemoryToRegisters::run() {
10941105
continue;
10951106
}
10961107

1097-
bool promoted = promoteSingleAllocation(asi, domTreeLevels);
1108+
bool promoted = promoteSingleAllocation(asi);
10981109
++ii;
10991110
if (promoted) {
11001111
if (asi->use_empty())

0 commit comments

Comments
 (0)