17
17
#include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
18
18
#include " swift/SIL/SILArgument.h"
19
19
#include " swift/SIL/SILBuilder.h"
20
+ #include " swift/SIL/CFG.h"
21
+ #include " llvm/Support/GenericDomTree.h"
22
+ #include " llvm/Support/GenericDomTreeConstruction.h"
20
23
#include " llvm/ADT/Statistic.h"
21
24
22
25
STATISTIC (NumStackPromoted, " Number of objects promoted to the stack" );
@@ -48,9 +51,23 @@ class StackPromoter {
48
51
SILFunction *F;
49
52
EscapeAnalysis::ConnectionGraph *ConGraph;
50
53
DominanceInfo *DT;
51
- PostDominanceInfo *PDT;
52
54
EscapeAnalysis *EA;
53
55
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
+
54
71
// Pseudo-functions for (de-)allocating array buffers on the stack.
55
72
56
73
SILFunction *BufferAllocFunc = nullptr ;
@@ -125,25 +142,41 @@ class StackPromoter {
125
142
}
126
143
127
144
bool strictlyPostDominates (SILBasicBlock *A, SILBasicBlock *B) {
128
- return A != B && PDT->dominates (A, 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);
129
152
}
130
153
131
154
SILBasicBlock *getImmediatePostDom (SILBasicBlock *BB) {
132
- auto *Node = PDT->getNode (BB);
155
+ calculatePostDomTree ();
156
+ auto *Node = PostDomTree.getNode (BB);
133
157
if (!Node)
134
158
return nullptr ;
135
159
auto *IDomNode = Node->getIDom ();
136
160
if (!IDomNode)
137
161
return nullptr ;
138
162
return IDomNode->getBlock ();
139
163
}
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
+ }
140
173
141
174
public:
142
175
143
176
StackPromoter (SILFunction *F, EscapeAnalysis::ConnectionGraph *ConGraph,
144
- DominanceInfo *DT, PostDominanceInfo *PDT,
145
- EscapeAnalysis *EA) :
146
- F (F), ConGraph(ConGraph), DT(DT), PDT(PDT), EA(EA ) { }
177
+ DominanceInfo *DT, EscapeAnalysis *EA) :
178
+ F (F), ConGraph(ConGraph), DT(DT), EA(EA), PostDomTree( true ),
179
+ PostDomTreeValid ( false ) { }
147
180
148
181
// / What did the optimization change?
149
182
enum class ChangeState {
@@ -152,6 +185,8 @@ class StackPromoter {
152
185
Calls
153
186
};
154
187
188
+ SILFunction *getFunction () const { return F; }
189
+
155
190
// / The main entry point for the optimization.
156
191
ChangeState promote ();
157
192
};
@@ -284,6 +319,87 @@ SILFunction *StackPromoter::getBufferDeallocFunc(SILFunction *OrigFunc,
284
319
return BufferDeallocFunc;
285
320
}
286
321
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
+
287
403
bool StackPromoter::canPromoteAlloc (SILInstruction *AI,
288
404
SILInstruction *&AllocInsertionPoint,
289
405
SILInstruction *&DeallocInsertionPoint) {
@@ -394,7 +510,7 @@ bool StackPromoter::canPromoteAlloc(SILInstruction *AI,
394
510
if (!Alloc)
395
511
return false ;
396
512
// This should always be the case, but let's be on the safe side.
397
- if (!PDT-> dominates (StartBlock, Alloc->getParent ()))
513
+ if (!postDominates (StartBlock, Alloc->getParent ()))
398
514
return false ;
399
515
AllocInsertionPoint = Alloc;
400
516
StackDepth++;
@@ -466,20 +582,18 @@ class StackPromotion : public SILFunctionTransform {
466
582
467
583
auto *EA = PM->getAnalysis <EscapeAnalysis>();
468
584
auto *DA = PM->getAnalysis <DominanceAnalysis>();
469
- auto *PDA = PM->getAnalysis <PostDominanceAnalysis>();
470
585
471
586
SILFunction *F = getFunction ();
472
587
if (auto *ConGraph = EA->getConnectionGraph (F)) {
473
- StackPromoter promoter (F, ConGraph, DA->get (F), PDA-> get (F), EA);
588
+ StackPromoter promoter (F, ConGraph, DA->get (F), EA);
474
589
switch (promoter.promote ()) {
475
590
case StackPromoter::ChangeState::None:
476
591
break ;
477
592
case StackPromoter::ChangeState::Insts:
478
593
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
479
594
break ;
480
- case StackPromoter::ChangeState::Calls: {
595
+ case StackPromoter::ChangeState::Calls:
481
596
invalidateAnalysis (SILAnalysis::InvalidationKind::CallsAndInstructions);
482
- }
483
597
break ;
484
598
}
485
599
}
0 commit comments