@@ -507,10 +507,20 @@ namespace {
507
507
void OptimizeAutoreleaseRVCall (Function &F, Instruction *AutoreleaseRV,
508
508
ARCInstKind &Class);
509
509
void OptimizeIndividualCalls (Function &F);
510
- void
511
- OptimizeIndividualCallImpl (Function &F,
512
- DenseMap<BasicBlock *, ColorVector> &BlockColors,
513
- Instruction *Inst, ARCInstKind Class);
510
+
511
+ // / Optimize an individual call, optionally passing the
512
+ // / GetArgRCIdentityRoot if it has already been computed.
513
+ void OptimizeIndividualCallImpl (
514
+ Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
515
+ Instruction *Inst, ARCInstKind Class, const Value *Arg);
516
+
517
+ // / Try to optimize an AutoreleaseRV with a RetainRV or ClaimRV. If the
518
+ // / optimization occurs, returns true to indicate that the caller should
519
+ // / assume the instructions are dead.
520
+ bool OptimizeInlinedAutoreleaseRVCall (
521
+ Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
522
+ Instruction *Inst, const Value *&Arg, ARCInstKind Class,
523
+ Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg);
514
524
515
525
void CheckForCFGHazards (const BasicBlock *BB,
516
526
DenseMap<const BasicBlock *, BBState> &BBStates,
@@ -594,36 +604,8 @@ void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const {
594
604
AU.setPreservesCFG ();
595
605
}
596
606
597
- static bool isSafeBetweenRVCalls (const Instruction *I) {
598
- if (IsNoopInstruction (I))
599
- return true ;
600
-
601
- auto *CB = dyn_cast<CallBase>(I);
602
- if (!CB)
603
- return false ;
604
-
605
- Intrinsic::ID IID = CB->getIntrinsicID ();
606
- if (IID == Intrinsic::not_intrinsic)
607
- return false ;
608
-
609
- switch (IID) {
610
- case Intrinsic::lifetime_start:
611
- case Intrinsic::lifetime_end:
612
- // The inliner adds new lifetime markers as part of the return sequence,
613
- // which should be skipped when looking for paired return RV call.
614
- LLVM_FALLTHROUGH;
615
- case Intrinsic::stacksave:
616
- case Intrinsic::stackrestore:
617
- // If the inlined code contains dynamic allocas, the above applies as well.
618
- return true ;
619
- default :
620
- return false ;
621
- }
622
- }
623
-
624
607
// / Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
625
- // / not a return value. Or, if it can be paired with an
626
- // / objc_autoreleaseReturnValue, delete the pair and return true.
608
+ // / not a return value.
627
609
bool
628
610
ObjCARCOpt::OptimizeRetainRVCall (Function &F, Instruction *RetainRV) {
629
611
// Check for the argument being from an immediately preceding call or invoke.
@@ -649,39 +631,6 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
649
631
}
650
632
}
651
633
652
- // Track PHIs which are equivalent to our Arg.
653
- SmallDenseSet<const Value*, 2 > EquivalentArgs;
654
- EquivalentArgs.insert (Arg);
655
-
656
- // Add PHIs that are equivalent to Arg to ArgUsers.
657
- if (const PHINode *PN = dyn_cast<PHINode>(Arg)) {
658
- SmallVector<const Value *, 2 > ArgUsers;
659
- getEquivalentPHIs (*PN, ArgUsers);
660
- EquivalentArgs.insert (ArgUsers.begin (), ArgUsers.end ());
661
- }
662
-
663
- // Check for being preceded by an objc_autoreleaseReturnValue on the same
664
- // pointer. In this case, we can delete the pair.
665
- BasicBlock::iterator I = RetainRV->getIterator (),
666
- Begin = RetainRV->getParent ()->begin ();
667
- if (I != Begin) {
668
- do
669
- --I;
670
- while (I != Begin && isSafeBetweenRVCalls (&*I));
671
- if (GetBasicARCInstKind (&*I) == ARCInstKind::AutoreleaseRV &&
672
- EquivalentArgs.count (GetArgRCIdentityRoot (&*I))) {
673
- Changed = true ;
674
- ++NumPeeps;
675
-
676
- LLVM_DEBUG (dbgs () << " Erasing autoreleaseRV,retainRV pair: " << *I << " \n "
677
- << " Erasing " << *RetainRV << " \n " );
678
-
679
- EraseInstruction (&*I);
680
- EraseInstruction (RetainRV);
681
- return true ;
682
- }
683
- }
684
-
685
634
// Turn it to a plain objc_retain.
686
635
Changed = true ;
687
636
++NumPeeps;
@@ -699,6 +648,62 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
699
648
return false ;
700
649
}
701
650
651
+ bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall (
652
+ Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
653
+ Instruction *Inst, const Value *&Arg, ARCInstKind Class,
654
+ Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) {
655
+ // Must be in the same basic block.
656
+ assert (Inst->getParent () == AutoreleaseRV->getParent ());
657
+
658
+ // Must operate on the same root.
659
+ Arg = GetArgRCIdentityRoot (Inst);
660
+ AutoreleaseRVArg = GetArgRCIdentityRoot (AutoreleaseRV);
661
+ if (Arg != AutoreleaseRVArg) {
662
+ // If there isn't an exact match, check if we have equivalent PHIs.
663
+ const PHINode *PN = dyn_cast<PHINode>(Arg);
664
+ if (!PN)
665
+ return false ;
666
+
667
+ SmallVector<const Value *, 4 > ArgUsers;
668
+ getEquivalentPHIs (*PN, ArgUsers);
669
+ if (llvm::find (ArgUsers, AutoreleaseRVArg) == ArgUsers.end ())
670
+ return false ;
671
+ }
672
+
673
+ // Okay, this is a match. Merge them.
674
+ ++NumPeeps;
675
+ LLVM_DEBUG (dbgs () << " Found inlined objc_autoreleaseReturnValue '"
676
+ << *AutoreleaseRV << " ' paired with '" << *Inst << " '\n " );
677
+
678
+ // Delete the RV pair, starting with the AutoreleaseRV.
679
+ AutoreleaseRV->replaceAllUsesWith (
680
+ cast<CallInst>(AutoreleaseRV)->getArgOperand (0 ));
681
+ EraseInstruction (AutoreleaseRV);
682
+ if (Class == ARCInstKind::RetainRV) {
683
+ // AutoreleaseRV and RetainRV cancel out. Delete the RetainRV.
684
+ Inst->replaceAllUsesWith (cast<CallInst>(Inst)->getArgOperand (0 ));
685
+ EraseInstruction (Inst);
686
+ return true ;
687
+ }
688
+
689
+ // ClaimRV is a frontend peephole for RetainRV + Release. Since the
690
+ // AutoreleaseRV and RetainRV cancel out, replace the ClaimRV with a Release.
691
+ assert (Class == ARCInstKind::ClaimRV);
692
+ Value *CallArg = cast<CallInst>(Inst)->getArgOperand (0 );
693
+ CallInst *Release = CallInst::Create (
694
+ EP.get (ARCRuntimeEntryPointKind::Release), CallArg, " " , Inst);
695
+ assert (IsAlwaysTail (ARCInstKind::ClaimRV) &&
696
+ " Expected ClaimRV to be safe to tail call" );
697
+ Release->setTailCall ();
698
+ Inst->replaceAllUsesWith (CallArg);
699
+ EraseInstruction (Inst);
700
+
701
+ // Run the normal optimizations on Release.
702
+ OptimizeIndividualCallImpl (F, BlockColors, Release, ARCInstKind::Release,
703
+ Arg);
704
+ return true ;
705
+ }
706
+
702
707
// / Turn objc_autoreleaseReturnValue into objc_autorelease if the result is not
703
708
// / used as a return value.
704
709
void ObjCARCOpt::OptimizeAutoreleaseRVCall (Function &F,
@@ -785,31 +790,98 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
785
790
isScopedEHPersonality (classifyEHPersonality (F.getPersonalityFn ())))
786
791
BlockColors = colorEHFunclets (F);
787
792
793
+ // Store any delayed AutoreleaseRV intrinsics, so they can be easily paired
794
+ // with RetainRV and ClaimRV.
795
+ Instruction *DelayedAutoreleaseRV = nullptr ;
796
+ const Value *DelayedAutoreleaseRVArg = nullptr ;
797
+ auto setDelayedAutoreleaseRV = [&](Instruction *AutoreleaseRV) {
798
+ assert (!DelayedAutoreleaseRV || !AutoreleaseRV);
799
+ DelayedAutoreleaseRV = AutoreleaseRV;
800
+ DelayedAutoreleaseRVArg = nullptr ;
801
+ };
802
+ auto optimizeDelayedAutoreleaseRV = [&]() {
803
+ if (!DelayedAutoreleaseRV)
804
+ return ;
805
+ OptimizeIndividualCallImpl (F, BlockColors, DelayedAutoreleaseRV,
806
+ ARCInstKind::AutoreleaseRV,
807
+ DelayedAutoreleaseRVArg);
808
+ setDelayedAutoreleaseRV (nullptr );
809
+ };
810
+ auto shouldDelayAutoreleaseRV = [&](Instruction *NonARCInst) {
811
+ // Nothing to delay, but we may as well skip the logic below.
812
+ if (!DelayedAutoreleaseRV)
813
+ return true ;
814
+
815
+ // If we hit the end of the basic block we're not going to find an RV-pair.
816
+ // Stop delaying.
817
+ if (NonARCInst->isTerminator ())
818
+ return false ;
819
+
820
+ // Given the frontend rules for emitting AutoreleaseRV, RetainRV, and
821
+ // ClaimRV, it's probably safe to skip over even opaque function calls
822
+ // here since OptimizeInlinedAutoreleaseRVCall will confirm that they
823
+ // have the same RCIdentityRoot. However, what really matters is
824
+ // skipping instructions or intrinsics that the inliner could leave behind;
825
+ // be conservative for now and don't skip over opaque calls, which could
826
+ // potentially include other ARC calls.
827
+ auto *CB = dyn_cast<CallBase>(NonARCInst);
828
+ if (!CB)
829
+ return true ;
830
+ return CB->getIntrinsicID () != Intrinsic::not_intrinsic;
831
+ };
832
+
788
833
// Visit all objc_* calls in F.
789
834
for (inst_iterator I = inst_begin (&F), E = inst_end (&F); I != E; ) {
790
835
Instruction *Inst = &*I++;
791
836
792
837
ARCInstKind Class = GetBasicARCInstKind (Inst);
793
838
794
- LLVM_DEBUG (dbgs () << " Visiting: Class: " << Class << " ; " << *Inst << " \n " );
795
-
796
839
// Skip this loop if this instruction isn't itself an ARC intrinsic.
840
+ const Value *Arg = nullptr ;
797
841
switch (Class) {
798
842
default :
843
+ optimizeDelayedAutoreleaseRV ();
799
844
break ;
800
845
case ARCInstKind::CallOrUser:
801
846
case ARCInstKind::User:
802
847
case ARCInstKind::None:
848
+ // This is a non-ARC instruction. If we're delaying an AutoreleaseRV,
849
+ // check if it's safe to skip over it; if not, optimize the AutoreleaseRV
850
+ // now.
851
+ if (!shouldDelayAutoreleaseRV (Inst))
852
+ optimizeDelayedAutoreleaseRV ();
853
+ continue ;
854
+ case ARCInstKind::AutoreleaseRV:
855
+ optimizeDelayedAutoreleaseRV ();
856
+ setDelayedAutoreleaseRV (Inst);
803
857
continue ;
858
+ case ARCInstKind::RetainRV:
859
+ case ARCInstKind::ClaimRV:
860
+ if (DelayedAutoreleaseRV) {
861
+ // We have a potential RV pair. Check if they cancel out.
862
+ if (OptimizeInlinedAutoreleaseRVCall (F, BlockColors, Inst, Arg, Class,
863
+ DelayedAutoreleaseRV,
864
+ DelayedAutoreleaseRVArg)) {
865
+ setDelayedAutoreleaseRV (nullptr );
866
+ continue ;
867
+ }
868
+ optimizeDelayedAutoreleaseRV ();
869
+ }
870
+ break ;
804
871
}
805
872
806
- OptimizeIndividualCallImpl (F, BlockColors, Inst, Class);
873
+ OptimizeIndividualCallImpl (F, BlockColors, Inst, Class, Arg );
807
874
}
875
+
876
+ // Catch the final delayed AutoreleaseRV.
877
+ optimizeDelayedAutoreleaseRV ();
808
878
}
809
879
810
880
void ObjCARCOpt::OptimizeIndividualCallImpl (
811
881
Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
812
- Instruction *Inst, ARCInstKind Class) {
882
+ Instruction *Inst, ARCInstKind Class, const Value *Arg) {
883
+ LLVM_DEBUG (dbgs () << " Visiting: Class: " << Class << " ; " << *Inst << " \n " );
884
+
813
885
// Some of the ARC calls can be deleted if their arguments are global
814
886
// variables that are inert in ARC.
815
887
if (IsNoopOnGlobal (Class)) {
@@ -958,7 +1030,9 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
958
1030
return ;
959
1031
}
960
1032
961
- const Value *Arg = GetArgRCIdentityRoot (Inst);
1033
+ // If we haven't already looked up the root, look it up now.
1034
+ if (!Arg)
1035
+ Arg = GetArgRCIdentityRoot (Inst);
962
1036
963
1037
// ARC calls with null are no-ops. Delete them.
964
1038
if (IsNullOrUndef (Arg)) {
0 commit comments