summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2017-04-15 06:42:00 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2017-04-15 06:42:00 +0000
commit4d53a1cb31c4950b2a30af3f4f6148f7216ffd92 (patch)
tree7fe753daacdc165e2f75093e8126f1fe6d619dc0
parentd26d8839d8dd4b0513ca6251ab8f341149446c69 (diff)
downloadbcm5719-llvm-4d53a1cb31c4950b2a30af3f4f6148f7216ffd92.tar.gz
bcm5719-llvm-4d53a1cb31c4950b2a30af3f4f6148f7216ffd92.zip
[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 llvm-svn: 300396
-rw-r--r--clang/include/clang/Basic/ObjCRuntime.h14
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp16
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp12
-rw-r--r--clang/test/CodeGenObjC/empty-collection-literals.m51
4 files changed, 91 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/ObjCRuntime.h b/clang/include/clang/Basic/ObjCRuntime.h
index 78fc8998824..8dc259c7ab6 100644
--- a/clang/include/clang/Basic/ObjCRuntime.h
+++ b/clang/include/clang/Basic/ObjCRuntime.h
@@ -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.
///
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index c011ab4dfc9..3a09a15dbc1 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -117,10 +117,22 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
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();
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 485d012b6e6..d65570fcef7 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5980,9 +5980,21 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
} 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();
}
diff --git a/clang/test/CodeGenObjC/empty-collection-literals.m b/clang/test/CodeGenObjC/empty-collection-literals.m
new file mode 100644
index 00000000000..0f9715f521f
--- /dev/null
+++ b/clang/test/CodeGenObjC/empty-collection-literals.m
@@ -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 = @{};
+}
OpenPOWER on IntegriCloud