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

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 14 22:31:36 PDT 2017


Author: ahatanak
Date: Sat Apr 15 00:31:35 2017
New Revision: 300389

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

Original patch by Douglas Gregor with minor modifications.

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=300389&r1=300388&r2=300389&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/ObjCRuntime.h (original)
+++ cfe/trunk/include/clang/Basic/ObjCRuntime.h Sat Apr 15 00:31:35 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=300389&r1=300388&r2=300389&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Apr 15 00:31:35 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);
+    LValue LV = LValue::MakeAddr(Constant, IdTy,
+                                 Context.getTypeAlignInChars(IdTy), Context);
+    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=300389&r1=300388&r2=300389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Apr 15 00:31:35 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=300389&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/empty-collection-literals.m (added)
+++ cfe/trunk/test/CodeGenObjC/empty-collection-literals.m Sat Apr 15 00:31:35 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