Index: lib/Transforms/ObjCARC/ObjCARCOpts.cpp =================================================================== --- lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -600,6 +600,19 @@ } } + // Track PHIs which are equivalent to our Arg. + SmallDenseSet EquivalentArgs; + EquivalentArgs.insert(Arg); + + // Add PHIs that are equivalent to Arg to ArgUsers. + if (const PHINode *PN = dyn_cast(Arg)) { + SmallVector ArgUsers; + getEquivalentPHIs(*PN, ArgUsers); + + for (const Value *ArgUser : ArgUsers) + EquivalentArgs.insert(ArgUser); + } + // 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(), @@ -608,17 +621,19 @@ do --I; while (I != Begin && IsNoopInstruction(&*I)); - if (GetBasicARCInstKind(&*I) == ARCInstKind::AutoreleaseRV && - GetArgRCIdentityRoot(&*I) == Arg) { - Changed = true; - ++NumPeeps; + if (GetBasicARCInstKind(&*I) == ARCInstKind::AutoreleaseRV) { + if (EquivalentArgs.count(GetArgRCIdentityRoot(&*I))) { + Changed = true; + ++NumPeeps; - LLVM_DEBUG(dbgs() << "Erasing autoreleaseRV,retainRV pair: " << *I << "\n" - << "Erasing " << *RetainRV << "\n"); + LLVM_DEBUG(dbgs() << "Erasing autoreleaseRV,retainRV pair: " + << *I << "\n" + << "Erasing " << *RetainRV << "\n"); - EraseInstruction(&*I); - EraseInstruction(RetainRV); - return true; + EraseInstruction(&*I); + EraseInstruction(RetainRV); + return true; + } } } Index: test/Transforms/ObjCARC/rv.ll =================================================================== --- test/Transforms/ObjCARC/rv.ll +++ test/Transforms/ObjCARC/rv.ll @@ -239,6 +239,24 @@ 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) {