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; } Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -579,6 +579,15 @@ SmallVector 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,6 +598,12 @@ 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) { @@ -596,6 +611,14 @@ 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: 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: 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/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/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-precise-lifetime.m =================================================================== --- test/CodeGenObjC/arc-precise-lifetime.m +++ test/CodeGenObjC/arc-precise-lifetime.m @@ -39,6 +39,8 @@ 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() @@ -46,8 +48,6 @@ // 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,6 +73,8 @@ 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() @@ -80,8 +82,6 @@ // 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,6 +107,8 @@ 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() @@ -114,8 +116,6 @@ // 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,6 +138,8 @@ 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() @@ -145,8 +147,6 @@ // 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,6 +169,8 @@ 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() @@ -176,8 +178,6 @@ // 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,6 +202,8 @@ 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() @@ -209,8 +211,6 @@ // 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,6 +235,8 @@ 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() @@ -242,8 +244,6 @@ // 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,6 +265,8 @@ 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() @@ -272,8 +274,6 @@ // 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-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.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_