waltl updated this revision to Diff 372035.
waltl added a comment.

Trivial cleanup.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108243/new/

https://reviews.llvm.org/D108243

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/arc-block-copy-escape.m
  clang/test/CodeGenObjC/arc-blocks.m
  clang/test/CodeGenObjCXX/arc-blocks.mm
  clang/test/PCH/arc-blocks.mm

Index: clang/test/PCH/arc-blocks.mm
===================================================================
--- clang/test/PCH/arc-blocks.mm
+++ clang/test/PCH/arc-blocks.mm
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -fblocks -std=c++1y -emit-pch %s -o %t
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -fblocks -std=c++1y -include-pch %t -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -fblocks -std=c++1y -include-pch %t -fobjc-avoid-heapify-local-blocks -emit-llvm -o - %s | FileCheck %s
 
 #ifndef HEADER_INCLUDED
 #define HEADER_INCLUDED
Index: clang/test/CodeGenObjCXX/arc-blocks.mm
===================================================================
--- clang/test/CodeGenObjCXX/arc-blocks.mm
+++ clang/test/CodeGenObjCXX/arc-blocks.mm
@@ -1,9 +1,11 @@
 // RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s
 // RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s
 // RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck -check-prefix CHECK-NOEXCP %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -fobjc-avoid-heapify-local-blocks -o - %s | FileCheck -check-prefix CHECK-NOHEAP %s
 
 // CHECK: [[A:.*]] = type { i64, [10 x i8*] }
 // CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK-NOHEAP: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
 // CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
 // CHECK: %[[STRUCT_TRIVIAL_INTERNAL:.*]] = type { i32 }
 
@@ -209,8 +211,8 @@
 
 namespace test_block_retain {
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain14initializationEP11objc_object(
-// CHECK-NOT: @llvm.objc.retainBlock(
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain14initializationEP11objc_object(
+// CHECK-NOHEAP-NOT: @llvm.objc.retainBlock(
   void initialization(id a) {
     BlockTy b0 = ^{ foo1(a); };
     BlockTy b1 = (^{ foo1(a); });
@@ -218,23 +220,23 @@
     b1();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain20initializationStaticEP11objc_object(
-// CHECK: @llvm.objc.retainBlock(
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain20initializationStaticEP11objc_object(
+// CHECK-NOHEAP: @llvm.objc.retainBlock(
   void initializationStatic(id a) {
     static BlockTy b0 = ^{ foo1(a); };
     b0();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain15initialization2EP11objc_object
-// CHECK: %[[B0:.*]] = alloca void ()*, align 8
-// CHECK: %[[B1:.*]] = alloca void ()*, align 8
-// CHECK: load void ()*, void ()** %[[B0]], align 8
-// CHECK-NOT: @llvm.objc.retainBlock
-// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
-// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
-// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]])
-// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
-// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain15initialization2EP11objc_object
+// CHECK-NOHEAP: %[[B0:.*]] = alloca void ()*, align 8
+// CHECK-NOHEAP: %[[B1:.*]] = alloca void ()*, align 8
+// CHECK-NOHEAP: load void ()*, void ()** %[[B0]], align 8
+// CHECK-NOHEAP-NOT: @llvm.objc.retainBlock
+// CHECK-NOHEAP: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
+// CHECK-NOHEAP: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
+// CHECK-NOHEAP: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]])
+// CHECK-NOHEAP: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
+// CHECK-NOHEAP: store void ()* %[[V12]], void ()** %[[B1]], align 8
   void initialization2(id a) {
     BlockTy b0 = ^{ foo1(a); };
     b0();
@@ -242,8 +244,8 @@
     b1();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain10assignmentEP11objc_object(
-// CHECK-NOT: @llvm.objc.retainBlock(
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain10assignmentEP11objc_object(
+// CHECK-NOHEAP-NOT: @llvm.objc.retainBlock(
   void assignment(id a) {
     BlockTy b0;
     (b0) = ^{ foo1(a); };
@@ -252,16 +254,16 @@
     b0();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain16assignmentStaticEP11objc_object(
-// CHECK: @llvm.objc.retainBlock(
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain16assignmentStaticEP11objc_object(
+// CHECK-NOHEAP: @llvm.objc.retainBlock(
   void assignmentStatic(id a) {
     static BlockTy b0;
     b0 = ^{ foo1(a); };
     b0();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain21assignmentConditionalEP11objc_objectb(
-// CHECK: @llvm.objc.retainBlock(
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain21assignmentConditionalEP11objc_objectb(
+// CHECK-NOHEAP: @llvm.objc.retainBlock(
   void assignmentConditional(id a, bool c) {
     BlockTy b0;
     if (c)
@@ -270,16 +272,16 @@
     b0();
   }
 
-// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain11assignment2EP11objc_object(
-// CHECK: %[[B0:.*]] = alloca void ()*, align 8
-// CHECK: %[[B1:.*]] = alloca void ()*, align 8
-// CHECK-NOT: @llvm.objc.retainBlock
-// CHECK: store void ()* null, void ()** %[[B1]], align 8
-// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
-// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
-// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]]
-// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
-// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8
+// CHECK-NOHEAP-LABEL: define{{.*}} void @_ZN17test_block_retain11assignment2EP11objc_object(
+// CHECK-NOHEAP: %[[B0:.*]] = alloca void ()*, align 8
+// CHECK-NOHEAP: %[[B1:.*]] = alloca void ()*, align 8
+// CHECK-NOHEAP-NOT: @llvm.objc.retainBlock
+// CHECK-NOHEAP: store void ()* null, void ()** %[[B1]], align 8
+// CHECK-NOHEAP: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
+// CHECK-NOHEAP: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
+// CHECK-NOHEAP: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]]
+// CHECK-NOHEAP: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
+// CHECK-NOHEAP: store void ()* %[[V12]], void ()** %[[B1]], align 8
   void assignment2(id a) {
     BlockTy b0 = ^{ foo1(a); };
     b0();
@@ -290,30 +292,30 @@
 
 // We cannot remove the call to @llvm.objc.retainBlock if the variable is of type id.
 
-// CHECK: define{{.*}} void @_ZN17test_block_retain21initializationObjCPtrEP11objc_object(
-// CHECK: alloca i8*, align 8
-// CHECK: %[[B0:.*]] = alloca i8*, align 8
-// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
-// CHECK: %[[V3:.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]] to void ()*
-// CHECK: %[[V4:.*]] = bitcast void ()* %[[V3]] to i8*
-// CHECK: %[[V5:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V4]])
-// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to void ()*
-// CHECK: %[[V7:.*]] = bitcast void ()* %[[V6]] to i8*
-// CHECK: store i8* %[[V7]], i8** %[[B0]], align 8
+// CHECK-NOHEAP: define{{.*}} void @_ZN17test_block_retain21initializationObjCPtrEP11objc_object(
+// CHECK-NOHEAP: alloca i8*, align 8
+// CHECK-NOHEAP: %[[B0:.*]] = alloca i8*, align 8
+// CHECK-NOHEAP: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+// CHECK-NOHEAP: %[[V3:.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]] to void ()*
+// CHECK-NOHEAP: %[[V4:.*]] = bitcast void ()* %[[V3]] to i8*
+// CHECK-NOHEAP: %[[V5:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V4]])
+// CHECK-NOHEAP: %[[V6:.*]] = bitcast i8* %[[V5]] to void ()*
+// CHECK-NOHEAP: %[[V7:.*]] = bitcast void ()* %[[V6]] to i8*
+// CHECK-NOHEAP: store i8* %[[V7]], i8** %[[B0]], align 8
   void initializationObjCPtr(id a) {
     id b0 = ^{ foo1(a); };
     ((BlockTy)b0)();
   }
 
-// CHECK: define{{.*}} void @_ZN17test_block_retain17assignmentObjCPtrEP11objc_object(
-// CHECK: %[[B0:.*]] = alloca void ()*, align 8
-// CHECK: %[[B1:.*]] = alloca i8*, align 8
-// CHECK: %[[V4:.*]] = load void ()*, void ()** %[[B0]], align 8
-// CHECK: %[[V5:.*]] = bitcast void ()* %[[V4]] to i8*
-// CHECK: %[[V6:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V5]])
-// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to void ()*
-// CHECK: %[[V8:.*]] = bitcast void ()* %[[V7]] to i8*
-// CHECK: store i8* %[[V8]], i8** %[[B1]], align 8
+// CHECK-NOHEAP: define{{.*}} void @_ZN17test_block_retain17assignmentObjCPtrEP11objc_object(
+// CHECK-NOHEAP: %[[B0:.*]] = alloca void ()*, align 8
+// CHECK-NOHEAP: %[[B1:.*]] = alloca i8*, align 8
+// CHECK-NOHEAP: %[[V4:.*]] = load void ()*, void ()** %[[B0]], align 8
+// CHECK-NOHEAP: %[[V5:.*]] = bitcast void ()* %[[V4]] to i8*
+// CHECK-NOHEAP: %[[V6:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V5]])
+// CHECK-NOHEAP: %[[V7:.*]] = bitcast i8* %[[V6]] to void ()*
+// CHECK-NOHEAP: %[[V8:.*]] = bitcast void ()* %[[V7]] to i8*
+// CHECK-NOHEAP: store i8* %[[V8]], i8** %[[B1]], align 8
   void assignmentObjCPtr(id a) {
     BlockTy b0 = ^{ foo1(a); };
     id b1;
Index: clang/test/CodeGenObjC/arc-blocks.m
===================================================================
--- clang/test/CodeGenObjC/arc-blocks.m
+++ clang/test/CodeGenObjC/arc-blocks.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-COMMON %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-HEAP -check-prefix=CHECK-COMMON %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -fobjc-avoid-heapify-local-blocks -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NOHEAP -check-prefix=CHECK-COMMON %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT -check-prefix=CHECK-COMMON %s
 
 // CHECK-COMMON: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
@@ -320,7 +321,7 @@
 // CHECK-LABEL:    define{{.*}} i8* @test9(
 // CHECK:      load i8*, i8** getelementptr
 // CHECK-NEXT: bitcast i8*
-// CHECK-NEXT: call i8* 
+// CHECK-NEXT: call i8*
 // CHECK-NEXT: tail call i8* @llvm.objc.autoreleaseReturnValue
 // CHECK-NEXT: ret i8*
 
@@ -334,31 +335,35 @@
 // when the initialization captures the variable.
 void test10a(void) {
   __block void (^block)(void) = ^{ block(); };
-  // CHECK-LABEL:    define{{.*}} void @test10a()
-  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
-  // CHECK:      [[BLOCK1:%.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+  // CHECK-LABEL:       define{{.*}} void @test10a()
+  // CHECK:             [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
+  // CHECK-NOHEAP:      [[BLOCK1:%.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
 
   // Zero-initialization before running the initializer.
-  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
-  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
+  // CHECK:             [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+  // CHECK-NEXT:        store void ()* null, void ()** [[T0]], align 8
 
   // Run the initializer as an assignment.
-  // CHECK:      [[T2:%.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* [[BLOCK1]] to void ()*
-  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
-  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
-  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
-  // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
-  // CHECK-NEXT: store void ()* [[T2]], void ()** [[T5]], align 8
-  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
-  // CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
+  // CHECK-HEAP:        [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
+  // CHECK-HEAP-NEXT:   [[T1:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T0]])
+  // CHECK-HEAP-NEXT:   [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
+  // CHECK-NOHEAP:      [[T2:%.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* [[BLOCK1]] to void ()*
+  // CHECK-NEXT:        [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
+  // CHECK-NEXT:        [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
+  // CHECK-NEXT:        [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
+  // CHECK-NEXT:        [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
+  // CHECK-HEAP-NEXT:   store void ()* {{%.*}}, void ()** [[T5]], align 8
+  // CHECK-NOHEAP-NEXT: store void ()* [[T2]], void ()** [[T5]], align 8
+  // CHECK-NEXT:        [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
+  // CHECK-NEXT:        call void @llvm.objc.release(i8* [[T7]])
 
   // Destroy at end of function.
-  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
-  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
-  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
-  // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
-  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
-  // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
+  // CHECK-NEXT:        [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+  // CHECK-NEXT:        [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
+  // CHECK-NEXT:        call void @_Block_object_dispose(i8* [[T0]], i32 8)
+  // CHECK-NEXT:        [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
+  // CHECK-NEXT:        [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
+  // CHECK-NEXT:        call void @llvm.objc.release(i8* [[T2]])
   // CHECK: ret void
 }
 
@@ -396,32 +401,36 @@
   __block void (^block)(void);
   block = ^{ block(); };
 
-  // CHECK-LABEL:    define{{.*}} void @test10b()
-  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
-  // CHECK:      [[BLOCK3:%.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+  // CHECK-LABEL:       define{{.*}} void @test10b()
+  // CHECK:             [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
+  // CHECK-NOHEAP:      [[BLOCK3:%.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
 
   // Zero-initialize.
-  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
-  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
+  // CHECK:             [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+  // CHECK-NEXT:        store void ()* null, void ()** [[T0]], align 8
 
-  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+  // CHECK-NEXT:        [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
 
   // The assignment.
-  // CHECK:      [[T2:%.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* [[BLOCK3]] to void ()*
-  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
-  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
-  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
-  // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
-  // CHECK-NEXT: store void ()* [[T2]], void ()** [[T5]], align 8
-  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
-  // CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
+  // CHECK-HEAP:        [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
+  // CHECK-HEAP-NEXT:   [[T1:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T0]])
+  // CHECK-HEAP-NEXT:   [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
+  // CHECK-NOHEAP:      [[T2:%.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* [[BLOCK3]] to void ()*
+  // CHECK-NEXT:        [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
+  // CHECK-NEXT:        [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
+  // CHECK-NEXT:        [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
+  // CHECK-NEXT:        [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
+  // CHECK-HEAP-NEXT:   store void ()* {{%.*}}, void ()** [[T5]], align 8
+  // CHECK-NOHEAP-NEXT: store void ()* [[T2]], void ()** [[T5]], align 8
+  // CHECK-NEXT:        [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
+  // CHECK-NEXT:        call void @llvm.objc.release(i8* [[T7]])
 
   // Destroy at end of function.
-  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
-  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
-  // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
-  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
-  // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
+  // CHECK-NEXT:        [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
+  // CHECK-NEXT:        call void @_Block_object_dispose(i8* [[T0]], i32 8)
+  // CHECK-NEXT:        [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
+  // CHECK-NEXT:        [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
+  // CHECK-NEXT:        call void @llvm.objc.release(i8* [[T2]])
   // CHECK: ret void
 }
 
Index: clang/test/CodeGenObjC/arc-block-copy-escape.m
===================================================================
--- clang/test/CodeGenObjC/arc-block-copy-escape.m
+++ clang/test/CodeGenObjC/arc-block-copy-escape.m
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fobjc-arc -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fobjc-arc -fblocks -emit-llvm %s -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK-HEAP %s
+// RUN: %clang_cc1 -fobjc-arc -fblocks -fobjc-avoid-heapify-local-blocks -emit-llvm %s -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NOHEAP %s
+
 
 typedef void (^block_t)(void);
 void use_block(block_t);
@@ -8,17 +10,19 @@
 
 void test0(int i) {
   block_t block = ^{ use_int(i); };
-  // CHECK-LABEL:   define {{.*}}void @test0(
-  // CHECK-NOT: @llvm.objc.retainBlock(
-  // CHECK:     ret void
+  // CHECK-LABEL:      define {{.*}}void @test0(
+  // CHECK-HEAP:       call {{.*}}i8* @llvm.objc.retainBlock(i8* {{%.*}}) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape
+  // CHECK-NOHEAP-NOT: @llvm.objc.retainBlock(
+  // CHECK:            ret void
 }
 
 void test1(int i) {
   id block = ^{ use_int(i); };
   // CHECK-LABEL:   define {{.*}}void @test1(
-  // CHECK:     call {{.*}}i8* @llvm.objc.retainBlock(i8* {{%.*}}) [[NUW:#[0-9]+]]
-  // CHECK-NOT: !clang.arc.copy_on_escape
-  // CHECK:     ret void
+  // CHECK-HEAP:    call {{.*}}i8* @llvm.objc.retainBlock(i8* {{%.*}}) [[NUW]]
+  // CHECK-NOHEAP:  call {{.*}}i8* @llvm.objc.retainBlock(i8*  {{%.*}}) [[NUW:#[0-9]+]]
+  // CHECK-NOT:     !clang.arc.copy_on_escape
+  // CHECK:         ret void
 }
 
 // CHECK: attributes [[NUW]] = { nounwind }
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -3344,7 +3344,8 @@
     TryEmitResult result = visitExpr(e);
     // Avoid the block-retain if this is a block literal that doesn't need to be
     // copied to the heap.
-    if (e->getBlockDecl()->canAvoidCopyToHeap())
+    if (CGF.CGM.getCodeGenOpts().ObjCAvoidHeapifyLocalBlocks &&
+        e->getBlockDecl()->canAvoidCopyToHeap())
       result.setInt(true);
     return result;
   }
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2373,6 +2373,11 @@
   Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Ignore attribute objc_direct so that direct methods can be tested">,
   MarshallingInfoFlag<LangOpts<"ObjCDisableDirectMethodsForTesting">>;
+defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blocks",
+  CodeGenOpts<"ObjCAvoidHeapifyLocalBlocks">, DefaultFalse,
+  PosFlag<SetTrue, [CC1Option], "Try">,
+  NegFlag<SetFalse, [], "Don't try">,
+  BothFlags<[], " to avoid heapifying local blocks">>;
 
 def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
 def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, FlangOption, FC1Option]>,
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -188,6 +188,7 @@
 ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
 /// Replace certain message sends with calls to ObjC runtime entrypoints
 CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
+CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0)
 
 VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
 VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to