summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/noescape.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2017-09-20 06:32:45 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2017-09-20 06:32:45 +0000
commita4e2a1bb79ad3a93151ebd059a0d2cf0f88ff4aa (patch)
tree96c3afc54ecd82000558a3017b242d752d34439c /test/CodeGenCXX/noescape.cpp
parentb87abe7024808ca31ff5bb25aecef7f92b694cfa (diff)
Add support for attribute 'noescape'.
The attribute informs the compiler that the annotated pointer parameter of a function cannot escape and enables IRGen to attach attribute 'nocapture' to parameters that are annotated with the attribute. That is the only optimization that currently takes advantage of 'noescape', but there are other optimizations that will be added later that improves IRGen for ObjC blocks. rdar://problem/19886775 Differential Revision: https://reviews.llvm.org/D32210 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313722 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/noescape.cpp')
-rw-r--r--test/CodeGenCXX/noescape.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/test/CodeGenCXX/noescape.cpp b/test/CodeGenCXX/noescape.cpp
new file mode 100644
index 0000000000..e8abd41f54
--- /dev/null
+++ b/test/CodeGenCXX/noescape.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+struct S {
+ int a[4];
+ S(int *, int * __attribute__((noescape)));
+ S &operator=(int * __attribute__((noescape)));
+ void m0(int *, int * __attribute__((noescape)));
+ virtual void vm1(int *, int * __attribute__((noescape)));
+};
+
+// CHECK: define void @_ZN1SC2EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture)
+// CHECK: define void @_ZN1SC1EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture) {{.*}} {
+// CHECK: call void @_ZN1SC2EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}})
+
+S::S(int *, int * __attribute__((noescape))) {}
+
+// CHECK: define {{.*}} %struct.S* @_ZN1SaSEPi(%struct.S* {{.*}}, {{.*}} nocapture)
+S &S::operator=(int * __attribute__((noescape))) { return *this; }
+
+// CHECK: define void @_ZN1S2m0EPiS0_(%struct.S* {{.*}}, {{.*}} nocapture)
+void S::m0(int *, int * __attribute__((noescape))) {}
+
+// CHECK: define void @_ZN1S3vm1EPiS0_(%struct.S* {{.*}}, {{.*}} nocapture)
+void S::vm1(int *, int * __attribute__((noescape))) {}
+
+// CHECK-LABEL: define void @_Z5test0P1SPiS1_(
+// CHECK: call void @_ZN1SC1EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}})
+// CHECK: call {{.*}} %struct.S* @_ZN1SaSEPi(%struct.S* {{.*}}, {{.*}} nocapture {{.*}})
+// CHECK: call void @_ZN1S2m0EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}})
+// CHECK: call void {{.*}}(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}})
+void test0(S *s, int *p0, int *p1) {
+ S t(p0, p1);
+ t = p1;
+ s->m0(p0, p1);
+ s->vm1(p0, p1);
+}
+
+namespace std {
+ typedef decltype(sizeof(0)) size_t;
+}
+
+// CHECK: define {{.*}} @_ZnwmPv({{.*}}, {{.*}} nocapture {{.*}})
+void *operator new(std::size_t, void * __attribute__((noescape)) p) {
+ return p;
+}
+
+// CHECK-LABEL: define i8* @_Z5test1Pv(
+// CHECK : %call = call {{.*}} @_ZnwmPv({{.*}}, {{.*}} nocapture {{.*}})
+void *test1(void *p0) {
+ return ::operator new(16, p0);
+}
+
+// CHECK-LABEL: define void @_Z5test2PiS_(
+// CHECK: call void @"_ZZ5test2PiS_ENK3$_0clES_S_"({{.*}}, {{.*}}, {{.*}} nocapture {{.*}})
+// CHECK: define internal void @"_ZZ5test2PiS_ENK3$_0clES_S_"({{.*}}, {{.*}}, {{.*}} nocapture)
+void test2(int *p0, int *p1) {
+ auto t = [](int *, int * __attribute__((noescape))){};
+ t(p0, p1);
+}
+
+// CHECK-LABEL: define void @_Z5test3PFvU8noescapePiES_(
+// CHECK: call void {{.*}}(i32* nocapture {{.*}})
+typedef void (*NoEscapeFunc)(__attribute__((noescape)) int *);
+
+void test3(NoEscapeFunc f, int *p) {
+ f(p);
+}