@@ -1563,6 +1563,42 @@ static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) {
1563
1563
SCC.initialize(Nodes);
1564
1564
}
1565
1565
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
+ }
1566
1602
/// Replace a call to llvm.coro.prepare.retcon.
1567
1603
static void replacePrepare(CallInst *Prepare, CallGraph &CG) {
1568
1604
auto CastFn = Prepare->getArgOperand(0); // as an i8*
@@ -1618,6 +1654,19 @@ static void replacePrepare(CallInst *Prepare, CallGraph &CG) {
1618
1654
}
1619
1655
}
1620
1656
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
+
1621
1670
/// Remove calls to llvm.coro.prepare.retcon, a barrier meant to prevent
1622
1671
/// IPO from operating on calls to a retcon coroutine before it's been
1623
1672
/// split. This is only safe to do after we've split all retcon
@@ -1656,7 +1705,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
1656
1705
return PreservedAnalyses::all();
1657
1706
1658
1707
// 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");
1660
1709
if (PrepareFn && PrepareFn->use_empty())
1661
1710
PrepareFn = nullptr;
1662
1711
@@ -1670,8 +1719,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
1670
1719
return PreservedAnalyses::all();
1671
1720
1672
1721
if (Coroutines.empty())
1673
- llvm_unreachable("new pass manager cannot yet handle "
1674
- "'llvm.coro.prepare.retcon'");
1722
+ replaceAllPrepares(PrepareFn, CG, C);
1675
1723
1676
1724
// Split all the coroutines.
1677
1725
for (LazyCallGraph::Node *N : Coroutines) {
@@ -1704,8 +1752,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
1704
1752
}
1705
1753
1706
1754
if (PrepareFn)
1707
- llvm_unreachable("new pass manager cannot yet handle "
1708
- "'llvm.coro.prepare.retcon'");
1755
+ replaceAllPrepares(PrepareFn, CG, C);
1709
1756
1710
1757
return PreservedAnalyses::none();
1711
1758
}
0 commit comments