@@ -1563,6 +1563,42 @@ static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) {
15631563 SCC.initialize (Nodes);
15641564}
15651565
1566+ // / Replace a call to llvm.coro.prepare.retcon.
1567+ static void replacePrepare (CallInst *Prepare, LazyCallGraph &CG,
1568+ LazyCallGraph::SCC &C) {
1569+ auto CastFn = Prepare->getArgOperand (0 ); // as an i8*
1570+ auto Fn = CastFn->stripPointerCasts (); // as its original type
1571+
1572+ // Attempt to peephole this pattern:
1573+ // %0 = bitcast [[TYPE]] @some_function to i8*
1574+ // %1 = call @llvm.coro.prepare.retcon(i8* %0)
1575+ // %2 = bitcast %1 to [[TYPE]]
1576+ // ==>
1577+ // %2 = @some_function
1578+ for (auto UI = Prepare->use_begin (), UE = Prepare->use_end (); UI != UE;) {
1579+ // Look for bitcasts back to the original function type.
1580+ auto *Cast = dyn_cast<BitCastInst>((UI++)->getUser ());
1581+ if (!Cast || Cast->getType () != Fn->getType ())
1582+ continue ;
1583+
1584+ // Replace and remove the cast.
1585+ Cast->replaceAllUsesWith (Fn);
1586+ Cast->eraseFromParent ();
1587+ }
1588+
1589+ // Replace any remaining uses with the function as an i8*.
1590+ // This can never directly be a callee, so we don't need to update CG.
1591+ Prepare->replaceAllUsesWith (CastFn);
1592+ Prepare->eraseFromParent ();
1593+
1594+ // Kill dead bitcasts.
1595+ while (auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
1596+ if (!Cast->use_empty ())
1597+ break ;
1598+ CastFn = Cast->getOperand (0 );
1599+ Cast->eraseFromParent ();
1600+ }
1601+ }
15661602// / Replace a call to llvm.coro.prepare.retcon.
15671603static void replacePrepare (CallInst *Prepare, CallGraph &CG) {
15681604 auto CastFn = Prepare->getArgOperand (0 ); // as an i8*
@@ -1618,6 +1654,19 @@ static void replacePrepare(CallInst *Prepare, CallGraph &CG) {
16181654 }
16191655}
16201656
1657+ static bool replaceAllPrepares (Function *PrepareFn, LazyCallGraph &CG,
1658+ LazyCallGraph::SCC &C) {
1659+ bool Changed = false ;
1660+ for (auto PI = PrepareFn->use_begin (), PE = PrepareFn->use_end (); PI != PE;) {
1661+ // Intrinsics can only be used in calls.
1662+ auto *Prepare = cast<CallInst>((PI++)->getUser ());
1663+ replacePrepare (Prepare, CG, C);
1664+ Changed = true ;
1665+ }
1666+
1667+ return Changed;
1668+ }
1669+
16211670// / Remove calls to llvm.coro.prepare.retcon, a barrier meant to prevent
16221671// / IPO from operating on calls to a retcon coroutine before it's been
16231672// / split. This is only safe to do after we've split all retcon
@@ -1656,7 +1705,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
16561705 return PreservedAnalyses::all ();
16571706
16581707 // Check for uses of llvm.coro.prepare.retcon.
1659- const auto *PrepareFn = M.getFunction (" llvm.coro.prepare.retcon" );
1708+ auto *PrepareFn = M.getFunction (" llvm.coro.prepare.retcon" );
16601709 if (PrepareFn && PrepareFn->use_empty ())
16611710 PrepareFn = nullptr ;
16621711
@@ -1670,8 +1719,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
16701719 return PreservedAnalyses::all ();
16711720
16721721 if (Coroutines.empty ())
1673- llvm_unreachable (" new pass manager cannot yet handle "
1674- " 'llvm.coro.prepare.retcon'" );
1722+ replaceAllPrepares (PrepareFn, CG, C);
16751723
16761724 // Split all the coroutines.
16771725 for (LazyCallGraph::Node *N : Coroutines) {
@@ -1704,8 +1752,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
17041752 }
17051753
17061754 if (PrepareFn)
1707- llvm_unreachable (" new pass manager cannot yet handle "
1708- " 'llvm.coro.prepare.retcon'" );
1755+ replaceAllPrepares (PrepareFn, CG, C);
17091756
17101757 return PreservedAnalyses::none ();
17111758}
0 commit comments