@@ -78,6 +78,10 @@ class SimplifyCFG {
7878 llvm::SmallDenseMap<SILBasicBlock *, unsigned , 32 > WorklistMap;
7979 // Keep track of loop headers - we don't want to jump-thread through them.
8080 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;
8185 // The cost (~ number of copied instructions) of jump threading per basic
8286 // block. Used to prevent infinite jump threading loops.
8387 llvm::SmallDenseMap<SILBasicBlock *, int , 8 > JumpThreadingCost;
@@ -125,6 +129,16 @@ class SimplifyCFG {
125129 }
126130
127131private:
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+
128142 void clearWorklist () {
129143 WorklistMap.clear ();
130144 WorklistList.clear ();
@@ -170,8 +184,10 @@ class SimplifyCFG {
170184 // Remove it from the map as well.
171185 WorklistMap.erase (It);
172186
173- if (LoopHeaders.count (BB))
187+ if (LoopHeaders.count (BB)) {
174188 LoopHeaders.erase (BB);
189+ ClonedLoopHeaders.erase (BB);
190+ }
175191 }
176192
177193 bool simplifyBlocks ();
@@ -1082,10 +1098,13 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
10821098 return false ;
10831099
10841100 // 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 .
10861102 bool DestIsLoopHeader = (LoopHeaders.count (DestBB) != 0 );
10871103 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))
10891108 return false ;
10901109 }
10911110
@@ -1127,8 +1146,14 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
11271146
11281147 // If we jump-thread a switch_enum in the loop header, we have to recalculate
11291148 // 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 ());
11311155 findLoopHeaders ();
1156+ }
11321157
11331158 ++NumJumpThreads;
11341159 return true ;
@@ -1375,8 +1400,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
13751400 for (auto &Succ : remainingBlock->getSuccessors ())
13761401 addToWorklist (Succ);
13771402
1378- if (LoopHeaders.count (deletedBlock))
1379- LoopHeaders.insert (remainingBlock);
1403+ substitutedBlockPreds (deletedBlock, remainingBlock);
13801404
13811405 auto Iter = JumpThreadingCost.find (deletedBlock);
13821406 if (Iter != JumpThreadingCost.end ()) {
@@ -1400,8 +1424,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
14001424 trampolineDest.newSourceBranchArgs );
14011425 // Eliminating the trampoline can expose opportunities to improve the
14021426 // new block we branch to.
1403- if (LoopHeaders.count (DestBB))
1404- LoopHeaders.insert (BB);
1427+ substitutedBlockPreds (DestBB, trampolineDest.destBB );
14051428
14061429 addToWorklist (trampolineDest.destBB );
14071430 BI->eraseFromParent ();
@@ -1586,8 +1609,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
15861609 BI->getTrueBBCount (), BI->getFalseBBCount ());
15871610 BI->eraseFromParent ();
15881611
1589- if (LoopHeaders.count (TrueSide))
1590- LoopHeaders.insert (ThisBB);
1612+ substitutedBlockPreds (TrueSide, ThisBB);
15911613 removeIfDead (TrueSide);
15921614 addToWorklist (ThisBB);
15931615 return true ;
@@ -1605,8 +1627,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
16051627 falseTrampolineDest.destBB , falseTrampolineDest.newSourceBranchArgs ,
16061628 BI->getTrueBBCount (), BI->getFalseBBCount ());
16071629 BI->eraseFromParent ();
1608- if (LoopHeaders.count (FalseSide))
1609- LoopHeaders.insert (ThisBB);
1630+ substitutedBlockPreds (FalseSide, ThisBB);
16101631 removeIfDead (FalseSide);
16111632 addToWorklist (ThisBB);
16121633 return true ;
0 commit comments