brintos

brintos / llvm-project-archived public Read only

0
0
Text · 54.8 KiB · 2d860c1 Raw
1405 lines · plain
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s2// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s3 4// Check both native/non-native arc platforms. Here we check that they treat5// nonlazybind differently.6// RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s7// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s8 9// ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(ptr, ptr)10// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retain(ptr returned)11// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autoreleaseReturnValue(ptr returned)12// ARC-ALIEN: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]]13// ARC-ALIEN: declare extern_weak void @llvm.objc.release(ptr)14// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)15// ARC-ALIEN: declare extern_weak ptr @llvm.objc.initWeak(ptr, ptr)16// ARC-ALIEN: declare extern_weak ptr @llvm.objc.storeWeak(ptr, ptr)17// ARC-ALIEN: declare extern_weak ptr @llvm.objc.loadWeakRetained(ptr)18// ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(ptr)19// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autorelease(ptr returned)20// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutorelease(ptr returned)21 22// ARC-NATIVE: declare void @llvm.objc.storeStrong(ptr, ptr)23// ARC-NATIVE: declare ptr @llvm.objc.retain(ptr returned)24// ARC-NATIVE: declare ptr @llvm.objc.autoreleaseReturnValue(ptr returned)25// ARC-NATIVE: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]]26// ARC-NATIVE: declare void @llvm.objc.release(ptr)27// ARC-NATIVE: declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)28// ARC-NATIVE: declare ptr @llvm.objc.initWeak(ptr, ptr)29// ARC-NATIVE: declare ptr @llvm.objc.storeWeak(ptr, ptr)30// ARC-NATIVE: declare ptr @llvm.objc.loadWeakRetained(ptr)31// ARC-NATIVE: declare void @llvm.objc.destroyWeak(ptr)32// ARC-NATIVE: declare ptr @llvm.objc.autorelease(ptr returned)33// ARC-NATIVE: declare ptr @llvm.objc.retainAutorelease(ptr returned)34 35// CHECK-LABEL: define{{.*}} void @test036void test0(id x) {37  // CHECK:      [[X:%.*]] = alloca ptr38  // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{.*}})39  // CHECK-NEXT: store ptr [[PARM]], ptr [[X]]40  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]41  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]])42  // CHECK-NEXT: ret void43}44 45// CHECK-LABEL: define{{.*}} ptr @test1(ptr46id test1(id x) {47  // CHECK:      [[X:%.*]] = alloca ptr48  // CHECK-NEXT: [[Y:%.*]] = alloca ptr49  // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}})50  // CHECK-NEXT: store ptr [[PARM]], ptr [[X]]51  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])52  // CHECK-NEXT: store ptr null, ptr [[Y]]53  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]54  // CHECK-NEXT: [[RET:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])55  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]56  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])57  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[Y]])58  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]59  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])60  // CHECK-NEXT: [[T1:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[RET]])61  // CHECK-NEXT: ret ptr [[T1]]62  id y;63  return y;64}65 66@interface Test267+ (void) class_method;68- (void) inst_method;69@end70@implementation Test271 72// The self pointer of a class method is not retained.73// CHECK: define internal void @"\01+[Test2 class_method]"74// CHECK:      alloca75// CHECK-NEXT: alloca76// CHECK-NEXT: store77// CHECK-NEXT: store78// CHECK-NEXT: ret void79+ (void) class_method {}80 81// The self pointer of an instance method is not retained.82// CHECK: define internal void @"\01-[Test2 inst_method]"83// CHECK:      alloca84// CHECK-NEXT: alloca85// CHECK-NEXT: store86// CHECK-NEXT: store87// CHECK-NEXT: ret void88- (void) inst_method {}89@end90 91@interface Test392+ (id) alloc;93- (id) initWith: (int) x;94- (id) copy;95@end96 97// CHECK-LABEL: define{{.*}} void @test3_unelided()98void test3_unelided(void) {99  extern void test3_helper(void);100 101  // CHECK:      [[X:%.*]] = alloca ptr102  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])103  // CHECK-NEXT: store ptr null, ptr [[X]], align104  Test3 *x;105 106  // Call to +alloc.107  // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_108  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_109  // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend110  // CHECK-NEXT: call void @llvm.objc.release(ptr111  [Test3 alloc];112 113  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]114  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_115  // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]],116  // CHECK-NEXT: call void @llvm.objc.release(ptr [[COPY]]) [[NUW:#[0-9]+]]117  [x copy];118 119  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]120  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]121  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])122  // CHECK-NEXT: ret void123}124 125// CHECK-LABEL: define{{.*}} void @test3()126void test3(void) {127  // CHECK:      [[X:%.*]] = alloca ptr128  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])129 130  id x = [[Test3 alloc] initWith: 5];131 132  // Call to +alloc.133  // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_134  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_135  // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend136 137  // Call to -initWith: with elided retain of consumed argument.138  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_139  // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr140  // Assignment for initialization, retention elided.141  // CHECK-NEXT: store ptr [[INIT]], ptr [[X]]142 143  // Call to -copy.144  // CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[X]]145  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_146  // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[V]],147 148  // Assignment to x.149  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]150  // CHECK-NEXT: store ptr [[COPY]], ptr [[X]]151  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]152 153  x = [x copy];154 155  // Cleanup for x.156  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]157  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]158  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])159  // CHECK-NEXT: ret void160}161 162// CHECK-LABEL: define{{.*}} ptr @test4()163id test4(void) {164  // Call to +alloc.165  // CHECK:      load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_166  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_167  // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend168 169  // Call to -initWith: with elided retain of consumed argument.170  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_171  // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr noundef [[ALLOC]],172 173  // Initialization of return value, occurring within full-expression.174  // Retain/release elided.175  // CHECK-NEXT: [[RET:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[INIT]])176 177  // CHECK-NEXT: ret ptr [[RET]]178 179  return [[Test3 alloc] initWith: 6];180}181 182@interface Test5 {183@public184  id var;185}186@end187 188// CHECK-LABEL: define{{.*}} void @test5189void test5(Test5 *x, id y) {190  // Prologue.191  // CHECK:      [[X:%.*]] = alloca ptr,192  // CHECK-NEXT: [[Y:%.*]] = alloca ptr193  // CHECK-NEXT: call ptr @llvm.objc.retain194  // CHECK-NEXT: store ptr {{%.*}}, ptr [[X]]195  // CHECK-NEXT: call ptr @llvm.objc.retain196  // CHECK-NEXT: store197 198  // CHECK-NEXT: load ptr, ptr [[X]]199  // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var"200  // CHECK-NEXT: [[VAR:%.*]] = getelementptr201  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]]202  // CHECK-NEXT: store ptr null, ptr [[VAR]]203  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]204  x->var = 0;205 206  // CHECK-NEXT: [[YVAL:%.*]] = load ptr, ptr [[Y]]207  // CHECK-NEXT: load ptr, ptr [[X]]208  // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var"209  // CHECK-NEXT: [[VAR:%.*]] = getelementptr210  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr [[YVAL]]) [[NUW]]211  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]]212  // CHECK-NEXT: store ptr [[T0]], ptr [[VAR]]213  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]214  x->var = y;215 216  // Epilogue.217  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[Y]]218  // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]219  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]220  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]221  // CHECK-NEXT: ret void222}223 224id test6_helper(void) __attribute__((ns_returns_retained));225// CHECK-LABEL: define{{.*}} void @test6()226void test6(void) {227  // CHECK:      [[X:%.*]] = alloca ptr228  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])229  // CHECK-NEXT: [[CALL:%.*]] = call ptr @test6_helper()230  // CHECK-NEXT: store ptr [[CALL]], ptr [[X]]231  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]232  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release233  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])234  // CHECK-NEXT: ret void235  id x = test6_helper();236}237 238void test7_helper(id __attribute__((ns_consumed)));239// CHECK-LABEL: define{{.*}} void @test7()240void test7(void) {241  // CHECK:      [[X:%.*]] = alloca ptr242  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])243  // CHECK-NEXT: store ptr null, ptr [[X]]244  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]245  // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) [[NUW]]246  // CHECK-NEXT: call void @test7_helper(ptr noundef [[T1]])247  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]248  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release249  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])250  // CHECK-NEXT: ret void251  id x;252  test7_helper(x);253}254 255id test8_helper(void) __attribute__((ns_returns_retained));256void test8(void) {257  __unsafe_unretained id x = test8_helper();258  // CHECK:      [[X:%.*]] = alloca ptr259  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])260  // CHECK-NEXT: [[T0:%.*]] = call ptr @test8_helper()261  // CHECK-NEXT: store ptr [[T0]], ptr [[X]]262  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release263  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])264  // CHECK-NEXT: ret void265}266 267@interface Test10268@property (retain) Test10 *me;269@end270void test10(void) {271  Test10 *x;272  id y = x.me.me;273 274  // CHECK-LABEL:      define{{.*}} void @test10()275  // CHECK:      [[X:%.*]] = alloca ptr, align276  // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align277  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])278  // CHECK-NEXT: store ptr null, ptr [[X]]279  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])280  // CHECK-NEXT: load ptr, ptr [[X]], align281  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}282  // CHECK-NEXT: [[V:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]283  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[V]])284  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}285  // CHECK-NEXT: [[T3:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]286  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]])287  // CHECK-NEXT: store ptr [[T3]], ptr [[Y]]288  // CHECK-NEXT: call void @llvm.objc.release(ptr [[V]])289  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]290  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])291  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[Y]])292  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]293  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])294  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])295  // CHECK-NEXT: ret void296}297 298void test11(id (*f)(void) __attribute__((ns_returns_retained))) {299  // CHECK-LABEL:      define{{.*}} void @test11(300  // CHECK:      [[F:%.*]] = alloca ptr, align301  // CHECK-NEXT: [[X:%.*]] = alloca ptr, align302  // CHECK-NEXT: store ptr {{%.*}}, ptr [[F]], align303  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])304  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[F]], align305  // CHECK-NEXT: [[T1:%.*]] = call ptr [[T0]]()306  // CHECK-NEXT: store ptr [[T1]], ptr [[X]], align307  // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]308  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) [[NUW]], !clang.imprecise_release309  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])310  // CHECK-NEXT: ret void311  id x = f();312}313 314void test12(void) {315  extern id test12_helper(void);316 317  // CHECK-LABEL:      define{{.*}} void @test12()318  // CHECK:      [[X:%.*]] = alloca ptr, align319  // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align320 321  __weak id x = test12_helper();322  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])323  // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]324  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])325  // CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T1]])326  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])327 328  x = test12_helper();329  // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]330  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])331  // CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T1]])332  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])333 334  id y = x;335  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])336  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[X]])337  // CHECK-NEXT: store ptr [[T2]], ptr [[Y]], align338 339  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[Y]]340  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) [[NUW]], !clang.imprecise_release341  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[Y]])342  // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])343  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])344  // CHECK: ret void345}346 347// Indirect consuming calls.348void test13(void) {349  // CHECK-LABEL:      define{{.*}} void @test13()350  // CHECK:      [[X:%.*]] = alloca ptr, align351  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])352  // CHECK-NEXT: store ptr null, ptr [[X]], align353  id x;354 355  typedef void fnty(id __attribute__((ns_consumed)));356  extern fnty *test13_func;357  // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr @test13_func, align358  // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align359  // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]]360  // CHECK-NEXT: call void [[FN]](ptr noundef [[X_TMP]])361  test13_func(x);362 363  extern fnty ^test13_block;364  // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr @test13_block, align365  // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds nuw [[BLOCKTY:%.*]], ptr [[TMP]], i32 0, i32 3366  // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align367  // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]]368  // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load ptr, ptr [[BLOCK_FN_PTR]]369  // CHECK-NEXT: call void [[BLOCK_FN_TMP]](ptr noundef [[TMP]], ptr noundef [[X_TMP]])370  test13_block(x);371 372  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]373  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]374  // CHECK-NEXT: void @llvm.lifetime.end.p0(ptr [[X]])375  // CHECK-NEXT: ret void376}377 378@interface Test16_super @end379@interface Test16 : Test16_super {380  id z;381}382@property (assign) int x;383@property (retain) id y;384- (void) dealloc;385@end386@implementation Test16387@synthesize x;388@synthesize y;389- (void) dealloc {390  // CHECK:    define internal void @"\01-[Test16 dealloc]"(391  // CHECK:      [[SELF:%.*]] = alloca ptr, align392  // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align393  // CHECK-NEXT: alloca394  // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align395  // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]396  // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]]397 398  // Call super.399  // CHECK-NEXT: [[T0:%.*]] = getelementptr400  // CHECK-NEXT: store ptr [[BASE]], ptr [[T0]]401  // CHECK-NEXT: load ptr, ptr @"OBJC_CLASSLIST_SUP_REFS_$_402  // CHECK-NEXT: getelementptr403  // CHECK-NEXT: store404  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_405  // CHECK-NEXT: call void @objc_msgSendSuper2(406  // CHECK-NEXT: ret void407}408 409// .cxx_destruct410  // CHECK:    define internal void @"\01-[Test16 .cxx_destruct]"(411  // CHECK:      [[SELF:%.*]] = alloca ptr, align412  // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align413  // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align414  // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]415  // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]]416 417  // Destroy y.418  // CHECK-NEXT: [[Y_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.y"419  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Y_OFF]]420  // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]]421 422  // Destroy z.423  // CHECK-NEXT: [[Z_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.z"424  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Z_OFF]]425  // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]]426 427  // CHECK-NEXT: ret void428 429@end430 431// This shouldn't crash.432@interface Test17A433@property (assign) int x;434@end435@interface Test17B : Test17A436@end437@implementation Test17B438- (int) x { return super.x + 1; }439@end440 441void test19(void) {442  // CHECK-LABEL: define{{.*}} void @test19()443  // CHECK:      [[X:%.*]] = alloca [5 x ptr], align 16444  // CHECK: call void @llvm.lifetime.start445  // CHECK: call void @llvm.memset.p0.i64(ptr align 16 [[X]], i8 0, i64 40, i1 false)446  id x[5];447 448  extern id test19_helper(void);449  x[2] = test19_helper();450 451  // CHECK-NEXT: [[T1:%.*]] = call ptr @test19_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]452  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])453  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i64 0, i64 2454  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SLOT]]455  // CHECK-NEXT: store ptr [[T1]], ptr [[SLOT]]456  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]457 458  // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i32 0, i32 0459  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 5460  // CHECK-NEXT: br label461 462  // CHECK:      [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]463  // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1464  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]465  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release466  // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]467  // CHECK-NEXT: br i1 [[EQ]],468 469  // CHECK:      ret void470}471 472void test20(unsigned n) {473  // CHECK-LABEL: define{{.*}} void @test20474  // CHECK:      [[N:%.*]] = alloca i32, align 4475  // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr476  // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8477  // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4478 479  id x[n];480 481  // Capture the VLA size.482  // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4483  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64484 485  // Save the stack pointer.486  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()487  // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]488 489  // Allocate the VLA.490  // CHECK-NEXT: [[VLA:%.*]] = alloca ptr, i64 [[DIM]], align 16491 492  // Store the VLA #elements expression.493  // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8494 495  // Zero-initialize.496  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8497  // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T1]], i1 false)498 499  // Destroy.500  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[VLA]], i64 [[DIM]]501  // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[VLA]], [[END]]502  // CHECK-NEXT: br i1 [[EMPTY]]503 504  // CHECK:      [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]505  // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1506  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]507  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release508  // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[VLA]]509  // CHECK-NEXT: br i1 [[EQ]],510 511  // CHECK:      [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]512  // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])513  // CHECK-NEXT: ret void514}515 516void test21(unsigned n) {517  // CHECK-LABEL: define{{.*}} void @test21518  // CHECK:      [[N:%.*]] = alloca i32, align 4519  // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr520  // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8521  // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4522 523  id x[2][n][3];524 525  // Capture the VLA size.526  // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4527  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64528 529  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()530  // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]531 532 533  // Allocate the VLA.534  // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]535  // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x ptr], i64 [[T0]], align 16536 537  // Store the VLA #elements expression.538  // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8539 540  // Zero-initialize.541  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]542  // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24543  // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T2]], i1 false)544 545  // Destroy.546  // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]547  // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x ptr], ptr [[VLA]], i32 0, i32 0548  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3549  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 [[T1]]550  // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]551  // CHECK-NEXT: br i1 [[EMPTY]]552 553  // CHECK:      [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]554  // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1555  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]556  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release557  // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]558  // CHECK-NEXT: br i1 [[EQ]],559 560  // CHECK:      [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]561  // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])562  // CHECK-NEXT: ret void563}564 565//   Note that we no longer emit .release_ivars flags.566//   Note that we set the flag saying that we need destruction *and*567//   the flag saying that we don't also need construction.568// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390,569@interface Test23 { id x; } @end570@implementation Test23 @end571 572// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130,573@interface Test24 {} @end574@implementation Test24 @end575 576@interface Test26 { id x[4]; } @end577@implementation Test26 @end578// CHECK:    define internal void @"\01-[Test26 .cxx_destruct]"(579// CHECK:      [[SELF:%.*]] = load ptr, ptr580// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0581// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x ptr], ptr [[T1]], i32 0, i32 0582// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 4583// CHECK-NEXT: br label584// CHECK:      [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]585// CHECK-NEXT: [[CUR]] = getelementptr inbounds ptr, ptr [[PAST]], i64 -1586// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[CUR]], ptr null)587// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]588// CHECK-NEXT: br i1 [[ISDONE]],589// CHECK:      ret void590 591// Check that 'init' retains self.592@interface Test27593- (id) init;594@end595@implementation Test27596- (id) init { return self; }597// CHECK:    define internal ptr @"\01-[Test27 init]"598// CHECK:      [[SELF:%.*]] = alloca ptr,599// CHECK-NEXT: [[CMD:%.*]] = alloca ptr,600// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]601// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]602// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]603// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])604// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]605// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])606// CHECK-NEXT: ret ptr [[T2]]607 608@end609 610@interface Test28611@property (copy) id prop;612@end613@implementation Test28614@synthesize prop;615@end616// CHECK:    define internal void @"\01-[Test28 .cxx_destruct]"617// CHECK:      [[SELF:%.*]] = load ptr, ptr618// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0619// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)620// CHECK-NEXT: ret void621 622@interface Test29_super623- (id) initWithAllocator: (id) allocator;624@end625@interface Test29 : Test29_super626- (id) init;627- (id) initWithAllocator: (id) allocator;628@end629@implementation Test29630static id _test29_allocator = 0;631- (id) init {632// CHECK:    define internal ptr @"\01-[Test29 init]"(ptr noundef {{%.*}},633// CHECK:      [[SELF:%.*]] = alloca ptr, align 8634// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8635// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]636// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]637 638// Evaluate arguments.  Note that the send argument is evaluated639// before the zeroing of self.640// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8641// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @_test29_allocator, align 8642 643// Implicit null of 'self', i.e. direct transfer of ownership.644// CHECK-NEXT: store ptr null, ptr [[SELF]]645 646// Actual message send.647// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_648// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]], ptr noundef [[T1]])649 650// Implicit write of result back into 'self'.  This is not supposed to651// be detectable because we're supposed to ban accesses to the old652// self value past the delegate init call.653// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]654 655// Return statement.656// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]657 658// Cleanup.659// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]660// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release661 662// Return.663// CHECK-NEXT: ret ptr [[T1]]664  return [self initWithAllocator: _test29_allocator];665}666- (id) initWithAllocator: (id) allocator {667// CHECK:    define internal ptr @"\01-[Test29 initWithAllocator:]"(668// CHECK:      [[SELF:%.*]] = alloca ptr, align 8669// CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8670// CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca ptr, align 8671// CHECK-NEXT: alloca672// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]673// CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]674// CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}})675// CHECK-NEXT: store ptr [[T0]], ptr [[ALLOCATOR]]676 677// Evaluate arguments.  Note that the send argument is evaluated678// before the zeroing of self.679// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]680// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[ALLOCATOR]], align 8681 682// Implicit null of 'self', i.e. direct transfer of ownership.683// CHECK-NEXT: store ptr null, ptr [[SELF]]684 685// Actual message send.686// CHECK:      [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2687 688// Implicit write of result back into 'self'.  This is not supposed to689// be detectable because we're supposed to ban accesses to the old690// self value past the delegate init call.691// CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]692 693// Assignment.694// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]695// CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[SELF]], align696// CHECK-NEXT: store ptr [[T2]], ptr [[SELF]], align697// CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])698 699// Return statement.700// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]]701// CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]]702 703// Cleanup.704// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[ALLOCATOR]]705// CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) [[NUW]], !clang.imprecise_release706 707// CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[SELF]]708// CHECK-NEXT: call void @llvm.objc.release(ptr [[T6]]) [[NUW]], !clang.imprecise_release709 710// Return.711// CHECK-NEXT: ret ptr [[T4]]712  self = [super initWithAllocator: allocator];713  return self;714}715@end716 717typedef struct Test30_helper Test30_helper;718@interface Test30719- (id) init;720- (Test30_helper*) initHelper;721@end722@implementation Test30 {723char *helper;724}725- (id) init {726// CHECK:    define internal ptr @"\01-[Test30 init]"(ptr noundef {{%.*}},727// CHECK:      [[RET:%.*]] = alloca ptr728// CHECK-NEXT: alloca ptr729// CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]730// CHECK-NEXT: store731 732// Call.733// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]734// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_735// CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])736 737// Assignment.738// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[SELF]]739// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 0740// CHECK-NEXT#: [[T5:%.*]] = load ptr, ptr [[T3]]741// CHECK-NEXT#: [[T6:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]])742// CHECK-NEXT#: call void @llvm.objc.release(ptr [[T5]])743// CHECK-NEXT: store ptr [[CALL]], ptr [[T3]]744 745// Return.746// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]747// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])748 749// Cleanup.750// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]751// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])752 753// Epilogue.754// CHECK-NEXT: ret ptr [[T1]]755  self->helper = [self initHelper];756  return self;757}758- (Test30_helper*) initHelper {759// CHECK:    define internal ptr @"\01-[Test30 initHelper]"(760// CHECK:      alloca761// CHECK-NEXT: alloca762// CHECK-NEXT: store763// CHECK-NEXT: store764// CHECK-NEXT: ret ptr null765  return 0;766}767 768@end769 770__attribute__((ns_returns_retained)) id test32(void) {771// CHECK-LABEL:    define{{.*}} ptr @test32()772// CHECK:      [[T0:%.*]] = call ptr @test32_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]773// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])774// CHECK-NEXT: ret ptr [[T0]]775  extern id test32_helper(void);776  return test32_helper();777}778 779@class Test33_a;780@interface Test33781- (void) give: (Test33_a **) x;782- (void) take: (Test33_a **) x;783- (void) giveStrong: (out __strong Test33_a **) x;784- (void) takeStrong: (inout __strong Test33_a **) x;785- (void) giveOut: (out Test33_a **) x;786@end787void test33(Test33 *ptr) {788  Test33_a *a;789  [ptr give: &a];790  [ptr take: &a];791  [ptr giveStrong: &a];792  [ptr takeStrong: &a];793  [ptr giveOut: &a];794 795  // CHECK:    define{{.*}} void @test33(ptr796  // CHECK:      [[PTR:%.*]] = alloca ptr797  // CHECK-NEXT: [[A:%.*]] = alloca ptr798  // CHECK-NEXT: [[TEMP0:%.*]] = alloca ptr799  // CHECK-NEXT: [[TEMP1:%.*]] = alloca ptr800  // CHECK-NEXT: [[TEMP2:%.*]] = alloca ptr801  // CHECK-NEXT: llvm.objc.retain802  // CHECK-NEXT: store803  // CHECK-NEXT: call void @llvm.lifetime.start804  // CHECK-NEXT: store ptr null, ptr [[A]]805 806  // CHECK-NEXT: load ptr, ptr [[PTR]]807  // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]808  // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP0]]809  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_810  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP0]])811  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP0]]812  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])813  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]814  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]815  // CHECK-NEXT: store ptr [[T2]], ptr [[A]]816  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])817 818  // CHECK-NEXT: load ptr, ptr [[PTR]]819  // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]820  // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP1]]821  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_822  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP1]])823  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP1]]824  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])825  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]826  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]827  // CHECK-NEXT: store ptr [[T2]], ptr [[A]]828  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])829 830  // CHECK-NEXT: load ptr, ptr [[PTR]]831  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_832  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])833 834  // CHECK-NEXT: load ptr, ptr [[PTR]]835  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_836  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])837 838  // 'out'839  // CHECK-NEXT: load ptr, ptr [[PTR]]840  // CHECK-NEXT: store ptr null, ptr [[TEMP2]]841  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_842  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP2]])843  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP2]]844  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])845  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]846  // CHECK-NEXT: store ptr [[T2]], ptr [[A]]847  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])848 849  // CHECK-NEXT: load850  // CHECK-NEXT: llvm.objc.release851  // CHECK-NEXT: call void @llvm.lifetime.end852  // CHECK-NEXT: load853  // CHECK-NEXT: llvm.objc.release854  // CHECK-NEXT: ret void855}856 857 858// CHECK-LABEL: define{{.*}} void @test36859void test36(id x) {860  // CHECK: [[X:%.*]] = alloca ptr861 862  // CHECK: call ptr @llvm.objc.retain863  // CHECK: call ptr @llvm.objc.retain864  // CHECK: call ptr @llvm.objc.retain865  id array[3] = { @"A", x, @"y" };866 867  // CHECK:      [[T0:%.*]] = load ptr, ptr [[X]]868  // CHECK-NEXT: store ptr null, ptr [[X]]869  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])870  x = 0;871 872  // CHECK: br label873  // CHECK: call void @llvm.objc.release874  // CHECK: br i1875 876  // CHECK: call void @llvm.objc.release877  // CHECK-NEXT: ret void878}879 880@class Test37;881void test37(void) {882  extern void test37_helper(id *);883  Test37 *var;884  test37_helper(&var);885 886  // CHECK-LABEL:    define{{.*}} void @test37()887  // CHECK:      [[VAR:%.*]] = alloca ptr,888  // CHECK-NEXT: [[TEMP:%.*]] = alloca ptr889  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VAR]])890  // CHECK-NEXT: store ptr null, ptr [[VAR]]891 892  // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[VAR]]893  // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP]]894  // CHECK-NEXT: call void @test37_helper(ptr noundef [[TEMP]])895  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP]]896  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])897  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]898  // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[VAR]]899  // CHECK-NEXT: store ptr [[T3]], ptr [[VAR]]900  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]])901 902  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[VAR]]903  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])904  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VAR]])905  // CHECK-NEXT: ret void906}907 908@interface Test43 @end909@implementation Test43910- (id) test __attribute__((ns_returns_retained)) {911  extern id test43_produce(void);912  return test43_produce();913  // CHECK:      call ptr @test43_produce(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]914  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(915  // CHECK-NEXT: ret916}917@end918 919@interface Test45920@property (retain) id x;921@end922@implementation Test45923@synthesize x;924@end925// CHECK:    define internal ptr @"\01-[Test45 x]"(926// CHECK:      [[CALL:%.*]] = tail call ptr @objc_getProperty(927// CHECK-NEXT: ret ptr [[CALL]]928 929void test46(__weak id *wp, __weak volatile id *wvp) {930  extern id test46_helper(void);931 932  // TODO: this is sub-optimal, we should retain at the actual call site.933 934  // CHECK:      [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]935  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])936  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8937  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])938  // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])939  // CHECK-NEXT: store ptr [[T4]], ptr940  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])941  id x = *wp = test46_helper();942 943  // CHECK:      [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]944  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])945  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8946  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])947  // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])948  // CHECK-NEXT: store ptr [[T4]], ptr949  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])950  id y = *wvp = test46_helper();951}952 953void test47(void) {954  extern id test47_helper(void);955  id x = x = test47_helper();956 957  // CHECK-LABEL:    define{{.*}} void @test47()958  // CHECK:      [[X:%.*]] = alloca ptr959  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])960  // CHECK-NEXT: store ptr null, ptr [[X]]961  // CHECK-NEXT: [[T0:%.*]] = call ptr @test47_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]962  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])963  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]964  // CHECK-NEXT: store ptr [[T0]], ptr [[X]]965  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])966  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])967  // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]968  // CHECK-NEXT: store ptr [[T2]], ptr [[X]]969  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]])970  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[X]]971  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])972  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])973  // CHECK-NEXT: ret void974}975 976void test48(void) {977  extern id test48_helper(void);978  __weak id x = x = test48_helper();979  // CHECK-LABEL:    define{{.*}} void @test48()980  // CHECK:      [[X:%.*]] = alloca ptr981  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])982  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.initWeak(ptr [[X]], ptr null)983  // CHECK-NEXT: [[T2:%.*]] = call ptr @test48_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]984  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T2]])985  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T2]])986  // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T3]])987  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])988  // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])989  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])990  // CHECK-NEXT: ret void991}992 993void test49(void) {994  extern id test49_helper(void);995  __autoreleasing id x = x = test49_helper();996  // CHECK-LABEL:    define{{.*}} void @test49()997  // CHECK:      [[X:%.*]] = alloca ptr998  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])999  // CHECK-NEXT: store ptr null, ptr [[X]]1000  // CHECK-NEXT: [[T0:%.*]] = call ptr @test49_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1001  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])1002  // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[T0]])1003  // CHECK-NEXT: store ptr [[T1]], ptr [[X]]1004  // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T1]])1005  // CHECK-NEXT: store ptr [[T3]], ptr [[X]]1006  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1007  // CHECK-NEXT: ret void1008}1009 1010id x(void);1011void test50(id y) {1012  ({x();});1013// CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain1014// CHECK: call void @llvm.objc.release1015}1016 1017struct CGPoint {1018  float x;1019  float y;1020};1021typedef struct CGPoint CGPoint;1022 1023@interface Foo1024@property (assign) CGPoint point;1025@end1026 1027@implementation Foo1028@synthesize point;1029@end1030 1031id test52(void) {1032  id test52_helper(int) __attribute__((ns_returns_retained));1033  return ({ int x = 5; test52_helper(x); });1034 1035// CHECK-LABEL:    define{{.*}} ptr @test52()1036// CHECK:      [[X:%.*]] = alloca i321037// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr1038// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1039// CHECK-NEXT: store i32 5, ptr [[X]],1040// CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[X]],1041// CHECK-NEXT: [[T1:%.*]] = call ptr @test52_helper(i32 noundef [[T0]])1042// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]1043// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1044// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[TMPALLOCA]]1045// CHECK-NEXT: [[T3:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T2]])1046// CHECK-NEXT: ret ptr [[T3]]1047}1048 1049void test53(void) {1050  id test53_helper(void);1051  id x = ({ id y = test53_helper(); y; });1052  (void) x;1053// CHECK-LABEL:    define{{.*}} void @test53()1054// CHECK:      [[X:%.*]] = alloca ptr,1055// CHECK-NEXT: [[Y:%.*]] = alloca ptr,1056// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr,1057// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1058// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])1059// CHECK-NEXT: [[T1:%.*]] = call ptr @test53_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1060// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1061// CHECK-NEXT: store ptr [[T1]], ptr [[Y]],1062// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]],1063// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])1064// CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]1065// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[Y]]1066// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])1067// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[Y]])1068// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[TMPALLOCA]]1069// CHECK-NEXT: store ptr [[T3]], ptr [[X]],1070// CHECK-NEXT: load ptr, ptr [[X]],1071// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]1072// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1073// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1074// CHECK-NEXT: ret void1075}1076 1077// CHECK-LABEL: define{{.*}} void @test54(i32 noundef %first, ...)1078void test54(int first, ...) {1079  __builtin_va_list arglist;1080  // CHECK: call void @llvm.va_start1081  __builtin_va_start(arglist, first);1082  // CHECK: call ptr @llvm.objc.retain1083  id obj = __builtin_va_arg(arglist, id);1084  // CHECK: call void @llvm.va_end1085  __builtin_va_end(arglist);1086  // CHECK: call void @llvm.objc.release1087  // CHECK: ret void1088}1089 1090// PR102281091@interface Test55Base @end1092@interface Test55 : Test55Base @end1093@implementation Test55 (Category)1094- (void) dealloc {}1095@end1096// CHECK:   define internal void @"\01-[Test55(Category) dealloc]"(1097// CHECK-NOT: ret1098// CHECK:     call void @objc_msgSendSuper2(1099 1100@protocol Test56Protocol1101+ (id) make __attribute__((ns_returns_retained));1102@end1103@interface Test56<Test56Protocol> @end1104@implementation Test561105// CHECK: define internal ptr @"\01+[Test56 make]"(1106+ (id) make {1107  extern id test56_helper(void);1108  // CHECK:      [[T1:%.*]] = call ptr @test56_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1109  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1110  // CHECK-NEXT: ret ptr [[T1]]1111  return test56_helper();1112}1113@end1114void test56_test(void) {1115  id x = [Test56 make];1116  // CHECK-LABEL: define{{.*}} void @test56_test()1117  // CHECK:      [[X:%.*]] = alloca ptr, align 81118  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])1119  // CHECK:      [[T0:%.*]] = call ptr @objc_msgSend(1120  // CHECK-NEXT: store ptr [[T0]], ptr [[X]]1121  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]1122  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1123  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])1124  // CHECK-NEXT: ret void1125}1126 1127@interface Test571128@property (nonatomic, strong) id strong;1129@property (nonatomic, weak) id weak;1130@property (nonatomic, unsafe_unretained) id unsafe;1131@end1132@implementation Test571133@synthesize strong, weak, unsafe;1134@end1135// CHECK: define internal ptr @"\01-[Test57 strong]"(1136// CHECK:      [[T0:%.*]] = load ptr, ptr {{%.*}}1137// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 01138// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]1139// CHECK-NEXT: ret ptr [[T5]]1140 1141// CHECK: define internal ptr @"\01-[Test57 weak]"(1142// CHECK:      [[T0:%.*]] = load ptr, ptr {{%.*}}1143// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 81144// CHECK-NEXT: [[T5:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T3]])1145// CHECK-NEXT: [[T6:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T5]])1146// CHECK-NEXT: ret ptr [[T6]]1147 1148// CHECK: define internal ptr @"\01-[Test57 unsafe]"(1149// CHECK:      [[T0:%.*]] = load ptr, ptr {{%.*}}1150// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 161151// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]1152// CHECK-NEXT: ret ptr [[T5]]1153 1154void test59(void) {1155  extern id test59_getlock(void);1156  extern void test59_body(void);1157  @synchronized (test59_getlock()) {1158    test59_body();1159  }1160 1161  // CHECK-LABEL:    define{{.*}} void @test59()1162  // CHECK:      [[T1:%.*]] = call ptr @test59_getlock(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1163  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1164  // CHECK-NEXT: call i32 @objc_sync_enter(ptr [[T1]])1165  // CHECK-NEXT: call void @test59_body()1166  // CHECK-NEXT: call i32 @objc_sync_exit(ptr [[T1]])1167  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1168  // CHECK-NEXT: ret void1169}1170 1171// Verify that we don't try to reclaim the result of performSelector.1172@interface Test611173- (id) performSelector: (SEL) selector;1174- (void) test61_void;1175- (id) test61_id;1176@end1177void test61(void) {1178  // CHECK-LABEL:    define{{.*}} void @test61()1179  // CHECK:      [[Y:%.*]] = alloca ptr, align 81180 1181  extern id test61_make(void);1182 1183  // CHECK-NEXT: [[T0:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1184  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])1185  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1186  // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1187  // CHECK-NEXT: [[T4:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]])1188  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1189  [test61_make() performSelector: @selector(test61_void)];1190 1191  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[Y]])1192  // CHECK-NEXT: [[T1:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1193  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1194  // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1195  // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_1196  // CHECK-NEXT: [[T5:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]]){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1197  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T5]])1198  // CHECK-NEXT: store ptr [[T5]], ptr [[Y]]1199  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])1200  id y = [test61_make() performSelector: @selector(test61_id)];1201 1202  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]1203  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1204  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[Y]])1205  // CHECK-NEXT: ret void1206}1207 1208void test62(void) {1209  // CHECK-LABEL:    define{{.*}} void @test62()1210  // CHECK:      [[I:%.*]] = alloca i32, align 41211  // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca ptr1212  // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i11213  extern id test62_make(void);1214  extern void test62_body(void);1215 1216  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[I]])1217  // CHECK-NEXT: store i32 0, ptr [[I]], align 41218  // CHECK-NEXT: br label1219 1220  // CHECK:      [[T0:%.*]] = load i32, ptr [[I]], align 41221  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 201222  // CHECK-NEXT: br i1 [[T1]],1223 1224  for (unsigned i = 0; i != 20; ++i) {1225    // CHECK:      [[T0:%.*]] = load i32, ptr [[I]], align 41226    // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 01227    // CHECK-NEXT: store i1 false, ptr [[CLEANUP_REQUIRED]]1228    // CHECK-NEXT: br i1 [[T1]],1229    // CHECK:      [[T1:%.*]] = call ptr @test62_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1230    // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1231    // CHECK-NEXT: store ptr [[T1]], ptr [[CLEANUP_VALUE]]1232    // CHECK-NEXT: store i1 true, ptr [[CLEANUP_REQUIRED]]1233    // CHECK-NEXT: [[T2:%.*]] = icmp ne ptr [[T1]], null1234    // CHECK-NEXT: br label1235    // CHECK:      [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ]1236    // CHECK-NEXT: [[T0:%.*]] = load i1, ptr [[CLEANUP_REQUIRED]]1237    // CHECK-NEXT: br i1 [[T0]],1238    // CHECK:      [[T0:%.*]] = load ptr, ptr [[CLEANUP_VALUE]]1239    // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])1240    // CHECK-NEXT: br label1241    // CHECK:      br i1 [[COND]]1242    // CHECK:      call void @test62_body()1243    // CHECK-NEXT: br label1244    // CHECK:      br label1245    if (i != 0 && test62_make() != 0)1246      test62_body();1247  }1248 1249  // CHECK:      [[T0:%.*]] = load i32, ptr [[I]], align 41250  // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 11251  // CHECK-NEXT: store i32 [[T1]], ptr [[I]]1252  // CHECK-NEXT: br label1253 1254  // CHECK:      ret void1255}1256 1257@class NSString;1258 1259@interface Person  {1260  NSString *name;1261}1262@property NSString *address;1263@end1264 1265@implementation Person1266@synthesize address;1267@end1268// CHECK: tail call ptr @objc_getProperty1269// CHECK: call void @objc_setProperty1270 1271// Verify that we successfully parse and preserve this attribute in1272// this position.1273@interface Test661274- (void) consume: (id __attribute__((ns_consumed))) ptr;1275@end1276void test66(void) {1277  extern Test66 *test66_receiver(void);1278  extern id test66_arg(void);1279  [test66_receiver() consume: test66_arg()];1280}1281// CHECK-LABEL:    define{{.*}} void @test66()1282// CHECK:      [[T3:%.*]] = call ptr @test66_receiver(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1283// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]])1284// CHECK-NEXT: [[T4:%.*]] = call ptr @test66_arg(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1285// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T4]])1286// CHECK-NEXT: [[SIX:%.*]] = icmp eq ptr [[T3]], null1287// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label %[[CALL:.*]]1288// CHECK:      [[CALL]]:1289// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES1290// CHECK-NEXT: call void @objc_msgSend(ptr noundef [[T3]], ptr noundef [[SEL]], ptr noundef [[T4]])1291// CHECK-NEXT: br label [[CONT:%.*]]1292// CHECK: call void @llvm.objc.release(ptr [[T4]]) [[NUW]]1293// CHECK-NEXT: br label [[CONT:%.*]]1294// CHECK: call void @llvm.objc.release(ptr [[T3]])1295// CHECK-NEXT: ret void1296 1297Class test67_helper(void);1298void test67(void) {1299  Class cl = test67_helper();1300}1301// CHECK-LABEL:    define{{.*}} void @test67()1302// CHECK:      [[CL:%.*]] = alloca ptr, align 81303// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[CL]])1304// CHECK-NEXT: [[T0:%.*]] = call ptr @test67_helper()1305// CHECK-NEXT: store ptr [[T0]], ptr [[CL]], align 81306// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[CL]])1307// CHECK-NEXT: ret void1308 1309Class test68_helper(void);1310void test68(void) {1311  __strong Class cl = test67_helper();1312}1313// CHECK-LABEL:    define{{.*}} void @test68()1314// CHECK:      [[CL:%.*]] = alloca ptr, align 81315// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[CL]])1316// CHECK-NEXT: [[T1:%.*]] = call ptr @test67_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]1317// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])1318// CHECK-NEXT: store ptr [[T1]], ptr [[CL]], align 81319// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[CL]]1320// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])1321// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[CL]])1322// CHECK-NEXT: ret void1323 1324@interface Test69 @end1325@implementation Test691326- (id) foo { return self; }1327@end1328// CHECK: define internal ptr @"\01-[Test69 foo]"(1329// CHECK:      [[SELF:%.*]] = alloca ptr, align 81330// CHECK:      [[T0:%.*]] = load ptr, ptr [[SELF]], align 81331// CHECK-NEXT: ret ptr [[T0]]1332 1333void test70(id i) {1334  // CHECK-LABEL: define{{.*}} void @test701335  // CHECK: store ptr null, ptr1336  // CHECK: store ptr null, ptr1337  // CHECK: [[ID:%.*]] = call ptr @llvm.objc.retain(ptr1338  // CHECK: store ptr [[ID]], ptr1339  id x[3] = {1340    [2] = i1341  };1342}1343 1344// Be sure that we emit lifetime intrinsics only after dtors1345struct AggDtor {1346  char cs[40];1347  id x;1348};1349 1350struct AggDtor getAggDtor(void);1351 1352// CHECK-LABEL: define{{.*}} void @test711353void test71(void) {1354  // CHECK: call void @llvm.lifetime.start.p0(ptr %[[T:.*]])1355  // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T]])1356  // CHECK: call void @__destructor_8_s40(ptr %[[T]])1357  // CHECK: call void @llvm.lifetime.end.p0(ptr %[[T]])1358  // CHECK: call void @llvm.lifetime.start.p0(ptr %[[T2:.*]])1359  // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T2]])1360  // CHECK: call void @__destructor_8_s40(ptr %[[T2]])1361  // CHECK: call void @llvm.lifetime.end.p0(ptr %[[T2]])1362  getAggDtor();1363  getAggDtor();1364}1365 1366// Check that no extra release calls are emitted to detruct the compond literal.1367 1368// CHECK: define{{.*}} void @test72(ptr noundef %[[A:.*]], ptr noundef %[[B:.*]])1369// CHECK: %[[A_ADDR:.*]] = alloca ptr, align 81370// CHECK: %[[B_ADDR:.*]] = alloca ptr, align 81371// CHECK: %[[T:.*]] = alloca [2 x ptr], align 161372// CHECK: %[[V0:.*]] = call ptr @llvm.objc.retain(ptr %[[A]])1373// CHECK: %[[V1:.*]] = call ptr @llvm.objc.retain(ptr %[[B]]) #21374// CHECK: %[[V3:.*]] = load ptr, ptr %[[A_ADDR]], align 8, !tbaa !{{[0-9]+}}1375// CHECK: %[[V4:.*]] = call ptr @llvm.objc.retain(ptr %[[V3]]) #21376// CHECK: store ptr %[[V4]], ptr %[[T]], align 8, !tbaa !{{[0-9]+}}1377// CHECK: %[[ARRAYINIT_ELEMENT:.*]] = getelementptr inbounds ptr, ptr %[[T]], i64 11378// CHECK: %[[V5:.*]] = load ptr, ptr %[[B_ADDR]], align 8, !tbaa !{{[0-9]+}}1379// CHECK: %[[V6:.*]] = call ptr @llvm.objc.retain(ptr %[[V5]]) #21380// CHECK: store ptr %[[V6]], ptr %[[ARRAYINIT_ELEMENT]], align 8, !tbaa !{{[0-9]+}}1381// CHECK: %[[ARRAY_BEGIN:.*]] = getelementptr inbounds [2 x ptr], ptr %[[T]], i32 0, i32 01382// CHECK: %[[V7:.*]] = getelementptr inbounds ptr, ptr %[[ARRAY_BEGIN]], i64 21383 1384// CHECK-NOT: call void @llvm.objc.release1385 1386// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V7]], %{{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], %{{.*}} ]1387// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -11388// CHECK: %[[V8:.*]] = load ptr, ptr %[[ARRAYDESTROY_ELEMENT]], align 81389// CHECK: call void @llvm.objc.release(ptr %[[V8]]) #2, !clang.imprecise_release1390 1391// CHECK-NOT: call void @llvm.objc.release1392 1393// CHECK: %[[V10:.*]] = load ptr, ptr %[[B_ADDR]], align 81394// CHECK: call void @llvm.objc.release(ptr %[[V10]]) #2, !clang.imprecise_release1395// CHECK: %[[V11:.*]] = load ptr, ptr %[[A_ADDR]], align 81396// CHECK: call void @llvm.objc.release(ptr %[[V11]]) #2, !clang.imprecise_release1397 1398void test72(id a, id b) {1399  __strong id t[] = (__strong id[]){a, b};1400}1401 1402// ARC-ALIEN: attributes [[NLB]] = { nonlazybind }1403// ARC-NATIVE: attributes [[NLB]] = { nonlazybind }1404// CHECK: attributes [[NUW]] = { nounwind }1405