diff options
| author | Michael Gottesman <mgottesman@apple.com> | 2013-05-24 20:44:02 +0000 | 
|---|---|---|
| committer | Michael Gottesman <mgottesman@apple.com> | 2013-05-24 20:44:02 +0000 | 
| commit | 5a91bbf33a6a940346e3577812b2185be47b5dad (patch) | |
| tree | 76a1b00c54f70ec38db8f13b8d2bac6b68c1a63b /llvm | |
| parent | 0b342b6ddf629005e47a2fdf9929fc7bfe162814 (diff) | |
| download | bcm5719-llvm-5a91bbf33a6a940346e3577812b2185be47b5dad.tar.gz bcm5719-llvm-5a91bbf33a6a940346e3577812b2185be47b5dad.zip  | |
[objc-arc] Make sure that multiple owners is propogated correctly through the pass via the usage of a global data structure.
rdar://13750319
llvm-svn: 182669
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 33 | ||||
| -rw-r--r-- | llvm/test/Transforms/ObjCARC/allocas.ll | 97 | 
2 files changed, 113 insertions, 17 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index aa2134152d8..91490d1b2d0 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -30,6 +30,7 @@  #include "ObjCARCAliasAnalysis.h"  #include "ProvenanceAnalysis.h"  #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/Statistic.h" @@ -454,18 +455,8 @@ namespace {      /// sequence.      SmallPtrSet<Instruction *, 2> ReverseInsertPts; -    /// Does this pointer have multiple owners? -    /// -    /// In the presence of multiple owners with the same provenance caused by -    /// allocas, we can not assume that the frontend will emit balanced code -    /// since it could put the release on the pointer loaded from the -    /// alloca. This confuses the optimizer so we must be more conservative in -    /// that case. -    bool MultipleOwners; -      RRInfo() : -      KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(0), -      MultipleOwners(false) {} +      KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(0) {}      void clear(); @@ -478,7 +469,6 @@ namespace {  void RRInfo::clear() {    KnownSafe = false;    IsTailCallRelease = false; -  MultipleOwners = false;    ReleaseMetadata = 0;    Calls.clear();    ReverseInsertPts.clear(); @@ -569,7 +559,6 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {      RRI.IsTailCallRelease = RRI.IsTailCallRelease &&                              Other.RRI.IsTailCallRelease;      RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end()); -    RRI.MultipleOwners |= Other.RRI.MultipleOwners;      // Merge the insert point sets. If there are any differences,      // that makes this a partial merge. @@ -1058,6 +1047,9 @@ namespace {      bool Changed;      ProvenanceAnalysis PA; +    // This is used to track if a pointer is stored into an alloca. +    DenseSet<const Value *> MultiOwnersSet; +      /// A flag indicating whether this optimization pass should run.      bool Run; @@ -1943,7 +1935,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst,          BBState::ptr_iterator I = MyStates.findPtrBottomUpState(            StripPointerCastsAndObjCCalls(SI->getValueOperand()));          if (I != MyStates.bottom_up_ptr_end()) -          I->second.RRI.MultipleOwners = true; +          MultiOwnersSet.insert(I->first);        }      }      break; @@ -2515,7 +2507,8 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>        assert(It != Retains.end());        const RRInfo &NewRetainRRI = It->second;        KnownSafeTD &= NewRetainRRI.KnownSafe; -      MultipleOwners |= NewRetainRRI.MultipleOwners; +      MultipleOwners = +        MultipleOwners || MultiOwnersSet.count(GetObjCArg(NewRetain));        for (SmallPtrSet<Instruction *, 2>::const_iterator               LI = NewRetainRRI.Calls.begin(),               LE = NewRetainRRI.Calls.end(); LI != LE; ++LI) { @@ -2903,8 +2896,14 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {    bool NestingDetected = Visit(F, BBStates, Retains, Releases);    // Transform. -  return PerformCodePlacement(BBStates, Retains, Releases, F.getParent()) && -         NestingDetected; +  bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains, +                                                           Releases, +                                                           F.getParent()); + +  // Cleanup. +  MultiOwnersSet.clear(); + +  return AnyPairsCompletelyEliminated && NestingDetected;  }  /// Check if there is a dependent call earlier that does not have anything in diff --git a/llvm/test/Transforms/ObjCARC/allocas.ll b/llvm/test/Transforms/ObjCARC/allocas.ll index eabd54deb7c..58740d2d802 100644 --- a/llvm/test/Transforms/ObjCARC/allocas.ll +++ b/llvm/test/Transforms/ObjCARC/allocas.ll @@ -197,6 +197,103 @@ entry:    ret void  } +; Make sure that if a store is in a different basic block we handle known safe +; conservatively. + + +; CHECK: define void @test2a(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test2a(i8* %x) { +entry: +  %A = alloca i8* +  store i8* %x, i8** %A, align 8 +  %y = load i8** %A +  br label %bb1 + +bb1: +  br label %bb2 + +bb2: +  br label %bb3 + +bb3: +  tail call i8* @objc_retain(i8* %x) +  tail call i8* @objc_retain(i8* %x) +  call void @use_alloca(i8** %A) +  call void @objc_release(i8* %y), !clang.imprecise_release !0 +  call void @use_pointer(i8* %x) +  call void @objc_release(i8* %x), !clang.imprecise_release !0 +  ret void +} + +; CHECK: define void @test2b(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test2b(i8* %x) { +entry: +  %A = alloca i8* +  %gep1 = getelementptr i8** %A, i32 0 +  store i8* %x, i8** %gep1, align 8 +  %gep2 = getelementptr i8** %A, i32 0 +  %y = load i8** %gep2 +  br label %bb1 + +bb1: +  br label %bb2 + +bb2: +  br label %bb3 + +bb3: +  tail call i8* @objc_retain(i8* %x) +  tail call i8* @objc_retain(i8* %x) +  call void @use_alloca(i8** %A) +  call void @objc_release(i8* %y), !clang.imprecise_release !0 +  call void @use_pointer(i8* %x) +  call void @objc_release(i8* %x), !clang.imprecise_release !0 +  ret void +} + +; CHECK: define void @test2c(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test2c(i8* %x) { +entry: +  %A = alloca i8*, i32 3 +  %gep1 = getelementptr i8** %A, i32 2 +  store i8* %x, i8** %gep1, align 8 +  %gep2 = getelementptr i8** %A, i32 2 +  %y = load i8** %gep2 +  tail call i8* @objc_retain(i8* %x) +  br label %bb1 + +bb1: +  br label %bb2 + +bb2: +  br label %bb3 + +bb3: +  tail call i8* @objc_retain(i8* %x) +  call void @use_alloca(i8** %A) +  call void @objc_release(i8* %y), !clang.imprecise_release !0 +  call void @use_pointer(i8* %x) +  call void @objc_release(i8* %x), !clang.imprecise_release !0 +  ret void +}  !0 = metadata !{}  | 

