Skip to content

Commit 52b961d

Browse files
committed
Revert "Fix post-dominator tree in stack promotion"
This broke the test suite under optimizations with a SIL verifier error: "stack dealloc does not match most recent stack alloc". This reverts commit 7a2ca23, reversing changes made to 4c55e8d.
1 parent b0d54b1 commit 52b961d

File tree

3 files changed

+12
-169
lines changed

3 files changed

+12
-169
lines changed

lib/SILOptimizer/Transforms/StackPromotion.cpp

Lines changed: 11 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
1818
#include "swift/SIL/SILArgument.h"
1919
#include "swift/SIL/SILBuilder.h"
20-
#include "swift/SIL/CFG.h"
21-
#include "llvm/Support/GenericDomTree.h"
22-
#include "llvm/Support/GenericDomTreeConstruction.h"
2320
#include "llvm/ADT/Statistic.h"
2421

2522
STATISTIC(NumStackPromoted, "Number of objects promoted to the stack");
@@ -51,23 +48,9 @@ class StackPromoter {
5148
SILFunction *F;
5249
EscapeAnalysis::ConnectionGraph *ConGraph;
5350
DominanceInfo *DT;
51+
PostDominanceInfo *PDT;
5452
EscapeAnalysis *EA;
5553

56-
// We use our own post-dominator tree instead of PostDominatorAnalysis,
57-
// because we ignore unreachable blocks (actually all unreachable sub-graphs).
58-
// Example:
59-
// |
60-
// bb1
61-
// / \
62-
// unreachable bb2
63-
// \
64-
//
65-
// We want to get bb2 as immediate post-domiator of bb1. This is not the case
66-
// with the regualar post-dominator tree.
67-
llvm::DominatorTreeBase<SILBasicBlock> PostDomTree;
68-
69-
bool PostDomTreeValid;
70-
7154
// Pseudo-functions for (de-)allocating array buffers on the stack.
7255

7356
SILFunction *BufferAllocFunc = nullptr;
@@ -142,41 +125,25 @@ class StackPromoter {
142125
}
143126

144127
bool strictlyPostDominates(SILBasicBlock *A, SILBasicBlock *B) {
145-
calculatePostDomTree();
146-
return A != B && PostDomTree.dominates(A, B);
147-
}
148-
149-
bool postDominates(SILBasicBlock *A, SILBasicBlock *B) {
150-
calculatePostDomTree();
151-
return PostDomTree.dominates(A, B);
128+
return A != B && PDT->dominates(A, B);
152129
}
153130

154131
SILBasicBlock *getImmediatePostDom(SILBasicBlock *BB) {
155-
calculatePostDomTree();
156-
auto *Node = PostDomTree.getNode(BB);
132+
auto *Node = PDT->getNode(BB);
157133
if (!Node)
158134
return nullptr;
159135
auto *IDomNode = Node->getIDom();
160136
if (!IDomNode)
161137
return nullptr;
162138
return IDomNode->getBlock();
163139
}
164-
165-
void calculatePostDomTree() {
166-
if (!PostDomTreeValid) {
167-
// The StackPromoter acts as a "graph" for which the post-dominator-tree
168-
// is calculated.
169-
PostDomTree.recalculate(*this);
170-
PostDomTreeValid = true;
171-
}
172-
}
173140

174141
public:
175142

176143
StackPromoter(SILFunction *F, EscapeAnalysis::ConnectionGraph *ConGraph,
177-
DominanceInfo *DT, EscapeAnalysis *EA) :
178-
F(F), ConGraph(ConGraph), DT(DT), EA(EA), PostDomTree(true),
179-
PostDomTreeValid(false) { }
144+
DominanceInfo *DT, PostDominanceInfo *PDT,
145+
EscapeAnalysis *EA) :
146+
F(F), ConGraph(ConGraph), DT(DT), PDT(PDT), EA(EA) { }
180147

181148
/// What did the optimization change?
182149
enum class ChangeState {
@@ -185,8 +152,6 @@ class StackPromoter {
185152
Calls
186153
};
187154

188-
SILFunction *getFunction() const { return F; }
189-
190155
/// The main entry point for the optimization.
191156
ChangeState promote();
192157
};
@@ -319,87 +284,6 @@ SILFunction *StackPromoter::getBufferDeallocFunc(SILFunction *OrigFunc,
319284
return BufferDeallocFunc;
320285
}
321286

322-
namespace {
323-
324-
/// Iterator which iterates over all basic blocks of a function which are not
325-
/// terminated by an unreachable inst.
326-
class NonUnreachableBlockIter :
327-
public std::iterator<std::forward_iterator_tag, SILBasicBlock, ptrdiff_t> {
328-
329-
SILFunction::iterator BaseIterator;
330-
SILFunction::iterator End;
331-
332-
void skipUnreachables() {
333-
while (true) {
334-
if (BaseIterator == End)
335-
return;
336-
if (!isa<UnreachableInst>(BaseIterator->getTerminator()))
337-
return;
338-
BaseIterator++;
339-
}
340-
}
341-
342-
public:
343-
NonUnreachableBlockIter(SILFunction::iterator BaseIterator,
344-
SILFunction::iterator End) :
345-
BaseIterator(BaseIterator), End(End) {
346-
skipUnreachables();
347-
}
348-
349-
NonUnreachableBlockIter() = default;
350-
351-
SILBasicBlock &operator*() const { return *BaseIterator; }
352-
SILBasicBlock &operator->() const { return *BaseIterator; }
353-
354-
NonUnreachableBlockIter &operator++() {
355-
BaseIterator++;
356-
skipUnreachables();
357-
return *this;
358-
}
359-
360-
NonUnreachableBlockIter operator++(int unused) {
361-
NonUnreachableBlockIter Copy = *this;
362-
++*this;
363-
return Copy;
364-
}
365-
366-
friend bool operator==(NonUnreachableBlockIter lhs,
367-
NonUnreachableBlockIter rhs) {
368-
return lhs.BaseIterator == rhs.BaseIterator;
369-
}
370-
friend bool operator!=(NonUnreachableBlockIter lhs,
371-
NonUnreachableBlockIter rhs) {
372-
return !(lhs == rhs);
373-
}
374-
};
375-
}
376-
377-
namespace llvm {
378-
379-
/// Use the StackPromoter as a wrapper for the function. It holds the list of
380-
/// basic blocks excluding all unreachable blocks.
381-
template <> struct GraphTraits<StackPromoter *>
382-
: public GraphTraits<swift::SILBasicBlock*> {
383-
typedef StackPromoter *GraphType;
384-
385-
static NodeType *getEntryNode(GraphType SP) {
386-
return &SP->getFunction()->front();
387-
}
388-
389-
typedef NonUnreachableBlockIter nodes_iterator;
390-
static nodes_iterator nodes_begin(GraphType SP) {
391-
return nodes_iterator(SP->getFunction()->begin(), SP->getFunction()->end());
392-
}
393-
static nodes_iterator nodes_end(GraphType SP) {
394-
return nodes_iterator(SP->getFunction()->end(), SP->getFunction()->end());
395-
}
396-
static unsigned size(GraphType SP) {
397-
return std::distance(nodes_begin(SP), nodes_end(SP));
398-
}
399-
};
400-
401-
}
402-
403287
bool StackPromoter::canPromoteAlloc(SILInstruction *AI,
404288
SILInstruction *&AllocInsertionPoint,
405289
SILInstruction *&DeallocInsertionPoint) {
@@ -510,7 +394,7 @@ bool StackPromoter::canPromoteAlloc(SILInstruction *AI,
510394
if (!Alloc)
511395
return false;
512396
// This should always be the case, but let's be on the safe side.
513-
if (!postDominates(StartBlock, Alloc->getParent()))
397+
if (!PDT->dominates(StartBlock, Alloc->getParent()))
514398
return false;
515399
AllocInsertionPoint = Alloc;
516400
StackDepth++;
@@ -582,18 +466,20 @@ class StackPromotion : public SILFunctionTransform {
582466

583467
auto *EA = PM->getAnalysis<EscapeAnalysis>();
584468
auto *DA = PM->getAnalysis<DominanceAnalysis>();
469+
auto *PDA = PM->getAnalysis<PostDominanceAnalysis>();
585470

586471
SILFunction *F = getFunction();
587472
if (auto *ConGraph = EA->getConnectionGraph(F)) {
588-
StackPromoter promoter(F, ConGraph, DA->get(F), EA);
473+
StackPromoter promoter(F, ConGraph, DA->get(F), PDA->get(F), EA);
589474
switch (promoter.promote()) {
590475
case StackPromoter::ChangeState::None:
591476
break;
592477
case StackPromoter::ChangeState::Insts:
593478
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
594479
break;
595-
case StackPromoter::ChangeState::Calls:
480+
case StackPromoter::ChangeState::Calls: {
596481
invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions);
482+
}
597483
break;
598484
}
599485
}

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ SILInstruction *ValueLifetimeAnalysis:: findLastUserInBlock(SILBasicBlock *BB) {
11341134
bool ValueLifetimeAnalysis::computeFrontier(Frontier &Fr, Mode mode) {
11351135
bool NoCriticalEdges = true;
11361136

1137-
// Exit-blocks from the lifetime region. The value is live at the end of
1137+
// Exit-blocks from the lifetime region. The value if live at the end of
11381138
// a predecessor block but not in the frontier block itself.
11391139
llvm::SmallSetVector<SILBasicBlock *, 16> FrontierBlocks;
11401140

test/SILOptimizer/stack_promotion.sil

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -88,49 +88,6 @@ bb0:
8888
return %t : $()
8989
}
9090

91-
// CHECK-LABEL: sil @promote_with_unreachable_block
92-
// CHECK: [[O:%[0-9]+]] = alloc_ref [stack] $XX
93-
// CHECK: bb1:
94-
// CHECK-NEXT: unreachable
95-
// CHECK: bb2:
96-
// CHECK: strong_release
97-
// CHECK: dealloc_ref [stack] [[O]] : $XX
98-
// CHECK: return
99-
sil @promote_with_unreachable_block : $@convention(thin) () -> Int32 {
100-
bb0:
101-
%o1 = alloc_ref $XX
102-
%f1 = function_ref @xx_init : $@convention(thin) (@guaranteed XX) -> XX
103-
%n1 = apply %f1(%o1) : $@convention(thin) (@guaranteed XX) -> XX
104-
cond_br undef, bb1, bb2
105-
106-
bb1:
107-
unreachable
108-
109-
bb2:
110-
%l1 = ref_element_addr %n1 : $XX, #XX.x
111-
%l2 = load %l1 : $*Int32
112-
strong_release %n1 : $XX
113-
return %l2 : $Int32
114-
}
115-
116-
// CHECK-LABEL: sil @no_return_function
117-
// Just check that we don't crash on this.
118-
// It's a corner case, so we don't care if stack promotion is done or not.
119-
// CHECK: unreachable
120-
sil @no_return_function : $@convention(thin) () -> Int32 {
121-
bb0:
122-
%o1 = alloc_ref $XX
123-
%f1 = function_ref @xx_init : $@convention(thin) (@guaranteed XX) -> XX
124-
%n1 = apply %f1(%o1) : $@convention(thin) (@guaranteed XX) -> XX
125-
br bb1
126-
127-
bb1:
128-
%l1 = ref_element_addr %n1 : $XX, #XX.x
129-
%l2 = load %l1 : $*Int32
130-
strong_release %n1 : $XX
131-
unreachable
132-
}
133-
13491
// CHECK-LABEL: sil @promote_in_loop_with_if
13592
// CHECK: [[O:%[0-9]+]] = alloc_ref [stack] $XX
13693
// CHECK: {{^}}bb4({{.*}}):

0 commit comments

Comments
 (0)