@@ -79,6 +79,10 @@ class SimplifyCFG {
79
79
llvm::SmallDenseMap<SILBasicBlock *, unsigned , 32 > WorklistMap;
80
80
// Keep track of loop headers - we don't want to jump-thread through them.
81
81
SmallPtrSet<SILBasicBlock *, 32 > LoopHeaders;
82
+ // The set of cloned loop headers to avoid infinite loop peeling. Blocks in
83
+ // this set may or may not still be LoopHeaders.
84
+ // (ultimately this can be used to eliminate findLoopHeaders)
85
+ SmallPtrSet<SILBasicBlock *, 4 > ClonedLoopHeaders;
82
86
// The cost (~ number of copied instructions) of jump threading per basic
83
87
// block. Used to prevent infinite jump threading loops.
84
88
llvm::SmallDenseMap<SILBasicBlock *, int , 8 > JumpThreadingCost;
@@ -126,6 +130,16 @@ class SimplifyCFG {
126
130
}
127
131
128
132
private:
133
+ // Called when \p newBlock inherits the former predecessors of \p
134
+ // oldBlock. e.g. if \p oldBlock was a loop header, then newBlock is now a
135
+ // loop header.
136
+ void substitutedBlockPreds (SILBasicBlock *oldBlock, SILBasicBlock *newBlock) {
137
+ if (LoopHeaders.count (oldBlock))
138
+ LoopHeaders.insert (newBlock);
139
+ if (ClonedLoopHeaders.count (oldBlock))
140
+ ClonedLoopHeaders.insert (newBlock);
141
+ }
142
+
129
143
void clearWorklist () {
130
144
WorklistMap.clear ();
131
145
WorklistList.clear ();
@@ -171,8 +185,10 @@ class SimplifyCFG {
171
185
// Remove it from the map as well.
172
186
WorklistMap.erase (It);
173
187
174
- if (LoopHeaders.count (BB))
188
+ if (LoopHeaders.count (BB)) {
175
189
LoopHeaders.erase (BB);
190
+ ClonedLoopHeaders.erase (BB);
191
+ }
176
192
}
177
193
178
194
bool simplifyBlocks ();
@@ -1083,10 +1099,13 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
1083
1099
return false ;
1084
1100
1085
1101
// Don't jump thread through a potential header - this can produce irreducible
1086
- // control flow. Still, we make an exception for switch_enum .
1102
+ // control flow and lead to infinite loop peeling .
1087
1103
bool DestIsLoopHeader = (LoopHeaders.count (DestBB) != 0 );
1088
1104
if (DestIsLoopHeader) {
1089
- if (!isa<SwitchEnumInst>(destTerminator))
1105
+ // Make an exception for switch_enum, but only if it's block was not already
1106
+ // peeled out of it's original loop. In that case, further jump threading
1107
+ // can accomplish nothing, and the loop will be infinitely peeled.
1108
+ if (!isa<SwitchEnumInst>(destTerminator) || ClonedLoopHeaders.count (DestBB))
1090
1109
return false ;
1091
1110
}
1092
1111
@@ -1132,8 +1151,14 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
1132
1151
1133
1152
// If we jump-thread a switch_enum in the loop header, we have to recalculate
1134
1153
// the loop header info.
1135
- if (DestIsLoopHeader)
1154
+ //
1155
+ // FIXME: findLoopHeaders should not be called repeatedly during simplify-cfg
1156
+ // iteration. It is a whole-function analysis! It also does no nothing help to
1157
+ // avoid infinite loop peeling.
1158
+ if (DestIsLoopHeader) {
1159
+ ClonedLoopHeaders.insert (Cloner.getNewBB ());
1136
1160
findLoopHeaders ();
1161
+ }
1137
1162
1138
1163
++NumJumpThreads;
1139
1164
return true ;
@@ -1372,8 +1397,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
1372
1397
for (auto &Succ : remainingBlock->getSuccessors ())
1373
1398
addToWorklist (Succ);
1374
1399
1375
- if (LoopHeaders.count (deletedBlock))
1376
- LoopHeaders.insert (remainingBlock);
1400
+ substitutedBlockPreds (deletedBlock, remainingBlock);
1377
1401
1378
1402
auto Iter = JumpThreadingCost.find (deletedBlock);
1379
1403
if (Iter != JumpThreadingCost.end ()) {
@@ -1397,8 +1421,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
1397
1421
trampolineDest.newSourceBranchArgs );
1398
1422
// Eliminating the trampoline can expose opportunities to improve the
1399
1423
// new block we branch to.
1400
- if (LoopHeaders.count (DestBB))
1401
- LoopHeaders.insert (trampolineDest.destBB );
1424
+ substitutedBlockPreds (DestBB, trampolineDest.destBB );
1402
1425
1403
1426
addToWorklist (trampolineDest.destBB );
1404
1427
BI->eraseFromParent ();
@@ -1583,8 +1606,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
1583
1606
BI->getTrueBBCount (), BI->getFalseBBCount ());
1584
1607
BI->eraseFromParent ();
1585
1608
1586
- if (LoopHeaders.count (TrueSide))
1587
- LoopHeaders.insert (ThisBB);
1609
+ substitutedBlockPreds (TrueSide, ThisBB);
1588
1610
removeIfDead (TrueSide);
1589
1611
addToWorklist (ThisBB);
1590
1612
return true ;
@@ -1602,8 +1624,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
1602
1624
falseTrampolineDest.destBB , falseTrampolineDest.newSourceBranchArgs ,
1603
1625
BI->getTrueBBCount (), BI->getFalseBBCount ());
1604
1626
BI->eraseFromParent ();
1605
- if (LoopHeaders.count (FalseSide))
1606
- LoopHeaders.insert (ThisBB);
1627
+ substitutedBlockPreds (FalseSide, ThisBB);
1607
1628
removeIfDead (FalseSide);
1608
1629
addToWorklist (ThisBB);
1609
1630
return true ;
0 commit comments