From a116bba31ce6ae2a537c6a2b3e8d6f7ba1d4b5c8 Mon Sep 17 00:00:00 2001 From: Pete Cooper Date: Thu, 3 Jan 2019 01:38:08 +0000 Subject: [PATCH] Teach ObjCARC optimizer about equivalent PHIs when eliminating autoreleaseRV/retainRV pairs 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 | 13 ++++++++++++- test/Transforms/ObjCARC/rv.ll | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index 6ffaadc2b5f..9a02174556f 100644 --- a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -600,6 +600,17 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { } } + // 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); + 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; diff --git a/test/Transforms/ObjCARC/rv.ll b/test/Transforms/ObjCARC/rv.ll index ca3d7e2f848..3d0d56ca0e5 100644 --- a/test/Transforms/ObjCARC/rv.ll +++ b/test/Transforms/ObjCARC/rv.ll @@ -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) { -- 2.50.1