From 604ae0b712af9143d2211c42c2584b529791cdfd Mon Sep 17 00:00:00 2001 From: Pete Cooper Date: Fri, 27 May 2016 02:13:53 +0000 Subject: [PATCH] Form objc_storeStrong in the presence of bitcasts. objc_storeStrong can be formed from a sequence such as %0 = tail call i8* @objc_retain(i8* %p) nounwind %tmp = load i8*, i8** @x, align 8 store i8* %0, i8** @x, align 8 tail call void @objc_release(i8* %tmp) nounwind The code was already looking through bitcasts for most of the values involved, but had missed one case where the pointer operand for the store was a bitcast. Ultimately the pointer for the load and store have to be the same value, after stripping casts. llvm-svn: 270955 --- lib/Transforms/ObjCARC/ObjCARCContract.cpp | 3 ++- .../ObjCARC/contract-storestrong.ll | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/lib/Transforms/ObjCARC/ObjCARCContract.cpp index ef70d4c4392..11e2d03e17d 100644 --- a/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -201,6 +201,7 @@ static StoreInst *findSafeStoreForStoreStrongContraction(LoadInst *Load, // Get the location associated with Load. MemoryLocation Loc = MemoryLocation::get(Load); + auto *LocPtr = Loc.Ptr->stripPointerCasts(); // Walk down to find the store and the release, which may be in either order. for (auto I = std::next(BasicBlock::iterator(Load)), @@ -261,7 +262,7 @@ static StoreInst *findSafeStoreForStoreStrongContraction(LoadInst *Load, // Then make sure that the pointer we are storing to is Ptr. If so, we // found our Store! - if (Store->getPointerOperand() == Loc.Ptr) + if (Store->getPointerOperand()->stripPointerCasts() == LocPtr) continue; // Otherwise, we have an unknown store to some other ptr that clobbers diff --git a/test/Transforms/ObjCARC/contract-storestrong.ll b/test/Transforms/ObjCARC/contract-storestrong.ll index aadc3a26539..2b83bdb9bfb 100644 --- a/test/Transforms/ObjCARC/contract-storestrong.ll +++ b/test/Transforms/ObjCARC/contract-storestrong.ll @@ -217,6 +217,32 @@ entry: ret i1 %t } +; Make sure that we form the store strong even if there are bitcasts on +; the pointers. +; CHECK-LABEL: define void @test12( +; CHECK: entry: +; CHECK-NEXT: %p16 = bitcast i8** @x to i16** +; CHECK-NEXT: %tmp16 = load i16*, i16** %p16, align 8 +; CHECK-NEXT: %tmp8 = bitcast i16* %tmp16 to i8* +; CHECK-NEXT: %p32 = bitcast i8** @x to i32** +; CHECK-NEXT: %v32 = bitcast i8* %p to i32* +; CHECK-NEXT: %0 = bitcast i16** %p16 to i8** +; CHECK-NEXT: tail call void @objc_storeStrong(i8** %0, i8* %p) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test12(i8* %p) { +entry: + %retain = tail call i8* @objc_retain(i8* %p) nounwind + %p16 = bitcast i8** @x to i16** + %tmp16 = load i16*, i16** %p16, align 8 + %tmp8 = bitcast i16* %tmp16 to i8* + %p32 = bitcast i8** @x to i32** + %v32 = bitcast i8* %retain to i32* + store i32* %v32, i32** %p32, align 8 + tail call void @objc_release(i8* %tmp8) nounwind + ret void +} + !0 = !{} ; CHECK: attributes [[NUW]] = { nounwind }