From: Pete Cooper Date: Tue, 18 Dec 2018 22:20:03 +0000 (+0000) Subject: Rewrite objc intrinsics to runtime methods in PreISelIntrinsicLowering instead of... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c9e35df2386ab125d0053289cf52b078718fc2e;p=llvm Rewrite objc intrinsics to runtime methods in PreISelIntrinsicLowering instead of SDAG. SelectionDAG currently changes these intrinsics to function calls, but that won't work for other ISel's. Also we want to eventually support nonlazybind and weak linkage coming from the front-end which we can't do in SelectionDAG. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349552 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 60e2581d1d4..acf1ebb5bc8 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -389,9 +389,10 @@ namespace llvm { /// ModulePass *createLowerEmuTLSPass(); - /// This pass lowers the \@llvm.load.relative intrinsic to instructions. - /// This is unsafe to do earlier because a pass may combine the constant - /// initializer into the load, which may result in an overflowing evaluation. + /// This pass lowers the \@llvm.load.relative and \@llvm.objc.* intrinsics to + /// instructions. This is unsafe to do earlier because a pass may combine the + /// constant initializer into the load, which may result in an overflowing + /// evaluation. ModulePass *createPreISelIntrinsicLoweringPass(); /// GlobalMerge - This pass merges internal (by default) globals into structs diff --git a/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/include/llvm/CodeGen/PreISelIntrinsicLowering.h index 7a007eb8bce..b7f83e515b7 100644 --- a/include/llvm/CodeGen/PreISelIntrinsicLowering.h +++ b/include/llvm/CodeGen/PreISelIntrinsicLowering.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This pass implements IR lowering for the llvm.load.relative intrinsic. +// This pass implements IR lowering for the llvm.load.relative and llvm.objc.* +// intrinsics. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PREISELINTRINSICLOWERING_H diff --git a/lib/CodeGen/PreISelIntrinsicLowering.cpp b/lib/CodeGen/PreISelIntrinsicLowering.cpp index 8f88ef78828..cd15f6b7fcb 100644 --- a/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -7,13 +7,15 @@ // //===----------------------------------------------------------------------===// // -// This pass implements IR lowering for the llvm.load.relative intrinsic. +// This pass implements IR lowering for the llvm.load.relative and llvm.objc.* +// intrinsics. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" @@ -55,11 +57,119 @@ static bool lowerLoadRelative(Function &F) { return Changed; } +static bool lowerObjCCall(Function &F, const char *NewFn) { + if (F.use_empty()) + return false; + + // If we haven't already looked up this function, check to see if the + // program already contains a function with this name. + Module *M = F.getParent(); + Constant* FCache = M->getOrInsertFunction(NewFn, F.getFunctionType()); + + for (auto I = F.use_begin(), E = F.use_end(); I != E;) { + auto *CI = dyn_cast(I->getUser()); + assert(CI->getCalledFunction() && "Cannot lower an indirect call!"); + ++I; + + IRBuilder<> Builder(CI->getParent(), CI->getIterator()); + SmallVector Args(CI->arg_begin(), CI->arg_end()); + CallInst *NewCI = Builder.CreateCall(FCache, Args); + NewCI->setName(CI->getName()); + NewCI->setTailCallKind(CI->getTailCallKind()); + if (!CI->use_empty()) + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + } + + return true; +} + static bool lowerIntrinsics(Module &M) { bool Changed = false; for (Function &F : M) { - if (F.getName().startswith("llvm.load.relative.")) + if (F.getName().startswith("llvm.load.relative.")) { Changed |= lowerLoadRelative(F); + continue; + } + switch (F.getIntrinsicID()) { + default: + break; + case Intrinsic::objc_autorelease: + Changed |= lowerObjCCall(F, "objc_autorelease"); + break; + case Intrinsic::objc_autoreleasePoolPop: + Changed |= lowerObjCCall(F, "objc_autoreleasePoolPop"); + break; + case Intrinsic::objc_autoreleasePoolPush: + Changed |= lowerObjCCall(F, "objc_autoreleasePoolPush"); + break; + case Intrinsic::objc_autoreleaseReturnValue: + Changed |= lowerObjCCall(F, "objc_autoreleaseReturnValue"); + break; + case Intrinsic::objc_copyWeak: + Changed |= lowerObjCCall(F, "objc_copyWeak"); + break; + case Intrinsic::objc_destroyWeak: + Changed |= lowerObjCCall(F, "objc_destroyWeak"); + break; + case Intrinsic::objc_initWeak: + Changed |= lowerObjCCall(F, "objc_initWeak"); + break; + case Intrinsic::objc_loadWeak: + Changed |= lowerObjCCall(F, "objc_loadWeak"); + break; + case Intrinsic::objc_loadWeakRetained: + Changed |= lowerObjCCall(F, "objc_loadWeakRetained"); + break; + case Intrinsic::objc_moveWeak: + Changed |= lowerObjCCall(F, "objc_moveWeak"); + break; + case Intrinsic::objc_release: + Changed |= lowerObjCCall(F, "objc_release"); + break; + case Intrinsic::objc_retain: + Changed |= lowerObjCCall(F, "objc_retain"); + break; + case Intrinsic::objc_retainAutorelease: + Changed |= lowerObjCCall(F, "objc_retainAutorelease"); + break; + case Intrinsic::objc_retainAutoreleaseReturnValue: + Changed |= lowerObjCCall(F, "objc_retainAutoreleaseReturnValue"); + break; + case Intrinsic::objc_retainAutoreleasedReturnValue: + Changed |= lowerObjCCall(F, "objc_retainAutoreleasedReturnValue"); + break; + case Intrinsic::objc_retainBlock: + Changed |= lowerObjCCall(F, "objc_retainBlock"); + break; + case Intrinsic::objc_storeStrong: + Changed |= lowerObjCCall(F, "objc_storeStrong"); + break; + case Intrinsic::objc_storeWeak: + Changed |= lowerObjCCall(F, "objc_storeWeak"); + break; + case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue: + Changed |= lowerObjCCall(F, "objc_unsafeClaimAutoreleasedReturnValue"); + break; + case Intrinsic::objc_retainedObject: + Changed |= lowerObjCCall(F, "objc_retainedObject"); + break; + case Intrinsic::objc_unretainedObject: + Changed |= lowerObjCCall(F, "objc_unretainedObject"); + break; + case Intrinsic::objc_unretainedPointer: + Changed |= lowerObjCCall(F, "objc_unretainedPointer"); + break; + case Intrinsic::objc_retain_autorelease: + Changed |= lowerObjCCall(F, "objc_retain_autorelease"); + break; + case Intrinsic::objc_sync_enter: + Changed |= lowerObjCCall(F, "objc_sync_enter"); + break; + case Intrinsic::objc_sync_exit: + Changed |= lowerObjCCall(F, "objc_sync_exit"); + break; + } } return Changed; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index cf06c1f0b4b..c42d2491243 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6363,56 +6363,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { // MachineFunction in SelectionDAGISel::PrepareEHLandingPad. We can safely // delete it now. return nullptr; - case Intrinsic::objc_autorelease: - return "objc_autorelease"; - case Intrinsic::objc_autoreleasePoolPop: - return "objc_autoreleasePoolPop"; - case Intrinsic::objc_autoreleasePoolPush: - return "objc_autoreleasePoolPush"; - case Intrinsic::objc_autoreleaseReturnValue: - return "objc_autoreleaseReturnValue"; - case Intrinsic::objc_copyWeak: - return "objc_copyWeak"; - case Intrinsic::objc_destroyWeak: - return "objc_destroyWeak"; - case Intrinsic::objc_initWeak: - return "objc_initWeak"; - case Intrinsic::objc_loadWeak: - return "objc_loadWeak"; - case Intrinsic::objc_loadWeakRetained: - return "objc_loadWeakRetained"; - case Intrinsic::objc_moveWeak: - return "objc_moveWeak"; - case Intrinsic::objc_release: - return "objc_release"; - case Intrinsic::objc_retain: - return "objc_retain"; - case Intrinsic::objc_retainAutorelease: - return "objc_retainAutorelease"; - case Intrinsic::objc_retainAutoreleaseReturnValue: - return "objc_retainAutoreleaseReturnValue"; - case Intrinsic::objc_retainAutoreleasedReturnValue: - return "objc_retainAutoreleasedReturnValue"; - case Intrinsic::objc_retainBlock: - return "objc_retainBlock"; - case Intrinsic::objc_storeStrong: - return "objc_storeStrong"; - case Intrinsic::objc_storeWeak: - return "objc_storeWeak"; - case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue: - return "objc_unsafeClaimAutoreleasedReturnValue"; - case Intrinsic::objc_retainedObject: - return "objc_retainedObject"; - case Intrinsic::objc_unretainedObject: - return "objc_unretainedObject"; - case Intrinsic::objc_unretainedPointer: - return "objc_unretainedPointer"; - case Intrinsic::objc_retain_autorelease: - return "objc_retain_autorelease"; - case Intrinsic::objc_sync_enter: - return "objc_sync_enter"; - case Intrinsic::objc_sync_exit: - return "objc_sync_exit"; } } diff --git a/test/CodeGen/X86/objc-arc.ll b/test/CodeGen/X86/objc-arc.ll deleted file mode 100644 index 76f2fd57816..00000000000 --- a/test/CodeGen/X86/objc-arc.ll +++ /dev/null @@ -1,230 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s - -; Make sure calls to the objc intrinsics are translated to calls in to the -; runtime - -define i8* @test_objc_autorelease(i8* %arg0) { -; CHECK-LABEL: test_objc_autorelease -; CHECK: callq _objc_autorelease -entry: - %0 = call i8* @llvm.objc.autorelease(i8* %arg0) - ret i8* %0 -} - -define void @test_objc_autoreleasePoolPop(i8* %arg0) { -; CHECK-LABEL: test_objc_autoreleasePoolPop -; CHECK: callq _objc_autoreleasePoolPop -entry: - call void @llvm.objc.autoreleasePoolPop(i8* %arg0) - ret void -} - -define i8* @test_objc_autoreleasePoolPush() { -; CHECK-LABEL: test_objc_autoreleasePoolPush -; CHECK: callq _objc_autoreleasePoolPush -entry: - %0 = call i8* @llvm.objc.autoreleasePoolPush() - ret i8* %0 -} - -define i8* @test_objc_autoreleaseReturnValue(i8* %arg0) { -; CHECK-LABEL: test_objc_autoreleaseReturnValue -; CHECK: callq _objc_autoreleaseReturnValue -entry: - %0 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %arg0) - ret i8* %0 -} - -define void @test_objc_copyWeak(i8** %arg0, i8** %arg1) { -; CHECK-LABEL: test_objc_copyWeak -; CHECK: callq _objc_copyWeak -entry: - call void @llvm.objc.copyWeak(i8** %arg0, i8** %arg1) - ret void -} - -define void @test_objc_destroyWeak(i8** %arg0) { -; CHECK-LABEL: test_objc_destroyWeak -; CHECK: callq _objc_destroyWeak -entry: - call void @llvm.objc.destroyWeak(i8** %arg0) - ret void -} - -define i8* @test_objc_initWeak(i8** %arg0, i8* %arg1) { -; CHECK-LABEL: test_objc_initWeak -; CHECK: callq _objc_initWeak -entry: - %0 = call i8* @llvm.objc.initWeak(i8** %arg0, i8* %arg1) - ret i8* %0 -} - -define i8* @test_objc_loadWeak(i8** %arg0) { -; CHECK-LABEL: test_objc_loadWeak -; CHECK: callq _objc_loadWeak -entry: - %0 = call i8* @llvm.objc.loadWeak(i8** %arg0) - ret i8* %0 -} - -define i8* @test_objc_loadWeakRetained(i8** %arg0) { -; CHECK-LABEL: test_objc_loadWeakRetained -; CHECK: callq _objc_loadWeakRetained -entry: - %0 = call i8* @llvm.objc.loadWeakRetained(i8** %arg0) - ret i8* %0 -} - -define void @test_objc_moveWeak(i8** %arg0, i8** %arg1) { -; CHECK-LABEL: test_objc_moveWeak -; CHECK: callq _objc_moveWeak -entry: - call void @llvm.objc.moveWeak(i8** %arg0, i8** %arg1) - ret void -} - -define void @test_objc_release(i8* %arg0) { -; CHECK-LABEL: test_objc_release -; CHECK: callq _objc_release -entry: - call void @llvm.objc.release(i8* %arg0) - ret void -} - -define i8* @test_objc_retain(i8* %arg0) { -; CHECK-LABEL: test_objc_retain -; CHECK: callq _objc_retain -entry: - %0 = call i8* @llvm.objc.retain(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_retainAutorelease(i8* %arg0) { -; CHECK-LABEL: test_objc_retainAutorelease -; CHECK: callq _objc_retainAutorelease -entry: - %0 = call i8* @llvm.objc.retainAutorelease(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_retainAutoreleaseReturnValue(i8* %arg0) { -; CHECK-LABEL: test_objc_retainAutoreleaseReturnValue -; CHECK: callq _objc_retainAutoreleaseReturnValue -entry: - %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_retainAutoreleasedReturnValue(i8* %arg0) { -; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue -; CHECK: callq _objc_retainAutoreleasedReturnValue -entry: - %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_retainBlock(i8* %arg0) { -; CHECK-LABEL: test_objc_retainBlock -; CHECK: callq _objc_retainBlock -entry: - %0 = call i8* @llvm.objc.retainBlock(i8* %arg0) - ret i8* %0 -} - -define void @test_objc_storeStrong(i8** %arg0, i8* %arg1) { -; CHECK-LABEL: test_objc_storeStrong -; CHECK: callq _objc_storeStrong -entry: - call void @llvm.objc.storeStrong(i8** %arg0, i8* %arg1) - ret void -} - -define i8* @test_objc_storeWeak(i8** %arg0, i8* %arg1) { -; CHECK-LABEL: test_objc_storeWeak -; CHECK: callq _objc_storeWeak -entry: - %0 = call i8* @llvm.objc.storeWeak(i8** %arg0, i8* %arg1) - ret i8* %0 -} - -define i8* @test_objc_objc_unsafeClaimAutoreleasedReturnValue(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_unsafeClaimAutoreleasedReturnValue -; CHECK: callq _objc_unsafeClaimAutoreleasedReturnValue -entry: - %0 = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_objc_retainedObject(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_retainedObject -; CHECK: callq _objc_retainedObject -entry: - %0 = call i8* @llvm.objc.retainedObject(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_objc_unretainedObject(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_unretainedObject -; CHECK: callq _objc_unretainedObject -entry: - %0 = call i8* @llvm.objc.unretainedObject(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_objc_unretainedPointer(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_unretainedPointer -; CHECK: callq _objc_unretainedPointer -entry: - %0 = call i8* @llvm.objc.unretainedPointer(i8* %arg0) - ret i8* %0 -} - -define i8* @test_objc_objc_retain_autorelease(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_retain_autorelease -; CHECK: callq _objc_retain_autorelease -entry: - %0 = call i8* @llvm.objc.retain.autorelease(i8* %arg0) - ret i8* %0 -} - -define i32 @test_objc_objc_sync_enter(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_sync_enter -; CHECK: callq _objc_sync_enter -entry: - %0 = call i32 @llvm.objc.sync.enter(i8* %arg0) - ret i32 %0 -} - -define i32 @test_objc_objc_sync_exit(i8* %arg0) { -; CHECK-LABEL: test_objc_objc_sync_exit -; CHECK: callq _objc_sync_exit -entry: - %0 = call i32 @llvm.objc.sync.exit(i8* %arg0) - ret i32 %0 -} - -declare i8* @llvm.objc.autorelease(i8*) -declare void @llvm.objc.autoreleasePoolPop(i8*) -declare i8* @llvm.objc.autoreleasePoolPush() -declare i8* @llvm.objc.autoreleaseReturnValue(i8*) -declare void @llvm.objc.copyWeak(i8**, i8**) -declare void @llvm.objc.destroyWeak(i8**) -declare i8* @llvm.objc.initWeak(i8**, i8*) -declare i8* @llvm.objc.loadWeak(i8**) -declare i8* @llvm.objc.loadWeakRetained(i8**) -declare void @llvm.objc.moveWeak(i8**, i8**) -declare void @llvm.objc.release(i8*) -declare i8* @llvm.objc.retain(i8*) -declare i8* @llvm.objc.retainAutorelease(i8*) -declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*) -declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) -declare i8* @llvm.objc.retainBlock(i8*) -declare void @llvm.objc.storeStrong(i8**, i8*) -declare i8* @llvm.objc.storeWeak(i8**, i8*) -declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*) -declare i8* @llvm.objc.retainedObject(i8*) -declare i8* @llvm.objc.unretainedObject(i8*) -declare i8* @llvm.objc.unretainedPointer(i8*) -declare i8* @llvm.objc.retain.autorelease(i8*) -declare i32 @llvm.objc.sync.enter(i8*) -declare i32 @llvm.objc.sync.exit(i8*) diff --git a/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll b/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll new file mode 100644 index 00000000000..be852dfe37f --- /dev/null +++ b/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll @@ -0,0 +1,281 @@ +; RUN: opt -pre-isel-intrinsic-lowering -S -o - %s | FileCheck %s +; RUN: opt -passes='pre-isel-intrinsic-lowering' -S -o - %s | FileCheck %s + +; Make sure calls to the objc intrinsics are translated to calls in to the +; runtime + +define i8* @test_objc_autorelease(i8* %arg0) { +; CHECK-LABEL: test_objc_autorelease +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_autorelease(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.autorelease(i8* %arg0) + ret i8* %0 +} + +define void @test_objc_autoreleasePoolPop(i8* %arg0) { +; CHECK-LABEL: test_objc_autoreleasePoolPop +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* %arg0) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.autoreleasePoolPop(i8* %arg0) + ret void +} + +define i8* @test_objc_autoreleasePoolPush() { +; CHECK-LABEL: test_objc_autoreleasePoolPush +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_autoreleasePoolPush() +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.autoreleasePoolPush() + ret i8* %0 +} + +define i8* @test_objc_autoreleaseReturnValue(i8* %arg0) { +; CHECK-LABEL: test_objc_autoreleaseReturnValue +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_autoreleaseReturnValue(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %arg0) + ret i8* %0 +} + +define void @test_objc_copyWeak(i8** %arg0, i8** %arg1) { +; CHECK-LABEL: test_objc_copyWeak +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_copyWeak(i8** %arg0, i8** %arg1) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.copyWeak(i8** %arg0, i8** %arg1) + ret void +} + +define void @test_objc_destroyWeak(i8** %arg0) { +; CHECK-LABEL: test_objc_destroyWeak +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_destroyWeak(i8** %arg0) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.destroyWeak(i8** %arg0) + ret void +} + +define i8* @test_objc_initWeak(i8** %arg0, i8* %arg1) { +; CHECK-LABEL: test_objc_initWeak +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_initWeak(i8** %arg0, i8* %arg1) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.initWeak(i8** %arg0, i8* %arg1) + ret i8* %0 +} + +define i8* @test_objc_loadWeak(i8** %arg0) { +; CHECK-LABEL: test_objc_loadWeak +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_loadWeak(i8** %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.loadWeak(i8** %arg0) + ret i8* %0 +} + +define i8* @test_objc_loadWeakRetained(i8** %arg0) { +; CHECK-LABEL: test_objc_loadWeakRetained +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_loadWeakRetained(i8** %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.loadWeakRetained(i8** %arg0) + ret i8* %0 +} + +define void @test_objc_moveWeak(i8** %arg0, i8** %arg1) { +; CHECK-LABEL: test_objc_moveWeak +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_moveWeak(i8** %arg0, i8** %arg1) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.moveWeak(i8** %arg0, i8** %arg1) + ret void +} + +define void @test_objc_release(i8* %arg0) { +; CHECK-LABEL: test_objc_release +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_release(i8* %arg0) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.release(i8* %arg0) + ret void +} + +define i8* @test_objc_retain(i8* %arg0) { +; CHECK-LABEL: test_objc_retain +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retain(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retain(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retainAutorelease(i8* %arg0) { +; CHECK-LABEL: test_objc_retainAutorelease +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retainAutorelease(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retainAutorelease(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retainAutoreleaseReturnValue(i8* %arg0) { +; CHECK-LABEL: test_objc_retainAutoreleaseReturnValue +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retainAutoreleasedReturnValue(i8* %arg0) { +; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retainBlock(i8* %arg0) { +; CHECK-LABEL: test_objc_retainBlock +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retainBlock(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retainBlock(i8* %arg0) + ret i8* %0 +} + +define void @test_objc_storeStrong(i8** %arg0, i8* %arg1) { +; CHECK-LABEL: test_objc_storeStrong +; CHECK-NEXT: entry +; CHECK-NEXT: call void @objc_storeStrong(i8** %arg0, i8* %arg1) +; CHECK-NEXT: ret void +entry: + call void @llvm.objc.storeStrong(i8** %arg0, i8* %arg1) + ret void +} + +define i8* @test_objc_storeWeak(i8** %arg0, i8* %arg1) { +; CHECK-LABEL: test_objc_storeWeak +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_storeWeak(i8** %arg0, i8* %arg1) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.storeWeak(i8** %arg0, i8* %arg1) + ret i8* %0 +} + +define i8* @test_objc_unsafeClaimAutoreleasedReturnValue(i8* %arg0) { +; CHECK-LABEL: test_objc_unsafeClaimAutoreleasedReturnValue +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retainedObject(i8* %arg0) { +; CHECK-LABEL: test_objc_retainedObject +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retainedObject(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retainedObject(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_unretainedObject(i8* %arg0) { +; CHECK-LABEL: test_objc_unretainedObject +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_unretainedObject(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.unretainedObject(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_unretainedPointer(i8* %arg0) { +; CHECK-LABEL: test_objc_unretainedPointer +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_unretainedPointer(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.unretainedPointer(i8* %arg0) + ret i8* %0 +} + +define i8* @test_objc_retain_autorelease(i8* %arg0) { +; CHECK-LABEL: test_objc_retain_autorelease +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i8* @objc_retain_autorelease(i8* %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retain.autorelease(i8* %arg0) + ret i8* %0 +} + +define i32 @test_objc_sync_enter(i8* %arg0) { +; CHECK-LABEL: test_objc_sync_enter +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i32 @objc_sync_enter(i8* %arg0) +; CHECK-NEXT: ret i32 %0 +entry: + %0 = call i32 @llvm.objc.sync.enter(i8* %arg0) + ret i32 %0 +} + +define i32 @test_objc_sync_exit(i8* %arg0) { +; CHECK-LABEL: test_objc_sync_exit +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = call i32 @objc_sync_exit(i8* %arg0) +; CHECK-NEXT: ret i32 %0 +entry: + %0 = call i32 @llvm.objc.sync.exit(i8* %arg0) + ret i32 %0 +} + +declare i8* @llvm.objc.autorelease(i8*) +declare void @llvm.objc.autoreleasePoolPop(i8*) +declare i8* @llvm.objc.autoreleasePoolPush() +declare i8* @llvm.objc.autoreleaseReturnValue(i8*) +declare void @llvm.objc.copyWeak(i8**, i8**) +declare void @llvm.objc.destroyWeak(i8**) +declare i8* @llvm.objc.initWeak(i8**, i8*) +declare i8* @llvm.objc.loadWeak(i8**) +declare i8* @llvm.objc.loadWeakRetained(i8**) +declare void @llvm.objc.moveWeak(i8**, i8**) +declare void @llvm.objc.release(i8*) +declare i8* @llvm.objc.retain(i8*) +declare i8* @llvm.objc.retainAutorelease(i8*) +declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*) +declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) +declare i8* @llvm.objc.retainBlock(i8*) +declare void @llvm.objc.storeStrong(i8**, i8*) +declare i8* @llvm.objc.storeWeak(i8**, i8*) +declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*) +declare i8* @llvm.objc.retainedObject(i8*) +declare i8* @llvm.objc.unretainedObject(i8*) +declare i8* @llvm.objc.unretainedPointer(i8*) +declare i8* @llvm.objc.retain.autorelease(i8*) +declare i32 @llvm.objc.sync.enter(i8*) +declare i32 @llvm.objc.sync.exit(i8*)