Generate objc intrinsics instead of runtime calls as the ARC optimizer now works only on intrinsics

Differential Revision: https://reviews.llvm.org/D55802

Reviewers: rjmccall
llvm-svn: 349535
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index cc582b9..3747f49 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1873,12 +1873,8 @@
   EmitNounwindRuntimeCall(fn, values);
 }
 
-
-static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
-                                                llvm::FunctionType *FTy,
-                                                StringRef Name) {
-  llvm::Constant *RTF = CGM.CreateRuntimeFunction(FTy, Name);
-
+static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
+                                         llvm::Constant *RTF) {
   if (auto *F = dyn_cast<llvm::Function>(RTF)) {
     // If the target runtime doesn't naturally support ARC, emit weak
     // references to the runtime support library.  We don't really
@@ -1886,14 +1882,8 @@
     if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() &&
         !CGM.getTriple().isOSBinFormatCOFF()) {
       F->setLinkage(llvm::Function::ExternalWeakLinkage);
-    } else if (Name == "objc_retain" || Name  == "objc_release") {
-      // If we have Native ARC, set nonlazybind attribute for these APIs for
-      // performance.
-      F->addFnAttr(llvm::Attribute::NonLazyBind);
     }
   }
-
-  return RTF;
 }
 
 /// Perform an operation having the signature
@@ -1903,15 +1893,14 @@
                                           llvm::Value *value,
                                           llvm::Type *returnType,
                                           llvm::Constant *&fn,
-                                          StringRef fnName,
+                                          llvm::Intrinsic::ID IntID,
                                           bool isTailCall = false) {
   if (isa<llvm::ConstantPointerNull>(value))
     return value;
 
   if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false);
-    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+    fn = CGF.CGM.getIntrinsic(IntID);
+    setARCRuntimeFunctionLinkage(CGF.CGM, fn);
   }
 
   // Cast the argument to 'id'.
@@ -1932,11 +1921,10 @@
 static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
                                          Address addr,
                                          llvm::Constant *&fn,
-                                         StringRef fnName) {
+                                         llvm::Intrinsic::ID IntID) {
   if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrPtrTy, false);
-    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+    fn = CGF.CGM.getIntrinsic(IntID);
+    setARCRuntimeFunctionLinkage(CGF.CGM, fn);
   }
 
   // Cast the argument to 'id*'.
@@ -1959,16 +1947,13 @@
                                           Address addr,
                                           llvm::Value *value,
                                           llvm::Constant *&fn,
-                                          StringRef fnName,
+                                          llvm::Intrinsic::ID IntID,
                                           bool ignored) {
   assert(addr.getElementType() == value->getType());
 
   if (!fn) {
-    llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrTy };
-
-    llvm::FunctionType *fnType
-      = llvm::FunctionType::get(CGF.Int8PtrTy, argTypes, false);
-    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+    fn = CGF.CGM.getIntrinsic(IntID);
+    setARCRuntimeFunctionLinkage(CGF.CGM, fn);
   }
 
   llvm::Type *origType = value->getType();
@@ -1990,15 +1975,12 @@
                                  Address dst,
                                  Address src,
                                  llvm::Constant *&fn,
-                                 StringRef fnName) {
+                                 llvm::Intrinsic::ID IntID) {
   assert(dst.getType() == src.getType());
 
   if (!fn) {
-    llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrPtrTy };
-
-    llvm::FunctionType *fnType
-      = llvm::FunctionType::get(CGF.Builder.getVoidTy(), argTypes, false);
-    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+    fn = CGF.CGM.getIntrinsic(IntID);
+    setARCRuntimeFunctionLinkage(CGF.CGM, fn);
   }
 
   llvm::Value *args[] = {
@@ -2008,6 +1990,34 @@
   CGF.EmitNounwindRuntimeCall(fn, args);
 }
 
+/// Perform an operation having the signature
+///   i8* (i8*)
+/// where a null input causes a no-op and returns null.
+static llvm::Value *emitObjCValueOperation(CodeGenFunction &CGF,
+                                           llvm::Value *value,
+                                           llvm::Type *returnType,
+                                           llvm::Constant *&fn,
+                                           StringRef fnName) {
+  if (isa<llvm::ConstantPointerNull>(value))
+    return value;
+
+  if (!fn) {
+    llvm::FunctionType *fnType =
+      llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false);
+    fn = CGF.CGM.CreateRuntimeFunction(fnType, fnName);
+  }
+
+  // Cast the argument to 'id'.
+  llvm::Type *origType = returnType ? returnType : value->getType();
+  value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
+
+  // Call the function.
+  llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value);
+
+  // Cast the result back to the original type.
+  return CGF.Builder.CreateBitCast(call, origType);
+}
+
 /// Produce the code to do a retain.  Based on the type, calls one of:
 ///   call i8* \@objc_retain(i8* %value)
 ///   call i8* \@objc_retainBlock(i8* %value)
@@ -2023,7 +2033,7 @@
 llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
   return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_retain,
-                               "objc_retain");
+                               llvm::Intrinsic::objc_retain);
 }
 
 /// Retain the given block, with _Block_copy semantics.
@@ -2037,7 +2047,7 @@
   llvm::Value *result
     = emitARCValueOperation(*this, value, nullptr,
                             CGM.getObjCEntrypoints().objc_retainBlock,
-                            "objc_retainBlock");
+                            llvm::Intrinsic::objc_retainBlock);
 
   // If the copy isn't mandatory, add !clang.arc.copy_on_escape to
   // tell the optimizer that it doesn't need to do this copy if the
@@ -2107,7 +2117,7 @@
   emitAutoreleasedReturnValueMarker(*this);
   return emitARCValueOperation(*this, value, nullptr,
               CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
-                               "objc_retainAutoreleasedReturnValue");
+                           llvm::Intrinsic::objc_retainAutoreleasedReturnValue);
 }
 
 /// Claim a possibly-autoreleased return value at +0.  This is only
@@ -2122,7 +2132,7 @@
   emitAutoreleasedReturnValueMarker(*this);
   return emitARCValueOperation(*this, value, nullptr,
               CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue,
-                               "objc_unsafeClaimAutoreleasedReturnValue");
+                     llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);
 }
 
 /// Release the given object.
@@ -2133,9 +2143,8 @@
 
   llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release;
   if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
-    fn = createARCRuntimeFunction(CGM, fnType, "objc_release");
+    fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release);
+    setARCRuntimeFunctionLinkage(CGM, fn);
   }
 
   // Cast the argument to 'id'.
@@ -2180,10 +2189,8 @@
 
   llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
   if (!fn) {
-    llvm::Type *argTypes[] = { Int8PtrPtrTy, Int8PtrTy };
-    llvm::FunctionType *fnType
-      = llvm::FunctionType::get(Builder.getVoidTy(), argTypes, false);
-    fn = createARCRuntimeFunction(CGM, fnType, "objc_storeStrong");
+    fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong);
+    setARCRuntimeFunctionLinkage(CGM, fn);
   }
 
   llvm::Value *args[] = {
@@ -2237,7 +2244,7 @@
 llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
   return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_autorelease,
-                               "objc_autorelease");
+                               llvm::Intrinsic::objc_autorelease);
 }
 
 /// Autorelease the given object.
@@ -2246,7 +2253,7 @@
 CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
   return emitARCValueOperation(*this, value, nullptr,
                             CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
-                               "objc_autoreleaseReturnValue",
+                               llvm::Intrinsic::objc_autoreleaseReturnValue,
                                /*isTailCall*/ true);
 }
 
@@ -2256,7 +2263,7 @@
 CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
   return emitARCValueOperation(*this, value, nullptr,
                      CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue,
-                               "objc_retainAutoreleaseReturnValue",
+                             llvm::Intrinsic::objc_retainAutoreleaseReturnValue,
                                /*isTailCall*/ true);
 }
 
@@ -2285,7 +2292,7 @@
 CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
   return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_retainAutorelease,
-                               "objc_retainAutorelease");
+                               llvm::Intrinsic::objc_retainAutorelease);
 }
 
 /// i8* \@objc_loadWeak(i8** %addr)
@@ -2293,14 +2300,14 @@
 llvm::Value *CodeGenFunction::EmitARCLoadWeak(Address addr) {
   return emitARCLoadOperation(*this, addr,
                               CGM.getObjCEntrypoints().objc_loadWeak,
-                              "objc_loadWeak");
+                              llvm::Intrinsic::objc_loadWeak);
 }
 
 /// i8* \@objc_loadWeakRetained(i8** %addr)
 llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(Address addr) {
   return emitARCLoadOperation(*this, addr,
                               CGM.getObjCEntrypoints().objc_loadWeakRetained,
-                              "objc_loadWeakRetained");
+                              llvm::Intrinsic::objc_loadWeakRetained);
 }
 
 /// i8* \@objc_storeWeak(i8** %addr, i8* %value)
@@ -2310,7 +2317,7 @@
                                                bool ignored) {
   return emitARCStoreOperation(*this, addr, value,
                                CGM.getObjCEntrypoints().objc_storeWeak,
-                               "objc_storeWeak", ignored);
+                               llvm::Intrinsic::objc_storeWeak, ignored);
 }
 
 /// i8* \@objc_initWeak(i8** %addr, i8* %value)
@@ -2330,7 +2337,7 @@
 
   emitARCStoreOperation(*this, addr, value,
                         CGM.getObjCEntrypoints().objc_initWeak,
-                        "objc_initWeak", /*ignored*/ true);
+                        llvm::Intrinsic::objc_initWeak, /*ignored*/ true);
 }
 
 /// void \@objc_destroyWeak(i8** %addr)
@@ -2338,9 +2345,8 @@
 void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
   llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
   if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrPtrTy, false);
-    fn = createARCRuntimeFunction(CGM, fnType, "objc_destroyWeak");
+    fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak);
+    setARCRuntimeFunctionLinkage(CGM, fn);
   }
 
   // Cast the argument to 'id*'.
@@ -2355,7 +2361,7 @@
 void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) {
   emitARCCopyOperation(*this, dst, src,
                        CGM.getObjCEntrypoints().objc_moveWeak,
-                       "objc_moveWeak");
+                       llvm::Intrinsic::objc_moveWeak);
 }
 
 /// void \@objc_copyWeak(i8** %dest, i8** %src)
@@ -2364,7 +2370,7 @@
 void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) {
   emitARCCopyOperation(*this, dst, src,
                        CGM.getObjCEntrypoints().objc_copyWeak,
-                       "objc_copyWeak");
+                       llvm::Intrinsic::objc_copyWeak);
 }
 
 void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr,
@@ -2387,9 +2393,8 @@
 llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
   llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
   if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(Int8PtrTy, false);
-    fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPush");
+    fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush);
+    setARCRuntimeFunctionLinkage(CGM, fn);
   }
 
   return EmitNounwindRuntimeCall(fn);
@@ -2400,18 +2405,28 @@
 void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
   assert(value->getType() == Int8PtrTy);
 
-  llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
-  if (!fn) {
-    llvm::FunctionType *fnType =
-      llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+  if (getInvokeDest()) {
+    // Call the runtime method not the intrinsic if we are handling exceptions
+    llvm::Constant *&fn =
+      CGM.getObjCEntrypoints().objc_autoreleasePoolPopInvoke;
+    if (!fn) {
+      llvm::FunctionType *fnType =
+        llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+      fn = CGM.CreateRuntimeFunction(fnType, "objc_autoreleasePoolPop");
+      setARCRuntimeFunctionLinkage(CGM, fn);
+    }
 
-    // We don't want to use a weak import here; instead we should not
-    // fall into this path.
-    fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPop");
+    // objc_autoreleasePoolPop can throw.
+    EmitRuntimeCallOrInvoke(fn, value);
+  } else {
+    llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
+    if (!fn) {
+      fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop);
+      setARCRuntimeFunctionLinkage(CGM, fn);
+    }
+
+    EmitRuntimeCall(fn, value);
   }
-
-  // objc_autoreleasePoolPop can throw.
-  EmitRuntimeCallOrInvoke(fn, value);
 }
 
 /// Produce the code to do an MRR version objc_autoreleasepool_push.
@@ -2446,18 +2461,18 @@
 ///   call i8* \@objc_alloc(i8* %value)
 llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value,
                                             llvm::Type *resultType) {
-  return emitARCValueOperation(*this, value, resultType,
-                               CGM.getObjCEntrypoints().objc_alloc,
-                               "objc_alloc");
+  return emitObjCValueOperation(*this, value, resultType,
+                                CGM.getObjCEntrypoints().objc_alloc,
+                                "objc_alloc");
 }
 
 /// Allocate the given objc object.
 ///   call i8* \@objc_allocWithZone(i8* %value)
 llvm::Value *CodeGenFunction::EmitObjCAllocWithZone(llvm::Value *value,
                                                     llvm::Type *resultType) {
-  return emitARCValueOperation(*this, value, resultType,
-                               CGM.getObjCEntrypoints().objc_allocWithZone,
-                               "objc_allocWithZone");
+  return emitObjCValueOperation(*this, value, resultType,
+                                CGM.getObjCEntrypoints().objc_allocWithZone,
+                                "objc_allocWithZone");
 }
 
 /// Produce the code to do a primitive release.
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 0f6c3be..f0d72af 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -128,6 +128,10 @@
   /// void objc_autoreleasePoolPop(void*);
   llvm::Constant *objc_autoreleasePoolPop;
 
+  /// void objc_autoreleasePoolPop(void*);
+  /// Note this method is used when we are using exception handling
+  llvm::Constant *objc_autoreleasePoolPopInvoke;
+
   /// void *objc_autoreleasePoolPush(void);
   llvm::Constant *objc_autoreleasePoolPush;