brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.4 KiB · d03cbd5 Raw
813 lines · plain
1; RUN: opt -passes=objc-arc -S < %s | FileCheck %s2 3%struct.__objcFastEnumerationState = type { i64, ptr, ptr, [5 x i64] }4 5@"\01L_OBJC_METH_VAR_NAME_" = internal global [43 x i8] c"countByEnumeratingWithState:objects:count:\00", section "__TEXT,__objc_methname,cstring_literals", align 16@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_", section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"7@g = common global ptr null, align 88@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"9 10declare void @callee()11declare ptr @returner()12declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)13declare ptr @llvm.objc.retain(ptr)14declare void @llvm.objc.enumerationMutation(ptr)15declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind16declare ptr @objc_msgSend(ptr, ptr, ...) nonlazybind17declare void @use(ptr)18declare void @llvm.objc.release(ptr)19declare ptr @def()20declare void @__crasher_block_invoke(ptr nocapture)21declare ptr @llvm.objc.retainBlock(ptr)22declare void @__crasher_block_invoke1(ptr nocapture)23 24!0 = !{}25 26; Delete a nested retain+release pair.27 28; CHECK-LABEL: define void @test0(29; CHECK: call ptr @llvm.objc.retain30; CHECK-NOT: @llvm.objc.retain31; CHECK: }32define void @test0(ptr %a) nounwind {33entry:34  %state.ptr = alloca %struct.__objcFastEnumerationState, align 835  %items.ptr = alloca [16 x ptr], align 836  %0 = call ptr @llvm.objc.retain(ptr %a) nounwind37  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)38  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind39  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 840  %call = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)41  %iszero = icmp eq i64 %call, 042  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit43 44forcoll.loopinit:45  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 246  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 847  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 848  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 149  br label %forcoll.loopbody.outer50 51forcoll.loopbody.outer:52  %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call6, %forcoll.refetch ]53  %tmp7 = icmp ugt i64 %forcoll.count.ph, 154  %umax = select i1 %tmp7, i64 %forcoll.count.ph, i64 155  br label %forcoll.loopbody56 57forcoll.loopbody:58  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]59  %mutationsptr3 = load ptr, ptr %mutationsptr.ptr, align 860  %statemutations = load i64, ptr %mutationsptr3, align 861  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations62  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated63 64forcoll.mutated:65  call void @llvm.objc.enumerationMutation(ptr %1)66  br label %forcoll.notmutated67 68forcoll.notmutated:69  %stateitems = load ptr, ptr %stateitems.ptr, align 870  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index71  %3 = load ptr, ptr %currentitem.ptr, align 872  call void @use(ptr %3)73  %4 = add i64 %forcoll.index, 174  %exitcond = icmp eq i64 %4, %umax75  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody76 77forcoll.refetch:78  %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 879  %call6 = call i64 @objc_msgSend(ptr %1, ptr %tmp5, ptr %state.ptr, ptr %items.ptr, i64 16)80  %5 = icmp eq i64 %call6, 081  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer82 83forcoll.empty:84  call void @llvm.objc.release(ptr %1) nounwind85  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !086  ret void87}88 89; Delete a nested retain+release pair.90 91; CHECK-LABEL: define void @test2(92; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue93; CHECK-NOT: @llvm.objc.retain94; CHECK: }95define void @test2() nounwind {96entry:97  %state.ptr = alloca %struct.__objcFastEnumerationState, align 898  %items.ptr = alloca [16 x ptr], align 899  %call = call ptr @returner()100  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind101  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)102  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind103  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8104  %call3 = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)105  %iszero = icmp eq i64 %call3, 0106  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit107 108forcoll.loopinit:109  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2110  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8111  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8112  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1113  br label %forcoll.loopbody.outer114 115forcoll.loopbody.outer:116  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]117  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1118  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1119  br label %forcoll.loopbody120 121forcoll.loopbody:122  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]123  %mutationsptr4 = load ptr, ptr %mutationsptr.ptr, align 8124  %statemutations = load i64, ptr %mutationsptr4, align 8125  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations126  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated127 128forcoll.mutated:129  call void @llvm.objc.enumerationMutation(ptr %1)130  br label %forcoll.notmutated131 132forcoll.notmutated:133  %stateitems = load ptr, ptr %stateitems.ptr, align 8134  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index135  %3 = load ptr, ptr %currentitem.ptr, align 8136  call void @use(ptr %3)137  %4 = add i64 %forcoll.index, 1138  %exitcond = icmp eq i64 %4, %umax139  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody140 141forcoll.refetch:142  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8143  %call7 = call i64 @objc_msgSend(ptr %1, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)144  %5 = icmp eq i64 %call7, 0145  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer146 147forcoll.empty:148  call void @llvm.objc.release(ptr %1) nounwind149  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0150  ret void151}152 153; Delete a nested retain+release pair.154 155; CHECK-LABEL: define void @test4(156; CHECK: call ptr @llvm.objc.retain157; CHECK-NOT: @llvm.objc.retain158; CHECK: }159define void @test4() nounwind {160entry:161  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8162  %items.ptr = alloca [16 x ptr], align 8163  %tmp = load ptr, ptr @g, align 8164  %0 = call ptr @llvm.objc.retain(ptr %tmp) nounwind165  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)166  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind167  %tmp4 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8168  %call = call i64 @objc_msgSend(ptr %1, ptr %tmp4, ptr %state.ptr, ptr %items.ptr, i64 16)169  %iszero = icmp eq i64 %call, 0170  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit171 172forcoll.loopinit:173  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2174  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8175  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8176  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1177  br label %forcoll.loopbody.outer178 179forcoll.loopbody.outer:180  %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call8, %forcoll.refetch ]181  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1182  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1183  br label %forcoll.loopbody184 185forcoll.loopbody:186  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]187  %mutationsptr5 = load ptr, ptr %mutationsptr.ptr, align 8188  %statemutations = load i64, ptr %mutationsptr5, align 8189  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations190  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated191 192forcoll.mutated:193  call void @llvm.objc.enumerationMutation(ptr %1)194  br label %forcoll.notmutated195 196forcoll.notmutated:197  %stateitems = load ptr, ptr %stateitems.ptr, align 8198  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index199  %3 = load ptr, ptr %currentitem.ptr, align 8200  call void @use(ptr %3)201  %4 = add i64 %forcoll.index, 1202  %exitcond = icmp eq i64 %4, %umax203  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody204 205forcoll.refetch:206  %tmp7 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8207  %call8 = call i64 @objc_msgSend(ptr %1, ptr %tmp7, ptr %state.ptr, ptr %items.ptr, i64 16)208  %5 = icmp eq i64 %call8, 0209  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer210 211forcoll.empty:212  call void @llvm.objc.release(ptr %1) nounwind213  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0214  ret void215}216 217; Delete a nested retain+release pair.218 219; CHECK-LABEL: define void @test5(220; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue221; CHECK-NOT: @llvm.objc.retain222; CHECK: }223define void @test5() nounwind {224entry:225  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8226  %items.ptr = alloca [16 x ptr], align 8227  %call = call ptr @returner()228  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind229  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)230  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind231  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8232  %call3 = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)233  %iszero = icmp eq i64 %call3, 0234  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit235 236forcoll.loopinit:237  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2238  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8239  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8240  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1241  br label %forcoll.loopbody.outer242 243forcoll.loopbody.outer:244  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]245  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1246  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1247  br label %forcoll.loopbody248 249forcoll.loopbody:250  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]251  %mutationsptr4 = load ptr, ptr %mutationsptr.ptr, align 8252  %statemutations = load i64, ptr %mutationsptr4, align 8253  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations254  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated255 256forcoll.mutated:257  call void @llvm.objc.enumerationMutation(ptr %1)258  br label %forcoll.notmutated259 260forcoll.notmutated:261  %stateitems = load ptr, ptr %stateitems.ptr, align 8262  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index263  %3 = load ptr, ptr %currentitem.ptr, align 8264  call void @use(ptr %3)265  %4 = add i64 %forcoll.index, 1266  %exitcond = icmp eq i64 %4, %umax267  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody268 269forcoll.refetch:270  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8271  %call7 = call i64 @objc_msgSend(ptr %1, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)272  %5 = icmp eq i64 %call7, 0273  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer274 275forcoll.empty:276  call void @llvm.objc.release(ptr %1) nounwind277  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0278  ret void279}280 281; We handle this now due to the fact that a release just needs a post dominating282; use.283;284; CHECK-LABEL: define void @test6(285; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue286; CHECK-NOT: @llvm.objc.retain287; CHECK: }288define void @test6() nounwind {289entry:290  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8291  %items.ptr = alloca [16 x ptr], align 8292  %call = call ptr @returner()293  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind294  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)295  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind296  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8297  %call3 = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)298  %iszero = icmp eq i64 %call3, 0299  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit300 301forcoll.loopinit:302  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2303  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8304  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8305  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1306  br label %forcoll.loopbody.outer307 308forcoll.loopbody.outer:309  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]310  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1311  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1312  br label %forcoll.loopbody313 314forcoll.loopbody:315  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]316  %mutationsptr4 = load ptr, ptr %mutationsptr.ptr, align 8317  %statemutations = load i64, ptr %mutationsptr4, align 8318  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations319  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated320 321forcoll.mutated:322  call void @llvm.objc.enumerationMutation(ptr %1)323  br label %forcoll.notmutated324 325forcoll.notmutated:326  %stateitems = load ptr, ptr %stateitems.ptr, align 8327  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index328  %3 = load ptr, ptr %currentitem.ptr, align 8329  call void @use(ptr %3)330  %4 = add i64 %forcoll.index, 1331  %exitcond = icmp eq i64 %4, %umax332  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody333 334forcoll.refetch:335  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8336  %call7 = call i64 @objc_msgSend(ptr %1, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)337  %5 = icmp eq i64 %call7, 0338  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer339 340forcoll.empty:341  call void @llvm.objc.release(ptr %1) nounwind342  call void @callee()343  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0344  ret void345}346 347; TODO: Delete a nested retain+release pair.348; The optimizer currently can't do this, because isn't isn't sophisticated enough in349; reasnoning about nesting.350 351; CHECK-LABEL: define void @test7(352; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue353; CHECK: @llvm.objc.retain354; CHECK: }355define void @test7() nounwind {356entry:357  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8358  %items.ptr = alloca [16 x ptr], align 8359  %call = call ptr @returner()360  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind361  call void @callee()362  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)363  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind364  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8365  %call3 = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)366  %iszero = icmp eq i64 %call3, 0367  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit368 369forcoll.loopinit:370  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2371  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8372  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8373  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1374  br label %forcoll.loopbody.outer375 376forcoll.loopbody.outer:377  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]378  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1379  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1380  br label %forcoll.loopbody381 382forcoll.loopbody:383  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]384  %mutationsptr4 = load ptr, ptr %mutationsptr.ptr, align 8385  %statemutations = load i64, ptr %mutationsptr4, align 8386  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations387  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated388 389forcoll.mutated:390  call void @llvm.objc.enumerationMutation(ptr %1)391  br label %forcoll.notmutated392 393forcoll.notmutated:394  %stateitems = load ptr, ptr %stateitems.ptr, align 8395  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index396  %3 = load ptr, ptr %currentitem.ptr, align 8397  call void @use(ptr %3)398  %4 = add i64 %forcoll.index, 1399  %exitcond = icmp eq i64 %4, %umax400  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody401 402forcoll.refetch:403  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8404  %call7 = call i64 @objc_msgSend(ptr %1, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)405  %5 = icmp eq i64 %call7, 0406  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer407 408forcoll.empty:409  call void @llvm.objc.release(ptr %1) nounwind410  call void @callee()411  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0412  ret void413}414 415; Delete a nested retain+release pair.416 417; CHECK-LABEL: define void @test8(418; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue419; CHECK-NOT: @llvm.objc.retain420; CHECK: }421define void @test8() nounwind {422entry:423  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8424  %items.ptr = alloca [16 x ptr], align 8425  %call = call ptr @returner()426  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind427  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)428  %1 = call ptr @llvm.objc.retain(ptr %0) nounwind429  %tmp2 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8430  %call3 = call i64 @objc_msgSend(ptr %1, ptr %tmp2, ptr %state.ptr, ptr %items.ptr, i64 16)431  %iszero = icmp eq i64 %call3, 0432  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit433 434forcoll.loopinit:435  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2436  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8437  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8438  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 1439  br label %forcoll.loopbody.outer440 441forcoll.loopbody.outer:442  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]443  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1444  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1445  br label %forcoll.loopbody446 447forcoll.loopbody:448  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.next ]449  %mutationsptr4 = load ptr, ptr %mutationsptr.ptr, align 8450  %statemutations = load i64, ptr %mutationsptr4, align 8451  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations452  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated453 454forcoll.mutated:455  call void @llvm.objc.enumerationMutation(ptr %1)456  br label %forcoll.notmutated457 458forcoll.notmutated:459  %stateitems = load ptr, ptr %stateitems.ptr, align 8460  %currentitem.ptr = getelementptr ptr, ptr %stateitems, i64 %forcoll.index461  %3 = load ptr, ptr %currentitem.ptr, align 8462  %tobool = icmp eq ptr %3, null463  br i1 %tobool, label %forcoll.next, label %if.then464 465if.then:466  call void @callee()467  br label %forcoll.next468 469forcoll.next:470  %4 = add i64 %forcoll.index, 1471  %exitcond = icmp eq i64 %4, %umax472  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody473 474forcoll.refetch:475  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8476  %call7 = call i64 @objc_msgSend(ptr %1, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)477  %5 = icmp eq i64 %call7, 0478  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer479 480forcoll.empty:481  call void @llvm.objc.release(ptr %1) nounwind482  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0483  ret void484}485 486; TODO: Delete a nested retain+release pair.487; The optimizer currently can't do this, because of a split loop backedge.488; See test9b for the same testcase without a split backedge.489 490; CHECK-LABEL: define void @test9(491; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue492; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue493; CHECK: call ptr @llvm.objc.retain494; CHECK: }495define void @test9() nounwind {496entry:497  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8498  %items.ptr = alloca [16 x ptr], align 8499  %call = call ptr @returner()500  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind501  %call1 = call ptr @returner()502  %1 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1) nounwind503  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)504  %2 = call ptr @llvm.objc.retain(ptr %0) nounwind505  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8506  %call4 = call i64 @objc_msgSend(ptr %2, ptr %tmp3, ptr %state.ptr, ptr %items.ptr, i64 16)507  %iszero = icmp eq i64 %call4, 0508  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit509 510forcoll.loopinit:511  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2512  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8513  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8514  br label %forcoll.loopbody.outer515 516forcoll.loopbody.outer:517  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]518  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1519  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1520  br label %forcoll.loopbody521 522forcoll.loopbody:523  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]524  %mutationsptr5 = load ptr, ptr %mutationsptr.ptr, align 8525  %statemutations = load i64, ptr %mutationsptr5, align 8526  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations527  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated528 529forcoll.mutated:530  call void @llvm.objc.enumerationMutation(ptr %2)531  br label %forcoll.notmutated532 533forcoll.notmutated:534  %exitcond = icmp eq i64 %forcoll.index, %umax535  br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge536 537forcoll.notmutated.forcoll.loopbody_crit_edge:538  %phitmp = add i64 %forcoll.index, 1539  br label %forcoll.loopbody540 541forcoll.refetch:542  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8543  %call7 = call i64 @objc_msgSend(ptr %2, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)544  %4 = icmp eq i64 %call7, 0545  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer546 547forcoll.empty:548  call void @llvm.objc.release(ptr %2) nounwind549  call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0550  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0551  ret void552}553 554; Like test9, but without a split backedge. TODO: optimize this.555 556; CHECK-LABEL: define void @test9b(557; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue558; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue559; CHECK: @llvm.objc.retain560; CHECK: }561define void @test9b() nounwind {562entry:563  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8564  %items.ptr = alloca [16 x ptr], align 8565  %call = call ptr @returner()566  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind567  %call1 = call ptr @returner()568  %1 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1) nounwind569  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)570  %2 = call ptr @llvm.objc.retain(ptr %0) nounwind571  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8572  %call4 = call i64 @objc_msgSend(ptr %2, ptr %tmp3, ptr %state.ptr, ptr %items.ptr, i64 16)573  %iszero = icmp eq i64 %call4, 0574  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit575 576forcoll.loopinit:577  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2578  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8579  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8580  br label %forcoll.loopbody.outer581 582forcoll.loopbody.outer:583  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]584  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1585  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1586  br label %forcoll.loopbody587 588forcoll.loopbody:589  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated ], [ 0, %forcoll.loopbody.outer ]590  %mutationsptr5 = load ptr, ptr %mutationsptr.ptr, align 8591  %statemutations = load i64, ptr %mutationsptr5, align 8592  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations593  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated594 595forcoll.mutated:596  call void @llvm.objc.enumerationMutation(ptr %2)597  br label %forcoll.notmutated598 599forcoll.notmutated:600  %phitmp = add i64 %forcoll.index, 1601  %exitcond = icmp eq i64 %phitmp, %umax602  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody603 604forcoll.refetch:605  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8606  %call7 = call i64 @objc_msgSend(ptr %2, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)607  %4 = icmp eq i64 %call7, 0608  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer609 610forcoll.empty:611  call void @llvm.objc.release(ptr %2) nounwind612  call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0613  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0614  ret void615}616 617; TODO: Delete a nested retain+release pair.618; The optimizer currently can't do this, because of a split loop backedge.619; See test10b for the same testcase without a split backedge.620 621; CHECK-LABEL: define void @test10(622; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue623; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue624; CHECK: call ptr @llvm.objc.retain625; CHECK: }626define void @test10() nounwind {627entry:628  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8629  %items.ptr = alloca [16 x ptr], align 8630  %call = call ptr @returner()631  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind632  %call1 = call ptr @returner()633  %1 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1) nounwind634  call void @callee()635  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)636  %2 = call ptr @llvm.objc.retain(ptr %0) nounwind637  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8638  %call4 = call i64 @objc_msgSend(ptr %2, ptr %tmp3, ptr %state.ptr, ptr %items.ptr, i64 16)639  %iszero = icmp eq i64 %call4, 0640  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit641 642forcoll.loopinit:643  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2644  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8645  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8646  br label %forcoll.loopbody.outer647 648forcoll.loopbody.outer:649  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]650  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1651  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1652  br label %forcoll.loopbody653 654forcoll.loopbody:655  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]656  %mutationsptr5 = load ptr, ptr %mutationsptr.ptr, align 8657  %statemutations = load i64, ptr %mutationsptr5, align 8658  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations659  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated660 661forcoll.mutated:662  call void @llvm.objc.enumerationMutation(ptr %2)663  br label %forcoll.notmutated664 665forcoll.notmutated:666  %exitcond = icmp eq i64 %forcoll.index, %umax667  br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge668 669forcoll.notmutated.forcoll.loopbody_crit_edge:670  %phitmp = add i64 %forcoll.index, 1671  br label %forcoll.loopbody672 673forcoll.refetch:674  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8675  %call7 = call i64 @objc_msgSend(ptr %2, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)676  %4 = icmp eq i64 %call7, 0677  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer678 679forcoll.empty:680  call void @llvm.objc.release(ptr %2) nounwind681  call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0682  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0683  ret void684}685 686; Like test10, but without a split backedge. TODO: optimize this.687 688; CHECK-LABEL: define void @test10b(689; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue690; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue691; CHECK: @llvm.objc.retain692; CHECK: }693define void @test10b() nounwind {694entry:695  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8696  %items.ptr = alloca [16 x ptr], align 8697  %call = call ptr @returner()698  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind699  %call1 = call ptr @returner()700  %1 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1) nounwind701  call void @callee()702  call void @llvm.memset.p0.i64(ptr align 8 %state.ptr, i8 0, i64 64, i1 false)703  %2 = call ptr @llvm.objc.retain(ptr %0) nounwind704  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8705  %call4 = call i64 @objc_msgSend(ptr %2, ptr %tmp3, ptr %state.ptr, ptr %items.ptr, i64 16)706  %iszero = icmp eq i64 %call4, 0707  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit708 709forcoll.loopinit:710  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, ptr %state.ptr, i64 0, i32 2711  %mutationsptr = load ptr, ptr %mutationsptr.ptr, align 8712  %forcoll.initial-mutations = load i64, ptr %mutationsptr, align 8713  br label %forcoll.loopbody.outer714 715forcoll.loopbody.outer:716  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]717  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1718  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1719  br label %forcoll.loopbody720 721forcoll.loopbody:722  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated ], [ 0, %forcoll.loopbody.outer ]723  %mutationsptr5 = load ptr, ptr %mutationsptr.ptr, align 8724  %statemutations = load i64, ptr %mutationsptr5, align 8725  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations726  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated727 728forcoll.mutated:729  call void @llvm.objc.enumerationMutation(ptr %2)730  br label %forcoll.notmutated731 732forcoll.notmutated:733  %phitmp = add i64 %forcoll.index, 1734  %exitcond = icmp eq i64 %phitmp, %umax735  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody736 737forcoll.refetch:738  %tmp6 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8739  %call7 = call i64 @objc_msgSend(ptr %2, ptr %tmp6, ptr %state.ptr, ptr %items.ptr, i64 16)740  %4 = icmp eq i64 %call7, 0741  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer742 743forcoll.empty:744  call void @llvm.objc.release(ptr %2) nounwind745  call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0746  call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0747  ret void748}749 750; Pointers to strong pointers can obscure provenance relationships. Be conservative751; in the face of escaping pointers. rdar://12150909.752 753%struct.__block_d = type { i64, i64 }754 755@_NSConcreteStackBlock = external global ptr756@__block_d_tmp = external hidden constant { i64, i64, ptr, ptr, ptr, ptr }757@__block_d_tmp5 = external hidden constant { i64, i64, ptr, ptr, ptr, ptr }758 759; CHECK-LABEL: define void @test11(760; CHECK: tail call ptr @llvm.objc.retain(ptr %call) [[NUW:#[0-9]+]]761; CHECK: tail call ptr @llvm.objc.retain(ptr %call) [[NUW]]762; CHECK: call void @llvm.objc.release(ptr %call) [[NUW]], !clang.imprecise_release !0763; CHECK: }764define void @test11() {765entry:766  %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8767  %block9 = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8768  %call = call ptr @def(), !clang.arc.no_objc_arc_exceptions !0769  %foo = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 5770  %block.isa = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 0771  store ptr @_NSConcreteStackBlock, ptr %block.isa, align 8772  %block.flags = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 1773  store i32 1107296256, ptr %block.flags, align 8774  %block.reserved = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 2775  store i32 0, ptr %block.reserved, align 4776  %block.invoke = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 3777  store ptr @__crasher_block_invoke, ptr %block.invoke, align 8778  %block.d = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block, i64 0, i32 4779  store ptr @__block_d_tmp, ptr %block.d, align 8780  %foo2 = tail call ptr @llvm.objc.retain(ptr %call) nounwind781  store ptr %foo2, ptr %foo, align 8782  %foo5 = call ptr @llvm.objc.retainBlock(ptr %block) nounwind783  call void @use(ptr %foo5), !clang.arc.no_objc_arc_exceptions !0784  call void @llvm.objc.release(ptr %foo5) nounwind785  %strongdestroy = load ptr, ptr %foo, align 8786  call void @llvm.objc.release(ptr %strongdestroy) nounwind, !clang.imprecise_release !0787  %foo10 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 5788  %block.isa11 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 0789  store ptr @_NSConcreteStackBlock, ptr %block.isa11, align 8790  %block.flags12 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 1791  store i32 1107296256, ptr %block.flags12, align 8792  %block.reserved13 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 2793  store i32 0, ptr %block.reserved13, align 4794  %block.invoke14 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 3795  store ptr @__crasher_block_invoke1, ptr %block.invoke14, align 8796  %block.d15 = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %block9, i64 0, i32 4797  store ptr @__block_d_tmp5, ptr %block.d15, align 8798  %foo18 = call ptr @llvm.objc.retain(ptr %call) nounwind799  store ptr %call, ptr %foo10, align 8800  %foo21 = call ptr @llvm.objc.retainBlock(ptr %block9) nounwind801  call void @use(ptr %foo21), !clang.arc.no_objc_arc_exceptions !0802  call void @llvm.objc.release(ptr %foo21) nounwind803  %strongdestroy25 = load ptr, ptr %foo10, align 8804  call void @llvm.objc.release(ptr %strongdestroy25) nounwind, !clang.imprecise_release !0805  call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0806  ret void807}808 809 810; CHECK: attributes [[NUW]] = { nounwind }811; CHECK: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }812; CHECK: attributes #2 = { nonlazybind }813