@@ -316,9 +316,13 @@ class SingleExitLoopTransformer {
316
316
// / Create a new latch block and clone all the arguments from new header.
317
317
SILBasicBlock *createNewLatch (SILBasicBlock *newHeader);
318
318
319
- // Patch the edges that go to the header and exit blocks to the new header or
320
- // latch block as appropriate. Also, return the map consisting of indices
321
- // assigned to the exit blocks.
319
+ // / Replace the preheader->header edge with preheader->newHeader edge
320
+ // / and update the arguments of preheader to match that of newheader.
321
+ void patchPreheader (SILBasicBlock *newHeader);
322
+
323
+ // / Patch the edges that go to the header and exit blocks to the new header or
324
+ // / latch block as appropriate. Also, return the map consisting of indices
325
+ // / assigned to the exit blocks.
322
326
llvm::DenseMap<SILBasicBlock *, intmax_t >
323
327
patchEdges (SILBasicBlock *newHeader, SILBasicBlock *latchBlock);
324
328
@@ -368,9 +372,18 @@ void SingleExitLoopTransformer::initialize() {
368
372
loop->getExitBlocks (exitBlocks);
369
373
// All the exiting edges need to be rewired.
370
374
loop->getExitEdges (edgesToFix);
371
- // All the edges to the header need to be rewired.
372
- for (SILBasicBlock *headerPred : header->getPredecessorBlocks ()) {
373
- edgesToFix.emplace_back (headerPred, header);
375
+ edgesToFix.emplace_back (latch, header);
376
+ // Split critical edges in edgesToFix before we do any transformations.
377
+ for (auto &edge : edgesToFix) {
378
+ SILBasicBlock *src = const_cast <SILBasicBlock *>(edge.first );
379
+ SILBasicBlock *tgt = const_cast <SILBasicBlock *>(edge.second );
380
+ SILBasicBlock *splitBlock = splitIfCriticalEdge (src, tgt, /* DT*/ nullptr , LI);
381
+ if (splitBlock != nullptr ) {
382
+ // If the edge was critical then splitBlock would have been inserted
383
+ // between src and tgt as follows: src -> splitBlock -> tgt. Therefore,
384
+ // update src as the new edge to patch would be splitBlock -> tgt.
385
+ edge.first = splitBlock;
386
+ }
374
387
}
375
388
376
389
for (const SILBasicBlock *bb : loop->getBlocks ()) {
@@ -502,6 +515,30 @@ SingleExitLoopTransformer::createNewLatch(SILBasicBlock *newHeader) {
502
515
return latchBlock;
503
516
}
504
517
518
+ void SingleExitLoopTransformer::patchPreheader (SILBasicBlock *newHeader) {
519
+ // Update edge
520
+ replaceBranchTarget (preheader->getTerminator (), header, newHeader,
521
+ /* preserveArgs*/ true );
522
+ SILBuilder builder (preheader->getTerminator ());
523
+ SILLocation location (
524
+ getUserSourceLocation (preheader->getTerminator ()->getDebugLocation ()));
525
+ // Add arguments corresponding to escaping arguments.
526
+ // State from within the loop is not available in the preheader.
527
+ // Simply pass in an undef. This will never be accessed at runtime.
528
+ SmallVector<SILValue, 8 > newArgs;
529
+ for (const SILValue &escapingValue : escapingValues) {
530
+ newArgs.push_back (getUndef (escapingValue->getType ()));
531
+ }
532
+ // `exitIndex` to identify the block to which we exit from the loop.
533
+ newArgs.push_back (createTFIntegerConst (*deviceInfo, builder, location,
534
+ /* bitwidth*/ 32 ,
535
+ /* exitIndex*/ 0 ));
536
+ // `stayInLoop` flag
537
+ newArgs.push_back (createTFIntegerConst (*deviceInfo, builder, location,
538
+ /* bitwidth*/ 1 , true ));
539
+ appendArguments (preheader->getTerminator (), newHeader, newArgs);
540
+ }
541
+
505
542
llvm::DenseMap<SILBasicBlock *, intmax_t >
506
543
SingleExitLoopTransformer::patchEdges (SILBasicBlock *newHeader,
507
544
SILBasicBlock *latchBlock) {
@@ -537,14 +574,7 @@ SingleExitLoopTransformer::patchEdges(SILBasicBlock *newHeader,
537
574
for (const auto &edge : edgesToFix) {
538
575
SILBasicBlock *src = const_cast <SILBasicBlock *>(edge.first );
539
576
SILBasicBlock *tgt = const_cast <SILBasicBlock *>(edge.second );
540
- SILBasicBlock *newTgt = (src == preheader) ? newHeader : latchBlock;
541
- SILBasicBlock *splitBlock = splitIfCriticalEdge (src, tgt, /* DT*/ nullptr , LI);
542
- if (splitBlock != nullptr ) {
543
- // If the edge was critical then splitBlock would have been inserted
544
- // between src and tgt as follows: src -> splitBlock -> tgt. Therefore,
545
- // update src as the new edge to patch would be splitBlock -> tgt.
546
- src = splitBlock;
547
- }
577
+ SILBasicBlock *newTgt = latchBlock;
548
578
bool stayInLoop = loop->contains (tgt);
549
579
replaceBranchTarget (src->getTerminator (), tgt, newTgt,
550
580
/* preserveArgs=*/ stayInLoop);
@@ -564,13 +594,8 @@ SingleExitLoopTransformer::patchEdges(SILBasicBlock *newHeader,
564
594
for (const SILValue &escapingValue : escapingValues) {
565
595
if (DI->properlyDominates (escapingValue, src->getTerminator ())) {
566
596
newArgs.push_back (escapingValue);
567
- } else if (src != preheader) {
568
- // newHeader arguments are available if src is not the preheader.
569
- newArgs.push_back (newHeader->getArgument (argIndex));
570
597
} else {
571
- // State from within the loop is not available in the preheader.
572
- // Simply pass in an undef. This will never be accessed at runtime.
573
- newArgs.push_back (getUndef (escapingValue->getType ()));
598
+ newArgs.push_back (newHeader->getArgument (argIndex));
574
599
}
575
600
++argIndex;
576
601
}
@@ -690,6 +715,8 @@ bool SingleExitLoopTransformer::transform() {
690
715
// Create a new latch block.
691
716
SILBasicBlock *latchBlock = createNewLatch (newHeader);
692
717
718
+ patchPreheader (newHeader);
719
+
693
720
// Patch the edges and return the map consisting of indices assigned
694
721
// to the exit blocks.
695
722
llvm::DenseMap<SILBasicBlock *, intmax_t > exitIndices =
0 commit comments