From 58fb3401fa63174cd37281d167b16d90e84a47be Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 25 Jun 2012 19:47:37 +0000 Subject: [PATCH] Fix the objc_autoreleasedReturnValue optimization code to locate the call correctly even in the case where it is an invoke. This fixes rdar://11714057. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159157 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/ObjCARC.cpp | 19 ++++++++-- test/Transforms/ObjCARC/contract-testcases.ll | 35 ++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp index d89996a1ff6..87e17c7f90a 100644 --- a/lib/Transforms/Scalar/ObjCARC.cpp +++ b/lib/Transforms/Scalar/ObjCARC.cpp @@ -4064,8 +4064,22 @@ bool ObjCARCContract::runOnFunction(Function &F) { if (!RetainRVMarker) break; BasicBlock::iterator BBI = Inst; - --BBI; - while (isNoopInstruction(BBI)) --BBI; + BasicBlock *InstParent = Inst->getParent(); + + // Step up to see if the call immediately precedes the RetainRV call. + // If it's an invoke, we have to cross a block boundary. And we have + // to carefully dodge no-op instructions. + do { + if (&*BBI == InstParent->begin()) { + BasicBlock *Pred = InstParent->getSinglePredecessor(); + if (!Pred) + goto decline_rv_optimization; + BBI = Pred->getTerminator(); + break; + } + --BBI; + } while (isNoopInstruction(BBI)); + if (&*BBI == GetObjCArg(Inst)) { Changed = true; InlineAsm *IA = @@ -4075,6 +4089,7 @@ bool ObjCARCContract::runOnFunction(Function &F) { /*Constraints=*/"", /*hasSideEffects=*/true); CallInst::Create(IA, "", Inst); } + decline_rv_optimization: break; } case IC_InitWeak: { diff --git a/test/Transforms/ObjCARC/contract-testcases.ll b/test/Transforms/ObjCARC/contract-testcases.ll index 69fa8376757..1510ed00e69 100644 --- a/test/Transforms/ObjCARC/contract-testcases.ll +++ b/test/Transforms/ObjCARC/contract-testcases.ll @@ -4,17 +4,17 @@ %0 = type opaque %1 = type opaque %2 = type { i64, i64 } -%3 = type { i8*, i8* } %4 = type opaque declare %0* @"\01-[NSAttributedString(Terminal) pathAtIndex:effectiveRange:]"(%1*, i8* nocapture, i64, %2*) optsize declare i8* @objc_retainAutoreleasedReturnValue(i8*) -declare i8* @objc_msgSend_fixup(i8*, %3*, ...) +declare i8* @objc_msgSend_fixup(i8*, i8*, ...) +declare i8* @objc_msgSend(i8*, i8*, ...) declare void @objc_release(i8*) declare %2 @NSUnionRange(i64, i64, i64, i64) optsize declare i8* @objc_autoreleaseReturnValue(i8*) declare i8* @objc_autorelease(i8*) -declare i8* @objc_msgSend() nonlazybind +declare i32 @__gxx_personality_sj0(...) ; Don't get in trouble on bugpointed code. @@ -52,7 +52,7 @@ bb6: ; preds = %bb5, %bb4, %bb4, %b ; CHECK: %tmp8 = phi %0* [ %0, %bb ], [ %0, %bb ] define void @test1() { bb: - %tmp = tail call %0* bitcast (i8* ()* @objc_msgSend to %0* ()*)() + %tmp = tail call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %0* ()*)() %tmp2 = bitcast %0* %tmp to i8* %tmp3 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tmp2) nounwind br i1 undef, label %bb7, label %bb7 @@ -61,3 +61,30 @@ bb7: ; preds = %bb6, %bb6, %bb5 %tmp8 = phi %0* [ %tmp, %bb ], [ %tmp, %bb ] unreachable } + +; When looking for the defining instruction for an objc_retainAutoreleasedReturnValue +; call, handle the case where it's an invoke in a different basic block. +; rdar://11714057 + +; CHECK: define void @_Z6doTestP8NSString() { +; CHECK: invoke.cont: ; preds = %entry +; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue", ""() +; CHECK-NEXT: %tmp = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind +define void @_Z6doTestP8NSString() { +entry: + %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)() + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + %tmp = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + unreachable + +lpad: ; preds = %entry + %tmp1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) + cleanup + resume { i8*, i32 } undef +} + +!clang.arc.retainAutoreleasedReturnValueMarker = !{!0} + +!0 = metadata !{metadata !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}