[ObjCARC] Do not turn a call to @objc_autoreleaseReturnValue into a call
to @objc_autorelease if its operand is a PHI and the PHI has an
equivalent value that is used by a return instruction.
For example, ARC optimizer shouldn't replace the call in the following
example, as doing so breaks the AutoreleaseRV/RetainRV optimization:
%v1 = bitcast i32* %v0 to i8*
br label %bb3
bb2:
%v3 = bitcast i32* %v2 to i8*
br label %bb3
bb3:
%p = phi i8* [ %v1, %bb1 ], [ %v3, %bb2 ]
%retval = phi i32* [ %v0, %bb1 ], [ %v2, %bb2 ] ; equivalent to %p
%v4 = tail call i8* @objc_autoreleaseReturnValue(i8* %p)
ret i32* %retval
Also, make sure ObjCARCContract replaces @objc_autoreleaseReturnValue's
operand uses with its value so that the call gets tail-called.
rdar://problem/15894705
llvm-svn: 323009
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
index cd9b3d9..745dac8 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
@@ -82,6 +82,26 @@
return dyn_cast<InvokeInst>(Opnd);
}
+/// Return the list of PHI nodes that are equivalent to PN.
+template<class PHINodeTy, class VectorTy>
+void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList) {
+ auto *BB = PN.getParent();
+ for (auto &P : BB->phis()) {
+ if (&P == &PN) // Do not add PN to the list.
+ continue;
+ unsigned I = 0, E = PN.getNumIncomingValues();
+ for (; I < E; ++I) {
+ auto *BB = PN.getIncomingBlock(I);
+ auto *PNOpnd = PN.getIncomingValue(I)->stripPointerCasts();
+ auto *POpnd = P.getIncomingValueForBlock(BB)->stripPointerCasts();
+ if (PNOpnd != POpnd)
+ break;
+ }
+ if (I == E)
+ PHIList.push_back(&P);
+ }
+}
+
} // end namespace objcarc
} // end namespace llvm