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