@@ -753,11 +753,6 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
753
753
SmallPtrSet<ReturnInst *, 2 > &ReturnInsts = It.second ;
754
754
Value *RV = It.first ;
755
755
756
- // Ignore dead ReturnValues.
757
- if (LivenessAA &&
758
- !LivenessAA->isLiveInstSet (ReturnInsts.begin (), ReturnInsts.end ()))
759
- continue ;
760
-
761
756
LLVM_DEBUG (dbgs () << " [AAReturnedValues] Potentially returned value " << *RV
762
757
<< " \n " );
763
758
@@ -771,6 +766,14 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
771
766
// sites will be removed and we will fix the information for this state.
772
767
HasCallSite = true ;
773
768
769
+ // Ignore dead ReturnValues.
770
+ if (LivenessAA &&
771
+ !LivenessAA->isLiveInstSet (ReturnInsts.begin (), ReturnInsts.end ())) {
772
+ LLVM_DEBUG (dbgs () << " [AAReturnedValues] all returns are assumed dead, "
773
+ " skip it for now\n " );
774
+ continue ;
775
+ }
776
+
774
777
// Try to find a assumed unique return value for the called function.
775
778
auto *RetCSAA = A.getAAFor <AAReturnedValuesImpl>(*this , *RV);
776
779
if (!RetCSAA) {
@@ -1533,12 +1536,20 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
1533
1536
ToBeExploredPaths.insert (&(F.getEntryBlock ().front ()));
1534
1537
AssumedLiveBlocks.insert (&(F.getEntryBlock ()));
1535
1538
for (size_t i = 0 ; i < ToBeExploredPaths.size (); ++i)
1536
- explorePath (A, ToBeExploredPaths[i]);
1539
+ if (const Instruction *NextNoReturnI =
1540
+ findNextNoReturn (A, ToBeExploredPaths[i]))
1541
+ NoReturnCalls.insert (NextNoReturnI);
1537
1542
}
1538
1543
1539
- // / Explores new instructions starting from \p I. If instruction is dead, stop
1540
- // / and return true if it discovered a new instruction.
1541
- bool explorePath (Attributor &A, Instruction *I);
1544
+ // / Find the next assumed noreturn instruction in the block of \p I starting
1545
+ // / from, thus including, \p I.
1546
+ // /
1547
+ // / The caller is responsible to monitor the ToBeExploredPaths set as new
1548
+ // / instructions discovered in other basic block will be placed in there.
1549
+ // /
1550
+ // / \returns The next assumed noreturn instructions in the block of \p I
1551
+ // / starting from, thus including, \p I.
1552
+ const Instruction *findNextNoReturn (Attributor &A, const Instruction *I);
1542
1553
1543
1554
const std::string getAsStr () const override {
1544
1555
return " LiveBBs(" + std::to_string (AssumedLiveBlocks.size ()) + " /" +
@@ -1552,18 +1563,31 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
1552
1563
1553
1564
ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
1554
1565
1555
- for (Instruction *I : NoReturnCalls) {
1566
+ for (const Instruction *NRC : NoReturnCalls) {
1567
+ Instruction *I = const_cast <Instruction *>(NRC);
1556
1568
BasicBlock *BB = I->getParent ();
1569
+ Instruction *SplitPos = I->getNextNode ();
1557
1570
1558
- // / Invoke is replaced with a call and unreachable is placed after it.
1559
1571
if (auto *II = dyn_cast<InvokeInst>(I)) {
1560
- changeToCall (II);
1561
- changeToUnreachable (BB->getTerminator (), /* UseLLVMTrap */ false );
1562
- LLVM_DEBUG (dbgs () << " [AAIsDead] Replaced invoke with call inst\n " );
1563
- continue ;
1572
+ // / Invoke is replaced with a call and unreachable is placed after it if
1573
+ // / the callee is nounwind and noreturn. Otherwise, we keep the invoke
1574
+ // / and only place an unreachable in the normal successor.
1575
+ if (Function *Callee = II->getCalledFunction ()) {
1576
+ auto *AANoUnw = A.getAAFor <AANoUnwind>(*this , *Callee);
1577
+ if (Callee->hasFnAttribute (Attribute::NoUnwind) ||
1578
+ (AANoUnw && AANoUnw->isAssumedNoUnwind ())) {
1579
+ LLVM_DEBUG (dbgs () << " [AAIsDead] Replace invoke with call inst\n " );
1580
+ changeToCall (II);
1581
+ changeToUnreachable (BB->getTerminator (), /* UseLLVMTrap */ false );
1582
+ continue ;
1583
+ }
1584
+ }
1585
+
1586
+ BB = II->getNormalDest ();
1587
+ SplitPos = &BB->front ();
1564
1588
}
1565
1589
1566
- SplitBlock (BB, I-> getNextNode () );
1590
+ SplitBlock (BB, SplitPos );
1567
1591
changeToUnreachable (BB->getTerminator (), /* UseLLVMTrap */ false );
1568
1592
HasChanged = ChangeStatus::CHANGED;
1569
1593
}
@@ -1575,7 +1599,7 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
1575
1599
ChangeStatus updateImpl (Attributor &A) override ;
1576
1600
1577
1601
// / See AAIsDead::isAssumedDead(BasicBlock *).
1578
- bool isAssumedDead (BasicBlock *BB) const override {
1602
+ bool isAssumedDead (const BasicBlock *BB) const override {
1579
1603
assert (BB->getParent () == &getAnchorScope () &&
1580
1604
" BB must be in the same anchor scope function." );
1581
1605
@@ -1585,12 +1609,12 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
1585
1609
}
1586
1610
1587
1611
// / See AAIsDead::isKnownDead(BasicBlock *).
1588
- bool isKnownDead (BasicBlock *BB) const override {
1612
+ bool isKnownDead (const BasicBlock *BB) const override {
1589
1613
return getKnown () && isAssumedDead (BB);
1590
1614
}
1591
1615
1592
1616
// / See AAIsDead::isAssumed(Instruction *I).
1593
- bool isAssumedDead (Instruction *I) const override {
1617
+ bool isAssumedDead (const Instruction *I) const override {
1594
1618
assert (I->getParent ()->getParent () == &getAnchorScope () &&
1595
1619
" Instruction must be in the same anchor scope function." );
1596
1620
@@ -1603,33 +1627,29 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
1603
1627
return true ;
1604
1628
1605
1629
// If it is not after a noreturn call, than it is live.
1606
- if (!isAfterNoReturn (I))
1607
- return false ;
1608
-
1609
- // Definitely dead.
1610
- return true ;
1630
+ return isAfterNoReturn (I);
1611
1631
}
1612
1632
1613
1633
// / See AAIsDead::isKnownDead(Instruction *I).
1614
- bool isKnownDead (Instruction *I) const override {
1634
+ bool isKnownDead (const Instruction *I) const override {
1615
1635
return getKnown () && isAssumedDead (I);
1616
1636
}
1617
1637
1618
1638
// / Check if instruction is after noreturn call, in other words, assumed dead.
1619
- bool isAfterNoReturn (Instruction *I) const ;
1639
+ bool isAfterNoReturn (const Instruction *I) const ;
1620
1640
1621
1641
// / Collection of to be explored paths.
1622
- SmallSetVector<Instruction *, 8 > ToBeExploredPaths;
1642
+ SmallSetVector<const Instruction *, 8 > ToBeExploredPaths;
1623
1643
1624
1644
// / Collection of all assumed live BasicBlocks.
1625
- DenseSet<BasicBlock *> AssumedLiveBlocks;
1645
+ DenseSet<const BasicBlock *> AssumedLiveBlocks;
1626
1646
1627
1647
// / Collection of calls with noreturn attribute, assumed or knwon.
1628
- SmallSetVector<Instruction *, 4 > NoReturnCalls;
1648
+ SmallSetVector<const Instruction *, 4 > NoReturnCalls;
1629
1649
};
1630
1650
1631
- bool AAIsDeadFunction::isAfterNoReturn (Instruction *I) const {
1632
- Instruction *PrevI = I->getPrevNode ();
1651
+ bool AAIsDeadFunction::isAfterNoReturn (const Instruction *I) const {
1652
+ const Instruction *PrevI = I->getPrevNode ();
1633
1653
while (PrevI) {
1634
1654
if (NoReturnCalls.count (PrevI))
1635
1655
return true ;
@@ -1638,75 +1658,77 @@ bool AAIsDeadFunction::isAfterNoReturn(Instruction *I) const {
1638
1658
return false ;
1639
1659
}
1640
1660
1641
- bool AAIsDeadFunction::explorePath (Attributor &A, Instruction *I) {
1642
- BasicBlock *BB = I->getParent ();
1661
+ const Instruction *AAIsDeadFunction::findNextNoReturn (Attributor &A,
1662
+ const Instruction *I) {
1663
+ const BasicBlock *BB = I->getParent ();
1664
+
1665
+ // TODO: We should have a function that determines if an "edge" is dead.
1666
+ // Edges could be from an instruction to the next or from a terminator
1667
+ // to the successor. For now, we need to special case the unwind block
1668
+ // of InvokeInst below.
1643
1669
1644
1670
while (I) {
1645
1671
ImmutableCallSite ICS (I);
1646
1672
1647
1673
if (ICS) {
1648
- auto *NoReturnAA = A.getAAFor <AANoReturn>(*this , *I);
1649
-
1650
- if (NoReturnAA && NoReturnAA->isAssumedNoReturn ()) {
1651
- if (!NoReturnCalls.insert (I))
1652
- // If I is already in the NoReturnCalls set, then it stayed noreturn
1653
- // and we didn't discover any new instructions.
1654
- return false ;
1655
-
1656
- // Discovered new noreturn call, return true to indicate that I is not
1657
- // noreturn anymore and should be deleted from NoReturnCalls.
1658
- return true ;
1674
+ // Regarless of the no-return property of an invoke instruction we only
1675
+ // learn that the regular successor is not reachable through this
1676
+ // instruction but the unwind block might still be.
1677
+ if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1678
+ // Use nounwind to justify the unwind block is dead as well.
1679
+ auto *AANoUnw = A.getAAFor <AANoUnwind>(*this , *Invoke);
1680
+ if (!AANoUnw || !AANoUnw->isAssumedNoUnwind ()) {
1681
+ AssumedLiveBlocks.insert (Invoke->getUnwindDest ());
1682
+ ToBeExploredPaths.insert (&Invoke->getUnwindDest ()->front ());
1683
+ }
1659
1684
}
1660
1685
1661
- if (ICS.hasFnAttr (Attribute::NoReturn)) {
1662
- if (!NoReturnCalls.insert (I))
1663
- return false ;
1664
-
1665
- return true ;
1666
- }
1686
+ auto *NoReturnAA = A.getAAFor <AANoReturn>(*this , *I);
1687
+ if (ICS.hasFnAttr (Attribute::NoReturn) ||
1688
+ (NoReturnAA && NoReturnAA->isAssumedNoReturn ()))
1689
+ return I;
1667
1690
}
1668
1691
1669
1692
I = I->getNextNode ();
1670
1693
}
1671
1694
1672
1695
// get new paths (reachable blocks).
1673
- for (BasicBlock *SuccBB : successors (BB)) {
1674
- Instruction *Inst = &(SuccBB->front ());
1696
+ for (const BasicBlock *SuccBB : successors (BB)) {
1675
1697
AssumedLiveBlocks.insert (SuccBB);
1676
- ToBeExploredPaths.insert (Inst );
1698
+ ToBeExploredPaths.insert (&SuccBB-> front () );
1677
1699
}
1678
1700
1679
- return true ;
1701
+ // No noreturn instruction found.
1702
+ return nullptr ;
1680
1703
}
1681
1704
1682
1705
ChangeStatus AAIsDeadFunction::updateImpl (Attributor &A) {
1683
1706
// Temporary collection to iterate over existing noreturn instructions. This
1684
1707
// will alow easier modification of NoReturnCalls collection
1685
- SmallVector<Instruction *, 8 > NoReturnChanged;
1708
+ SmallVector<const Instruction *, 8 > NoReturnChanged;
1686
1709
ChangeStatus Status = ChangeStatus::UNCHANGED;
1687
1710
1688
- for (Instruction *I : NoReturnCalls)
1711
+ for (const Instruction *I : NoReturnCalls)
1689
1712
NoReturnChanged.push_back (I);
1690
1713
1691
- for (Instruction *I : NoReturnChanged) {
1714
+ for (const Instruction *I : NoReturnChanged) {
1692
1715
size_t Size = ToBeExploredPaths.size ();
1693
1716
1694
- // Still noreturn.
1695
- if (!explorePath (A, I))
1696
- continue ;
1697
-
1698
- NoReturnCalls.remove (I);
1699
-
1700
- // At least one new path.
1701
- Status = ChangeStatus::CHANGED;
1702
-
1703
- // No new paths.
1704
- if (Size == ToBeExploredPaths.size ())
1705
- continue ;
1717
+ const Instruction *NextNoReturnI = findNextNoReturn (A, I);
1718
+ if (NextNoReturnI != I) {
1719
+ Status = ChangeStatus::CHANGED;
1720
+ NoReturnCalls.remove (I);
1721
+ if (NextNoReturnI)
1722
+ NoReturnCalls.insert (NextNoReturnI);
1723
+ }
1706
1724
1707
- // explore new paths.
1708
- while (Size != ToBeExploredPaths.size ())
1709
- explorePath (A, ToBeExploredPaths[Size ++]);
1725
+ // Explore new paths.
1726
+ while (Size != ToBeExploredPaths.size ()) {
1727
+ Status = ChangeStatus::CHANGED;
1728
+ if (const Instruction *NextNoReturnI =
1729
+ findNextNoReturn (A, ToBeExploredPaths[Size ++]))
1730
+ NoReturnCalls.insert (NextNoReturnI);
1731
+ }
1710
1732
}
1711
1733
1712
1734
LLVM_DEBUG (
0 commit comments