@@ -741,6 +741,13 @@ namespace {
741741
742742// / Promote memory to registers
743743class 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
769801public:
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