r300396 - [ObjC] Use empty Objective-C collection literal constants when

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 14 23:42:00 PDT 2017


Author: ahatanak
Date: Sat Apr 15 01:42:00 2017
New Revision: 300396

URL: http://llvm.org/viewvc/llvm-project?rev=300396&view=rev
Log:
[ObjC] Use empty Objective-C collection literal constants when
available.

Original patch by Douglas Gregor with minor modifications.

This recommits r300389, which broke bots because there have been API
changes since the original patch was written.

rdar://problem/20689633

Added:
    cfe/trunk/test/CodeGenObjC/empty-collection-literals.m
Modified:
    cfe/trunk/include/clang/Basic/ObjCRuntime.h
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/include/clang/Basic/ObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ObjCRuntime.h?rev=300396&r1=300395&r2=300396&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/ObjCRuntime.h (original)
+++ cfe/trunk/include/clang/Basic/ObjCRuntime.h Sat Apr 15 01:42:00 2017
@@ -326,6 +326,20 @@ public:
     }
   }
 
+  /// Are the empty collection symbols available?
+  bool hasEmptyCollections() const {
+    switch (getKind()) {
+    default:
+      return false;
+    case MacOSX:
+      return getVersion() >= VersionTuple(10, 11);
+    case iOS:
+      return getVersion() >= VersionTuple(9);
+    case WatchOS:
+      return getVersion() >= VersionTuple(2);
+    }
+  }
+
   /// \brief Try to parse an Objective-C runtime specification from the given
   /// string.
   ///

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=300396&r1=300395&r2=300396&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Apr 15 01:42:00 2017
@@ -117,10 +117,22 @@ llvm::Value *CodeGenFunction::EmitObjCCo
   const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E);
   if (!ALE)
     DLE = cast<ObjCDictionaryLiteral>(E);
-  
-  // Compute the type of the array we're initializing.
+
+  // Optimize empty collections by referencing constants, when available.
   uint64_t NumElements = 
     ALE ? ALE->getNumElements() : DLE->getNumElements();
+  if (NumElements == 0 && CGM.getLangOpts().ObjCRuntime.hasEmptyCollections()) {
+    StringRef ConstantName = ALE ? "__NSArray0__" : "__NSDictionary0__";
+    QualType IdTy(CGM.getContext().getObjCIdType());
+    llvm::Constant *Constant =
+        CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName);
+    Address Addr(Constant, Context.getTypeAlignInChars(IdTy));
+    LValue LV = MakeAddrLValue(Addr, IdTy);
+    return Builder.CreateBitCast(EmitLoadOfScalar(LV, E->getLocStart()),
+                                 ConvertType(E->getType()));
+  }
+
+  // Compute the type of the array we're initializing.
   llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()),
                             NumElements);
   QualType ElementType = Context.getObjCIdType().withConst();

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=300396&r1=300395&r2=300396&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Apr 15 01:42:00 2017
@@ -5980,9 +5980,21 @@ ExprResult Sema::MaybeBindToTemporary(Ex
       } else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
         D = BoxedExpr->getBoxingMethod();
       } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
+        // Don't do reclaims if we're using the zero-element array
+        // constant.
+        if (ArrayLit->getNumElements() == 0 &&
+            Context.getLangOpts().ObjCRuntime.hasEmptyCollections())
+          return E;
+
         D = ArrayLit->getArrayWithObjectsMethod();
       } else if (ObjCDictionaryLiteral *DictLit
                                         = dyn_cast<ObjCDictionaryLiteral>(E)) {
+        // Don't do reclaims if we're using the zero-element dictionary
+        // constant.
+        if (DictLit->getNumElements() == 0 &&
+            Context.getLangOpts().ObjCRuntime.hasEmptyCollections())
+          return E;
+
         D = DictLit->getDictWithObjectsMethod();
       }
 

Added: cfe/trunk/test/CodeGenObjC/empty-collection-literals.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/empty-collection-literals.m?rev=300396&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/empty-collection-literals.m (added)
+++ cfe/trunk/test/CodeGenObjC/empty-collection-literals.m Sat Apr 15 01:42:00 2017
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.10.0 -fobjc-runtime=macosx-10.10.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.11.0 -fobjc-runtime=macosx-10.11.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-1.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-2.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+#include "literal-support.h"
+
+void test_empty_array() {
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
+
+  // CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSArray0__
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+  // CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
+  NSArray *arr = @[];
+}
+
+void test_empty_dictionary() {
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+  // CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
+
+  // CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSDictionary0__
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+  // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+  // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+  // CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
+  NSDictionary *dict = @{};
+}




More information about the cfe-commits mailing list