]> granicus.if.org Git - llvm/commitdiff
Teach ObjCARC optimizer about equivalent PHIs when eliminating autoreleaseRV/retainRV...
authorPete Cooper <peter_cooper@apple.com>
Thu, 3 Jan 2019 01:38:08 +0000 (01:38 +0000)
committerPete Cooper <peter_cooper@apple.com>
Thu, 3 Jan 2019 01:38:08 +0000 (01:38 +0000)
OptimizeAutoreleaseRVCall skips optimizing llvm.objc.autoreleaseReturnValue if it
sees a user which is llvm.objc.retainAutoreleasedReturnValue, and if they have
equivalent arguments (either identical or equivalent PHIs). It then assumes that
ObjCARCOpt::OptimizeRetainRVCall will optimize the pair instead.

Trouble is, ObjCARCOpt::OptimizeRetainRVCall doesn't know about equivalent PHIs
so optimizes in a different way and we are left with an unoptimized llvm.objc.autoreleaseReturnValue.

This teaches ObjCARCOpt::OptimizeRetainRVCall to also understand PHI equivalence.

rdar://problem/47005143

Reviewed By: ahatanak

Differential Revision: https://reviews.llvm.org/D56235

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350284 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/ObjCARC/ObjCARCOpts.cpp
test/Transforms/ObjCARC/rv.ll

index 6ffaadc2b5fc52d1fd38ee09557c3342291de903..9a02174556fccb0c630d1e90c9442a6cdc10f88d 100644 (file)
@@ -600,6 +600,17 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
     }
   }
 
+  // Track PHIs which are equivalent to our Arg.
+  SmallDenseSet<const Value*, 2> EquivalentArgs;
+  EquivalentArgs.insert(Arg);
+
+  // Add PHIs that are equivalent to Arg to ArgUsers.
+  if (const PHINode *PN = dyn_cast<PHINode>(Arg)) {
+    SmallVector<const Value *, 2> ArgUsers;
+    getEquivalentPHIs(*PN, ArgUsers);
+    EquivalentArgs.insert(ArgUsers.begin(), ArgUsers.end());
+  }
+
   // Check for being preceded by an objc_autoreleaseReturnValue on the same
   // pointer. In this case, we can delete the pair.
   BasicBlock::iterator I = RetainRV->getIterator(),
@@ -609,7 +620,7 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
       --I;
     while (I != Begin && IsNoopInstruction(&*I));
     if (GetBasicARCInstKind(&*I) == ARCInstKind::AutoreleaseRV &&
-        GetArgRCIdentityRoot(&*I) == Arg) {
+        EquivalentArgs.count(GetArgRCIdentityRoot(&*I))) {
       Changed = true;
       ++NumPeeps;
 
index ca3d7e2f848d10e12153b92f4eb9d32984155e85..3d0d56ca0e536418abf112dee95515abd0047fd5 100644 (file)
@@ -239,6 +239,24 @@ define i8* @test19(i8* %p) {
   ret i8* %p
 }
 
+; Delete autoreleaseRV+retainRV pairs when they have equivalent PHIs as inputs
+
+; CHECK: define i8* @test19phi(i8* %p) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %test19bb
+; CHECK: test19bb:
+; CHECK-NEXT: ret i8* %p
+define i8* @test19phi(i8* %p) {
+entry:
+  br label %test19bb
+test19bb:
+  %phi1 = phi i8* [ %p, %entry ]
+  %phi2 = phi i8* [ %p, %entry ]
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %phi1)
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %phi2)
+  ret i8* %p
+}
+
 ; Like test19 but with plain autorelease.
 
 ; CHECK: define i8* @test20(i8* %p) {