diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp index 1ca6ddabac5bc..dcc47582cf520 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp @@ -103,12 +103,16 @@ CallInst *BundledRetainClaimRVs::insertRVCallWithColors( Instruction *InsertPt, CallBase *AnnotatedCall, const DenseMap &BlockColors) { IRBuilder<> Builder(InsertPt); - Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall); - assert(Func && "operand isn't a Function"); - Type *ParamTy = Func->getArg(0)->getType(); + Optional Func = objcarc::getAttachedARCFunction(AnnotatedCall); + // This might be a call with an empty bundle, because contract already ran. + // In that case, we don't have to insert another call. + if (!Func) + return nullptr; + + Type *ParamTy = (*Func)->getArg(0)->getType(); Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy); auto *Call = - createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors); + createCallInstWithColors(*Func, CallArg, "", InsertPt, BlockColors); RVCalls[Call] = AnnotatedCall; return Call; } diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index c2ed94e8e1f62..a0738f45594af 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -580,8 +580,8 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) { if (auto *CI = dyn_cast(Inst)) if (objcarc::hasAttachedCallOpBundle(CI)) { - BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors); - --I; + if (BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors)) + --I; Changed = true; } diff --git a/llvm/test/Transforms/ObjCARC/contract-rv-attr-empty-bundle.ll b/llvm/test/Transforms/ObjCARC/contract-rv-attr-empty-bundle.ll new file mode 100644 index 0000000000000..1f6ffdbf74e0b --- /dev/null +++ b/llvm/test/Transforms/ObjCARC/contract-rv-attr-empty-bundle.ll @@ -0,0 +1,32 @@ +; RUN: opt -objc-arc-contract -S < %s | FileCheck %s +; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s + +; CHECK-LABEL: define void @test0() { +; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ] +; CHECK-NEXT: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""() +; CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL]]) + +define void @test0() { + %call1 = notail call i8* @foo() [ "clang.arc.attachedcall"() ] + call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) + ret void +} + +; CHECK-LABEL: define void @test1() { +; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ] +; CHECK-NEXT: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""() +; CHECK-NEXT: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]]) + +define void @test1() { + %call1 = notail call i8* @foo() [ "clang.arc.attachedcall"() ] + call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %call1) + ret void +} + +declare i8* @foo() +declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) +declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*) + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue"}