@@ -532,12 +532,15 @@ class ObjCARCOpt {
532
532
bool VisitBottomUp (BasicBlock *BB,
533
533
DenseMap<const BasicBlock *, BBState> &BBStates,
534
534
BlotMapVector<Value *, RRInfo> &Retains);
535
- bool VisitInstructionTopDown (Instruction *Inst,
536
- DenseMap<Value *, RRInfo> &Releases,
537
- BBState &MyStates);
538
- bool VisitTopDown (BasicBlock *BB,
539
- DenseMap<const BasicBlock *, BBState> &BBStates,
540
- DenseMap<Value *, RRInfo> &Releases);
535
+ bool VisitInstructionTopDown (
536
+ Instruction *Inst, DenseMap<Value *, RRInfo> &Releases, BBState &MyStates,
537
+ const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
538
+ &ReleaseInsertPtToRCIdentityRoots);
539
+ bool VisitTopDown (
540
+ BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates,
541
+ DenseMap<Value *, RRInfo> &Releases,
542
+ const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
543
+ &ReleaseInsertPtToRCIdentityRoots);
541
544
bool Visit (Function &F, DenseMap<const BasicBlock *, BBState> &BBStates,
542
545
BlotMapVector<Value *, RRInfo> &Retains,
543
546
DenseMap<Value *, RRInfo> &Releases);
@@ -1495,14 +1498,62 @@ bool ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
1495
1498
return NestingDetected;
1496
1499
}
1497
1500
1498
- bool
1499
- ObjCARCOpt::VisitInstructionTopDown (Instruction *Inst,
1500
- DenseMap<Value *, RRInfo> &Releases,
1501
- BBState &MyStates) {
1501
+ // Fill ReleaseInsertPtToRCIdentityRoots, which is a map from insertion points
1502
+ // to the set of RC identity roots that would be released by the release calls
1503
+ // moved to the insertion points.
1504
+ static void collectReleaseInsertPts (
1505
+ const BlotMapVector<Value *, RRInfo> &Retains,
1506
+ DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
1507
+ &ReleaseInsertPtToRCIdentityRoots) {
1508
+ for (auto &P : Retains) {
1509
+ // Retains is a map from an objc_retain call to a RRInfo of the RC identity
1510
+ // root of the call. Get the RC identity root of the objc_retain call.
1511
+ Instruction *Retain = cast<Instruction>(P.first );
1512
+ Value *Root = GetRCIdentityRoot (Retain->getOperand (0 ));
1513
+ // Collect all the insertion points of the objc_release calls that release
1514
+ // the RC identity root of the objc_retain call.
1515
+ for (const Instruction *InsertPt : P.second .ReverseInsertPts )
1516
+ ReleaseInsertPtToRCIdentityRoots[InsertPt].insert (Root);
1517
+ }
1518
+ }
1519
+
1520
+ // Get the RC identity roots from an insertion point of an objc_release call.
1521
+ // Return nullptr if the passed instruction isn't an insertion point.
1522
+ static const SmallPtrSet<const Value *, 2 > *
1523
+ getRCIdentityRootsFromReleaseInsertPt (
1524
+ const Instruction *InsertPt,
1525
+ const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
1526
+ &ReleaseInsertPtToRCIdentityRoots) {
1527
+ auto I = ReleaseInsertPtToRCIdentityRoots.find (InsertPt);
1528
+ if (I == ReleaseInsertPtToRCIdentityRoots.end ())
1529
+ return nullptr ;
1530
+ return &I->second ;
1531
+ }
1532
+
1533
+ bool ObjCARCOpt::VisitInstructionTopDown (
1534
+ Instruction *Inst, DenseMap<Value *, RRInfo> &Releases, BBState &MyStates,
1535
+ const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
1536
+ &ReleaseInsertPtToRCIdentityRoots) {
1502
1537
bool NestingDetected = false ;
1503
1538
ARCInstKind Class = GetARCInstKind (Inst);
1504
1539
const Value *Arg = nullptr ;
1505
1540
1541
+ // Make sure a call to objc_retain isn't moved past insertion points of calls
1542
+ // to objc_release.
1543
+ if (const SmallPtrSet<const Value *, 2 > *Roots =
1544
+ getRCIdentityRootsFromReleaseInsertPt (
1545
+ Inst, ReleaseInsertPtToRCIdentityRoots))
1546
+ for (auto *Root : *Roots) {
1547
+ TopDownPtrState &S = MyStates.getPtrTopDownState (Root);
1548
+ // Disable code motion if the current position is S_Retain to prevent
1549
+ // moving the objc_retain call past objc_release calls. If it's
1550
+ // S_CanRelease or larger, it's not necessary to disable code motion as
1551
+ // the insertion points that prevent the objc_retain call from moving down
1552
+ // should have been set already.
1553
+ if (S.GetSeq () == S_Retain)
1554
+ S.SetCFGHazardAfflicted (true );
1555
+ }
1556
+
1506
1557
LLVM_DEBUG (dbgs () << " Class: " << Class << " \n " );
1507
1558
1508
1559
switch (Class) {
@@ -1565,10 +1616,11 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
1565
1616
return NestingDetected;
1566
1617
}
1567
1618
1568
- bool
1569
- ObjCARCOpt::VisitTopDown (BasicBlock *BB,
1570
- DenseMap<const BasicBlock *, BBState> &BBStates,
1571
- DenseMap<Value *, RRInfo> &Releases) {
1619
+ bool ObjCARCOpt::VisitTopDown (
1620
+ BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates,
1621
+ DenseMap<Value *, RRInfo> &Releases,
1622
+ const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
1623
+ &ReleaseInsertPtToRCIdentityRoots) {
1572
1624
LLVM_DEBUG (dbgs () << " \n == ObjCARCOpt::VisitTopDown ==\n " );
1573
1625
bool NestingDetected = false ;
1574
1626
BBState &MyStates = BBStates[BB];
@@ -1608,7 +1660,8 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
1608
1660
for (Instruction &Inst : *BB) {
1609
1661
LLVM_DEBUG (dbgs () << " Visiting " << Inst << " \n " );
1610
1662
1611
- NestingDetected |= VisitInstructionTopDown (&Inst, Releases, MyStates);
1663
+ NestingDetected |= VisitInstructionTopDown (
1664
+ &Inst, Releases, MyStates, ReleaseInsertPtToRCIdentityRoots);
1612
1665
1613
1666
// Bail out if the number of pointers being tracked becomes too large so
1614
1667
// that this pass can complete in a reasonable amount of time.
@@ -1728,10 +1781,15 @@ bool ObjCARCOpt::Visit(Function &F,
1728
1781
return false ;
1729
1782
}
1730
1783
1784
+ DenseMap<const Instruction *, SmallPtrSet<const Value *, 2 >>
1785
+ ReleaseInsertPtToRCIdentityRoots;
1786
+ collectReleaseInsertPts (Retains, ReleaseInsertPtToRCIdentityRoots);
1787
+
1731
1788
// Use reverse-postorder for top-down.
1732
1789
bool TopDownNestingDetected = false ;
1733
1790
for (BasicBlock *BB : llvm::reverse (PostOrder)) {
1734
- TopDownNestingDetected |= VisitTopDown (BB, BBStates, Releases);
1791
+ TopDownNestingDetected |=
1792
+ VisitTopDown (BB, BBStates, Releases, ReleaseInsertPtToRCIdentityRoots);
1735
1793
if (DisableRetainReleasePairing)
1736
1794
return false ;
1737
1795
}
0 commit comments