ahatanak updated this revision to Diff 82421.
ahatanak added a comment.

When compiling for C, insert lifetime.start at the beginning of the current 
lexical scope, rather than moving it retroactively when a goto jumps backwards 
over the variable declaration.

Also, insert lifetime.start at a more precise location, rather than always 
inserting it at the beginning of a basic block. This enables keeping the live 
ranges disjoint in some cases. For example, in the following code, the live 
ranges of a and b would overlap if the lifetime.starts were moved to the 
beginning of the basic block, but would be disjoint if moved to the beginning 
of their lexical scopes:

void foo1() {

  {
    int a[5];
    foo2(a);
  }
  {
    int b[5];
    foo2(b);
  }

}


https://reviews.llvm.org/D27680

Files:
  lib/CodeGen/CGDecl.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGen/cleanup-destslot-simple.c
  test/CodeGen/lifetime2.c
  test/CodeGenObjC/arc-blocks.m
  test/CodeGenObjC/arc-bridged-cast.m
  test/CodeGenObjC/arc-precise-lifetime.m
  test/CodeGenObjC/arc-ternary-op.m
  test/CodeGenObjC/arc.m

Index: test/CodeGenObjC/arc.m
===================================================================
--- test/CodeGenObjC/arc.m
+++ test/CodeGenObjC/arc.m
@@ -46,10 +46,10 @@
 id test1(id x) {
   // CHECK:      [[X:%.*]] = alloca i8*
   // CHECK-NEXT: [[Y:%.*]] = alloca i8*
-  // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
-  // CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
   // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+  // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+  // CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
   // CHECK-NEXT: store i8* null, i8** [[Y]]
   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
   // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]])
@@ -308,11 +308,11 @@
   // CHECK-LABEL:      define void @test10()
   // CHECK:      [[X:%.*]] = alloca [[TEST10:%.*]]*, align
   // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align
+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
   // CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST10]]** [[X]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
   // CHECK-NEXT: store [[TEST10]]* null, [[TEST10]]** [[X]]
-  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
   // CHECK-NEXT: load [[TEST10]]*, [[TEST10]]** [[X]], align
   // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}
   // CHECK-NEXT: bitcast
@@ -346,9 +346,9 @@
   // CHECK-LABEL:      define void @test11(
   // CHECK:      [[F:%.*]] = alloca i8* ()*, align
   // CHECK-NEXT: [[X:%.*]] = alloca i8*, align
-  // CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align
   // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
+  // CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align
   // CHECK-NEXT: [[T0:%.*]] = load i8* ()*, i8* ()** [[F]], align
   // CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]()
   // CHECK-NEXT: store i8* [[T1]], i8** [[X]], align
@@ -366,10 +366,12 @@
   // CHECK-LABEL:      define void @test12()
   // CHECK:      [[X:%.*]] = alloca i8*, align
   // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align
-
-  __weak id x = test12_helper();
+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
   // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
+
+  __weak id x = test12_helper();
   // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper()
   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T1]])
@@ -382,8 +384,6 @@
   // CHECK-NEXT: call void @objc_release(i8* [[T1]])
 
   id y = x;
-  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]])
   // CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align
 
@@ -897,11 +897,11 @@
   // CHECK-NEXT: [[TEMP1:%.*]] = alloca [[A_T]]*
   // CHECK-NEXT: [[TEMP2:%.*]] = alloca [[A_T]]*
   // CHECK-NEXT: bitcast
+  // CHECK-NEXT: call void @llvm.lifetime.start
+  // CHECK-NEXT: bitcast
   // CHECK-NEXT: objc_retain
   // CHECK-NEXT: bitcast
   // CHECK-NEXT: store
-  // CHECK-NEXT: bitcast
-  // CHECK-NEXT: call void @llvm.lifetime.start
   // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[A]]
 
   // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]]
@@ -1338,6 +1338,8 @@
 void test61(void) {
   // CHECK-LABEL:    define void @test61()
   // CHECK:      [[Y:%.*]] = alloca i8*, align 8
+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
 
   extern id test61_make(void);
 
@@ -1349,8 +1351,6 @@
   // CHECK-NEXT: call void @objc_release(i8* [[T1]])
   [test61_make() performSelector: @selector(test61_void)];
 
-  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make()
   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
   // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
Index: test/CodeGenObjC/arc-ternary-op.m
===================================================================
--- test/CodeGenObjC/arc-ternary-op.m
+++ test/CodeGenObjC/arc-ternary-op.m
@@ -8,10 +8,10 @@
   // CHECK-NEXT: [[X:%.*]] = alloca i8*,
   // CHECK-NEXT: [[RELVAL:%.*]] = alloca i8*
   // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1
-  // CHECK-NEXT: zext
-  // CHECK-NEXT: store
   // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
+  // CHECK-NEXT: zext
+  // CHECK-NEXT: store
   // CHECK-NEXT: [[T0:%.*]] = load i8, i8* [[COND]]
   // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
   // CHECK-NEXT: store i1 false, i1* [[RELCOND]]
@@ -52,12 +52,12 @@
   // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8*
   // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*
   // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
-  // CHECK-NEXT: store i32
+  // CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*
+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]])
   // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
+  // CHECK-NEXT: store i32
   // CHECK-NEXT: store i8* null, i8** [[STRONG]]
-  // CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]])
   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
 
   // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
Index: test/CodeGenObjC/arc-precise-lifetime.m
===================================================================
--- test/CodeGenObjC/arc-precise-lifetime.m
+++ test/CodeGenObjC/arc-precise-lifetime.m
@@ -39,15 +39,15 @@
 void test1a_message(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[C:%.*]] = alloca i8*, align 8
+  // CHECK:      [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -73,15 +73,15 @@
 void test1a_property(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[C:%.*]] = alloca i8*, align 8
+  // CHECK:      [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -107,15 +107,15 @@
 void test1b_message(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[C:%.*]] = alloca i8*, align 8
+  // CHECK:      [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
@@ -138,15 +138,15 @@
 void test1b_property(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[C:%.*]] = alloca i8*, align 8
+  // CHECK:      [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
@@ -169,15 +169,15 @@
 void test1c_message(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
+  // CHECK:      [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -202,15 +202,15 @@
 void test1c_property(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
+  // CHECK:      [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -235,15 +235,15 @@
 void test1d_message(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
+  // CHECK:      [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
   // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
@@ -265,15 +265,15 @@
 void test1d_property(void) {
   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
+  // CHECK:      [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
   // CHECK-NEXT: store [[TEST1]]* [[T3]]
-  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
   // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
   // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
Index: test/CodeGenObjC/arc-bridged-cast.m
===================================================================
--- test/CodeGenObjC/arc-bridged-cast.m
+++ test/CodeGenObjC/arc-bridged-cast.m
@@ -78,10 +78,10 @@
 
 // CHECK-LABEL: define void @bridge_of_cf
 void bridge_of_cf(int *i) {
+  // CHECK: call void @llvm.lifetime.start
   // CHECK: store i32 7
   *i = 7;
-  // CHECK: call void @llvm.lifetime.start
-  // CHECK-NEXT: call i8* @CreateSomething()
+  // CHECK: call i8* @CreateSomething()
   CFTypeRef cf1 = (__bridge CFTypeRef)CreateSomething();
   // CHECK-NOT: retain
   // CHECK: store i32 11
Index: test/CodeGenObjC/arc-blocks.m
===================================================================
--- test/CodeGenObjC/arc-blocks.m
+++ test/CodeGenObjC/arc-blocks.m
@@ -70,12 +70,12 @@
   // CHECK:      [[SINK:%.*]] = alloca void (i8**)*
   // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
   // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
+  // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
   // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
   // CHECK-NEXT: call i8* @objc_retain(
   // CHECK-NEXT: bitcast i8*
   // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
-  // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
-  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
   // CHECK-NEXT: store i8* null, i8** [[STRONG]]
 
   // CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
@@ -503,10 +503,10 @@
   // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
   // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
   // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
-  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
-  // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
   // CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*
   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]])
+  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+  // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
   // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
   // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
Index: test/CodeGen/lifetime2.c
===================================================================
--- test/CodeGen/lifetime2.c
+++ test/CodeGen/lifetime2.c
@@ -1,5 +1,5 @@
-// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefixes=CHECK,O2
-// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0
+// RUN: %clang_cc1 -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s -check-prefixes=CHECK,O2
+// RUN: %clang_cc1 -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0
 
 extern int bar(char *A, int n);
 
@@ -19,11 +19,11 @@
 
 // CHECK-LABEL: @no_goto_bypass
 void no_goto_bypass() {
+  // O2: @llvm.lifetime.start(i64 5
   // O2: @llvm.lifetime.start(i64 1
   char x;
 l1:
   bar(&x, 1);
-  // O2: @llvm.lifetime.start(i64 5
   // O2: @llvm.lifetime.end(i64 5
   char y[5];
   bar(y, 5);
@@ -46,6 +46,7 @@
 
 // CHECK-LABEL: @no_switch_bypass
 void no_switch_bypass(int n) {
+  // O2: @llvm.lifetime.start(i64 5
   switch (n) {
   case 1: {
     // O2: @llvm.lifetime.start(i64 1
@@ -56,7 +57,6 @@
   }
   case 2:
     n = n;
-    // O2: @llvm.lifetime.start(i64 5
     // O2: @llvm.lifetime.end(i64 5
     char y[5];
     bar(y, 5);
@@ -89,3 +89,58 @@
 L:
   bar(&x, 1);
 }
+
+// O2-LABEL: define i32 @move_lifetime_start
+// O2: %i = alloca i32, align 4
+// O2: %[[BITCAST:[0-9]+]] = bitcast i32* %i to i8*
+// O2: call void @llvm.lifetime.start(i64 4, i8* %[[BITCAST]])
+// O2: br label %[[DESTLABEL:[a-z0-9]+]]
+// O2: [[DESTLABEL]]:
+// O2: switch i32 %{{.*}}, label %{{.*}} [
+// O2-NEXT: i32 2, label %[[DESTLABEL]]
+
+extern void foo2(int p);
+
+int move_lifetime_start(int a) {
+  int *p = 0;
+label1:
+  if (p) {
+    foo2(*p);
+    return 0;
+  }
+
+  int i = 999;
+  if (a != 2) {
+    p = &i;
+    goto label1;
+  }
+  return -1;
+}
+
+// O2-LABEL: define i32 @dont_move_lifetime_start
+// O2: %i = alloca i32, align 4
+// O2: br label %[[DESTLABEL:[a-z0-9]+]]
+// O2: [[DESTLABEL]]:
+// O2: %[[BITCAST:[0-9]+]] = bitcast i32* %i to i8*
+// O2: call void @llvm.lifetime.start(i64 4, i8* %[[BITCAST]])
+// O2: switch i32 %{{.*}}, label %{{.*}} [
+// O2-NEXT: i32 0, label %{{.*}}
+// O2-NEXT: i32 2, label %[[DESTLABEL]]
+
+int dont_move_lifetime_start(int a) {
+  int *p = 0;
+label1:
+  {
+    if (p) {
+      foo2(*p);
+      return 0;
+    }
+
+    int i = 999;
+    if (a != 2) {
+      p = &i;
+      goto label1;
+    }
+  }
+  return -1;
+}
Index: test/CodeGen/cleanup-destslot-simple.c
===================================================================
--- test/CodeGen/cleanup-destslot-simple.c
+++ test/CodeGen/cleanup-destslot-simple.c
@@ -13,8 +13,8 @@
   return *p;
 // CHECK: [[X:%.*]] = alloca i32
 // CHECK: [[P:%.*]] = alloca i32*
-// LIFETIME: call void @llvm.lifetime.start(i64 4, i8* nonnull %{{.*}}){{( #[0-9]+)?}}, !dbg
 // LIFETIME: call void @llvm.lifetime.start(i64 8, i8* nonnull %{{.*}}){{( #[0-9]+)?}}, !dbg
+// LIFETIME: call void @llvm.lifetime.start(i64 4, i8* nonnull %{{.*}}){{( #[0-9]+)?}}, !dbg
 // CHECK-NOT: store i32 %{{.*}}, i32* %cleanup.dest.slot
 // LIFETIME: call void @llvm.lifetime.end(i64 8, {{.*}}){{( #[0-9]+)?}}, !dbg
 // LIFETIME: call void @llvm.lifetime.end(i64 4, {{.*}}){{( #[0-9]+)?}}, !dbg
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -579,6 +579,15 @@
     SmallVector<const LabelDecl*, 4> Labels;
     LexicalScope *ParentScope;
 
+    // Basic block of this lexical scope.
+    llvm::BasicBlock *BB;
+
+    // Insert point of this lexical scope. If not null, lifetime.start will be
+    // inserted after this instruction (or before this instruction if it's a
+    // terminator). If null, lifetime.start will be inserted at the beginning of
+    // the lexical scope's basic block.
+    llvm::Instruction *InsertPt;
+
     LexicalScope(const LexicalScope &) = delete;
     void operator=(const LexicalScope &) = delete;
 
@@ -589,13 +598,27 @@
       CGF.CurLexicalScope = this;
       if (CGDebugInfo *DI = CGF.getDebugInfo())
         DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin());
+      CGF.EnsureInsertPoint();
+      BB = CGF.Builder.GetInsertBlock();
+      if (!BB->empty())
+        InsertPt = &*std::prev(CGF.Builder.GetInsertPoint());
+      else
+        InsertPt = nullptr;
     }
 
     void addLabel(const LabelDecl *label) {
       assert(PerformCleanup && "adding label to dead scope?");
       Labels.push_back(label);
     }
 
+    llvm::BasicBlock *getBasicBlock() const {
+      return BB;
+    }
+
+    llvm::Instruction *getInsertPoint() const {
+      return InsertPt;
+    }
+
     /// \brief Exit this cleanup scope, emitting any accumulated
     /// cleanups.
     ~LexicalScope() {
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -898,11 +898,41 @@
   if (!ShouldEmitLifetimeMarkers)
     return nullptr;
 
+  CGBuilderTy::InsertPoint SavedIP;
+
+  // If compiling for C, insert the lifetime.start marker at the beginning of
+  // the current lexical scope.
+  if (!getLangOpts().CPlusPlus) {
+    SavedIP = Builder.saveIP();
+    // If CurLexicalScope is null, insert it after the alloca insert point.
+    if (!CurLexicalScope) {
+      auto I = AllocaInsertPt->getIterator();
+      Builder.SetInsertPoint(I->getParent(), std::next(I));
+    } else {
+      llvm::BasicBlock *BB = CurLexicalScope->getBasicBlock();
+      llvm::Instruction *InsertPt = CurLexicalScope->getInsertPoint();
+
+      // If InsertPt is null, insert it at the beginning of BB.
+      if (!InsertPt)
+        Builder.SetInsertPoint(BB, BB->begin());
+      // If InsertPt is a terminator, insert it before InsertPt.
+      else if (InsertPt->isTerminator())
+        Builder.SetInsertPoint(InsertPt);
+      // Otherwise, insert it after InsertPt.
+      else
+        Builder.SetInsertPoint(BB, std::next(InsertPt->getIterator()));
+    }
+  }
+
   llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
   Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
   llvm::CallInst *C =
       Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
   C->setDoesNotThrow();
+
+  if (SavedIP.isSet())
+    Builder.SetInsertPoint(SavedIP.getBlock());
+
   return SizeV;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to