@@ -117,6 +117,15 @@ class SILGlobalOpt {
117
117
118
118
// / Returns true if we think that \p CurBB is inside a loop.
119
119
bool isInLoop (SILBasicBlock *CurBB);
120
+
121
+ // / Given that we are trying to place initializers in new locations, see if
122
+ // / we can hoist the passed in apply \p AI out of any loops that it is
123
+ // / currently within.
124
+ ApplyInst *getHoistedApplyForInitializer (
125
+ ApplyInst *AI, DominanceInfo *DT, SILFunction *InitF,
126
+ SILFunction *ParentF,
127
+ llvm::DenseMap<SILFunction *, ApplyInst *> &ParentFuncs);
128
+
120
129
void placeInitializers (SILFunction *InitF, ArrayRef<ApplyInst *> Calls);
121
130
122
131
// / Update UnhandledOnceCallee and InitializerCount by going through all
@@ -438,6 +447,48 @@ static bool isAvailabilityCheckOnDomPath(SILBasicBlock *From, SILBasicBlock *To,
438
447
}
439
448
}
440
449
450
+ ApplyInst *SILGlobalOpt::getHoistedApplyForInitializer (
451
+ ApplyInst *AI, DominanceInfo *DT, SILFunction *InitF, SILFunction *ParentF,
452
+ llvm::DenseMap<SILFunction *, ApplyInst *> &ParentFuncs) {
453
+ auto PFI = ParentFuncs.find (ParentF);
454
+ if (PFI == ParentFuncs.end ()) {
455
+ ParentFuncs[ParentF] = AI;
456
+
457
+ // It's the first time we found a call to InitF in this function, so we
458
+ // try to hoist it out of any loop.
459
+ return AI;
460
+ }
461
+
462
+ // Found a replacement for this init call. Ensure the replacement dominates
463
+ // the original call site.
464
+ ApplyInst *CommonAI = PFI->second ;
465
+ assert (
466
+ cast<FunctionRefInst>(CommonAI->getCallee ())->getReferencedFunction () ==
467
+ InitF &&
468
+ " ill-formed global init call" );
469
+ SILBasicBlock *DomBB =
470
+ DT->findNearestCommonDominator (AI->getParent (), CommonAI->getParent ());
471
+
472
+ // We must not move initializers around availability-checks.
473
+ if (isAvailabilityCheckOnDomPath (DomBB, CommonAI->getParent (), DT))
474
+ return nullptr ;
475
+
476
+ ApplyInst *Result = nullptr ;
477
+ if (DomBB != CommonAI->getParent ()) {
478
+ CommonAI->moveBefore (&*DomBB->begin ());
479
+ placeFuncRef (CommonAI, DT);
480
+
481
+ // Try to hoist the existing AI again if we move it to another block,
482
+ // e.g. from a loop exit into the loop.
483
+ Result = CommonAI;
484
+ }
485
+
486
+ AI->replaceAllUsesWith (CommonAI);
487
+ AI->eraseFromParent ();
488
+ HasChanged = true ;
489
+ return Result;
490
+ }
491
+
441
492
// / Optimize placement of initializer calls given a list of calls to the
442
493
// / same initializer. All original initialization points must be dominated by
443
494
// / the final initialization calls.
@@ -455,72 +506,46 @@ void SILGlobalOpt::placeInitializers(SILFunction *InitF,
455
506
assert (AI->getNumArguments () == 0 && " ill-formed global init call" );
456
507
assert (cast<FunctionRefInst>(AI->getCallee ())->getReferencedFunction ()
457
508
== InitF && " wrong init call" );
458
-
459
509
SILFunction *ParentF = AI->getFunction ();
460
510
DominanceInfo *DT = DA->get (ParentF);
461
- auto PFI = ParentFuncs.find (ParentF);
462
- ApplyInst *HoistAI = nullptr ;
463
- if (PFI != ParentFuncs.end ()) {
464
- // Found a replacement for this init call.
465
- // Ensure the replacement dominates the original call site.
466
- ApplyInst *CommonAI = PFI->second ;
467
- assert (cast<FunctionRefInst>(CommonAI->getCallee ())
468
- ->getReferencedFunction () == InitF &&
469
- " ill-formed global init call" );
470
- SILBasicBlock *DomBB =
471
- DT->findNearestCommonDominator (AI->getParent (), CommonAI->getParent ());
472
-
473
- // We must not move initializers around availability-checks.
474
- if (!isAvailabilityCheckOnDomPath (DomBB, CommonAI->getParent (), DT)) {
475
- if (DomBB != CommonAI->getParent ()) {
476
- CommonAI->moveBefore (&*DomBB->begin ());
477
- placeFuncRef (CommonAI, DT);
478
-
479
- // Try to hoist the existing AI again if we move it to another block,
480
- // e.g. from a loop exit into the loop.
481
- HoistAI = CommonAI;
482
- }
483
- AI->replaceAllUsesWith (CommonAI);
484
- AI->eraseFromParent ();
485
- HasChanged = true ;
486
- }
487
- } else {
488
- ParentFuncs[ParentF] = AI;
489
-
490
- // It's the first time we found a call to InitF in this function, so we
491
- // try to hoist it out of any loop.
492
- HoistAI = AI;
511
+ ApplyInst *HoistAI =
512
+ getHoistedApplyForInitializer (AI, DT, InitF, ParentF, ParentFuncs);
513
+
514
+ // If we were unable to find anything, just go onto the next apply.
515
+ if (!HoistAI) {
516
+ continue ;
493
517
}
494
- if (HoistAI) {
495
- // Move this call to the outermost loop preheader.
496
- SILBasicBlock *BB = HoistAI->getParent ();
497
- typedef llvm::DomTreeNodeBase<SILBasicBlock> DomTreeNode;
498
- DomTreeNode *Node = DT->getNode (BB);
499
- while (Node) {
500
- SILBasicBlock *DomParentBB = Node->getBlock ();
501
- if (isAvailabilityCheck (DomParentBB)) {
502
- DEBUG (llvm::dbgs () << " don't hoist above availability check at bb"
503
- << DomParentBB->getDebugID () << " \n " );
504
- break ;
505
- }
506
- BB = DomParentBB;
507
- if (!isInLoop (BB))
508
- break ;
509
- Node = Node->getIDom ();
510
- }
511
- if (BB == HoistAI->getParent ()) {
512
- // BB is either unreachable or not in a loop.
513
- DEBUG (llvm::dbgs () << " skipping (not in a loop): " << *HoistAI
514
- << " in " << HoistAI->getFunction ()->getName () << " \n " );
515
- }
516
- else {
517
- DEBUG (llvm::dbgs () << " hoisting: " << *HoistAI
518
- << " in " << HoistAI->getFunction ()->getName () << " \n " );
519
- HoistAI->moveBefore (&*BB->begin ());
520
- placeFuncRef (HoistAI, DT);
521
- HasChanged = true ;
518
+
519
+ // Otherwise, move this call to the outermost loop preheader.
520
+ SILBasicBlock *BB = HoistAI->getParent ();
521
+ typedef llvm::DomTreeNodeBase<SILBasicBlock> DomTreeNode;
522
+ DomTreeNode *Node = DT->getNode (BB);
523
+ while (Node) {
524
+ SILBasicBlock *DomParentBB = Node->getBlock ();
525
+ if (isAvailabilityCheck (DomParentBB)) {
526
+ DEBUG (llvm::dbgs () << " don't hoist above availability check at bb"
527
+ << DomParentBB->getDebugID () << " \n " );
528
+ break ;
522
529
}
530
+ BB = DomParentBB;
531
+ if (!isInLoop (BB))
532
+ break ;
533
+ Node = Node->getIDom ();
523
534
}
535
+
536
+ if (BB == HoistAI->getParent ()) {
537
+ // BB is either unreachable or not in a loop.
538
+ DEBUG (llvm::dbgs () << " skipping (not in a loop): " << *HoistAI
539
+ << " in " << HoistAI->getFunction ()->getName ()
540
+ << " \n " );
541
+ continue ;
542
+ }
543
+
544
+ DEBUG (llvm::dbgs () << " hoisting: " << *HoistAI << " in "
545
+ << HoistAI->getFunction ()->getName () << " \n " );
546
+ HoistAI->moveBefore (&*BB->begin ());
547
+ placeFuncRef (HoistAI, DT);
548
+ HasChanged = true ;
524
549
}
525
550
}
526
551
0 commit comments