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 60e2581..acf1ebb 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -389,9 +389,10 @@
   ///
   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 7a007eb..b7f83e5 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 8f88ef7..cd15f6b 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 @@
   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<CallInst>(I->getUser());
+    assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
+    ++I;
+
+    IRBuilder<> Builder(CI->getParent(), CI->getIterator());
+    SmallVector<Value *, 8> 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 cf06c1f..c42d249 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6363,56 +6363,6 @@
     // 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 76f2fd5..0000000
--- 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 0000000..be852df
--- /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*)