@@ -1567,50 +1567,70 @@ static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape,
1567
1567
}
1568
1568
1569
1569
for (Instruction &I : instructions (F)) {
1570
- if (!isa<AllocaInst>(&I))
1570
+ AllocaInst* AI = dyn_cast<AllocaInst>(&I);
1571
+ if (!AI)
1571
1572
continue ;
1572
1573
1573
1574
for (BasicBlock *DomBB : DomSet) {
1574
1575
bool Valid = true ;
1575
- SmallVector<Instruction *, 1 > BCInsts ;
1576
+ SmallVector<Instruction *, 1 > Lifetimes ;
1576
1577
1577
- auto isUsedByLifetimeStart = [&](Instruction *I) {
1578
- if (isa<BitCastInst>(I) && I->hasOneUse ())
1579
- if (auto *IT = dyn_cast<IntrinsicInst>(I->user_back ()))
1580
- return IT->getIntrinsicID () == Intrinsic::lifetime_start;
1578
+ auto isLifetimeStart = [](Instruction* I) {
1579
+ if (auto * II = dyn_cast<IntrinsicInst>(I))
1580
+ return II->getIntrinsicID () == Intrinsic::lifetime_start;
1581
1581
return false ;
1582
1582
};
1583
1583
1584
- for (User *U : I.users ()) {
1584
+ auto collectLifetimeStart = [&](Instruction *U, AllocaInst *AI) {
1585
+ if (isLifetimeStart (U)) {
1586
+ Lifetimes.push_back (U);
1587
+ return true ;
1588
+ }
1589
+ if (!U->hasOneUse () || U->stripPointerCasts () != AI)
1590
+ return false ;
1591
+ if (isLifetimeStart (U->user_back ())) {
1592
+ Lifetimes.push_back (U->user_back ());
1593
+ return true ;
1594
+ }
1595
+ return false ;
1596
+ };
1597
+
1598
+ for (User *U : AI->users ()) {
1585
1599
Instruction *UI = cast<Instruction>(U);
1586
1600
// For all users except lifetime.start markers, if they are all
1587
1601
// dominated by one of the basic blocks and do not cross
1588
1602
// suspend points as well, then there is no need to spill the
1589
1603
// instruction.
1590
1604
if (!DT.dominates (DomBB, UI->getParent ()) ||
1591
- Checker.isDefinitionAcrossSuspend (DomBB, U )) {
1592
- // Skip bitcast used by lifetime.start markers.
1593
- if ( isUsedByLifetimeStart (UI)) {
1594
- BCInsts. push_back (UI);
1605
+ Checker.isDefinitionAcrossSuspend (DomBB, UI )) {
1606
+ // Skip lifetime.start, GEP and bitcast used by lifetime.start
1607
+ // markers.
1608
+ if ( collectLifetimeStart (UI, AI))
1595
1609
continue ;
1596
- }
1597
1610
Valid = false ;
1598
1611
break ;
1599
1612
}
1600
1613
}
1601
1614
// Sink lifetime.start markers to dominate block when they are
1602
1615
// only used outside the region.
1603
- if (Valid && BCInsts.size () != 0 ) {
1604
- auto *NewBitcast = BCInsts[0 ]->clone ();
1605
- auto *NewLifetime = cast<Instruction>(BCInsts[0 ]->user_back ())->clone ();
1606
- NewLifetime->replaceUsesOfWith (BCInsts[0 ], NewBitcast);
1607
- NewBitcast->insertBefore (DomBB->getTerminator ());
1616
+ if (Valid && Lifetimes.size () != 0 ) {
1617
+ // May be AI itself, when the type of AI is i8*
1618
+ auto *NewBitCast = [&](AllocaInst *AI) -> Value* {
1619
+ if (isa<AllocaInst>(Lifetimes[0 ]->getOperand (1 )))
1620
+ return AI;
1621
+ auto *Int8PtrTy = Type::getInt8PtrTy (F.getContext ());
1622
+ return CastInst::Create (Instruction::BitCast, AI, Int8PtrTy, " " ,
1623
+ DomBB->getTerminator ());
1624
+ }(AI);
1625
+
1626
+ auto *NewLifetime = Lifetimes[0 ]->clone ();
1627
+ NewLifetime->replaceUsesOfWith (NewLifetime->getOperand (1 ), NewBitCast);
1608
1628
NewLifetime->insertBefore (DomBB->getTerminator ());
1609
1629
1610
1630
// All the outsided lifetime.start markers are no longer necessary.
1611
- for (Instruction *S : BCInsts) {
1612
- S->user_back ()-> eraseFromParent ();
1613
- }
1631
+ for (Instruction *S : Lifetimes)
1632
+ S->eraseFromParent ();
1633
+
1614
1634
break ;
1615
1635
}
1616
1636
}
@@ -1676,14 +1696,14 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
1676
1696
if (!II || II->getIntrinsicID () != Intrinsic::lifetime_start)
1677
1697
continue ;
1678
1698
1679
- if (auto *OpInst = dyn_cast<BitCastInst>(I. getOperand (1 )))
1680
- if (auto *AI = dyn_cast<AllocaInst>(OpInst->getOperand ( 0 ))) {
1699
+ if (auto *OpInst = dyn_cast<Instruction>(II-> getOperand (1 ))) {
1700
+ if (auto *AI = dyn_cast<AllocaInst>(OpInst->stripPointerCasts ( ))) {
1681
1701
1682
1702
if (LifetimeMap.find (AI) == LifetimeMap.end ())
1683
1703
LifetimeMap[AI] = std::make_unique<LifetimeStart>();
1684
-
1685
- LifetimeMap[AI]->insert (OpInst);
1704
+ LifetimeMap[AI]->insert (isa<AllocaInst>(OpInst) ? II : OpInst);
1686
1705
}
1706
+ }
1687
1707
}
1688
1708
1689
1709
// Collect the spills for arguments and other not-materializable values.
0 commit comments