984 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 62; RUN: opt < %s -passes=licm -S | FileCheck %s3; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s4target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"5 6@X = global i32 7 ; <ptr> [#uses=4]7 8define void @test1(i32 %i) {9; CHECK-LABEL: define void @test1(10; CHECK-SAME: i32 [[I:%.*]]) {11; CHECK-NEXT: [[ENTRY:.*]]:12; CHECK-NEXT: [[X_PROMOTED:%.*]] = load i32, ptr @X, align 413; CHECK-NEXT: br label %[[LOOP:.*]]14; CHECK: [[LOOP]]:15; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[X_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[LOOP]] ]16; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ]17; CHECK-NEXT: [[X2]] = add i32 [[X21]], 118; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 119; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 020; CHECK-NEXT: br i1 [[COND]], label %[[OUT:.*]], label %[[LOOP]]21; CHECK: [[OUT]]:22; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[LOOP]] ]23; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr @X, align 424; CHECK-NEXT: ret void25;26Entry:27 br label %Loop28 29Loop: ; preds = %Loop, %030 %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ] ; <i32> [#uses=1]31 %x = load i32, ptr @X ; <i32> [#uses=1]32 %x2 = add i32 %x, 1 ; <i32> [#uses=1]33 store i32 %x2, ptr @X34 %Next = add i32 %j, 1 ; <i32> [#uses=2]35 %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]36 br i1 %cond, label %Out, label %Loop37 38Out:39 ret void40}41 42define void @test2(i32 %i) {43; CHECK-LABEL: define void @test2(44; CHECK-SAME: i32 [[I:%.*]]) {45; CHECK-NEXT: [[ENTRY:.*]]:46; CHECK-NEXT: [[X1:%.*]] = getelementptr i32, ptr @X, i64 147; CHECK-NEXT: [[X2:%.*]] = getelementptr i32, ptr @X, i64 148; CHECK-NEXT: [[X1_PROMOTED:%.*]] = load i32, ptr [[X1]], align 449; CHECK-NEXT: br label %[[LOOP:.*]]50; CHECK: [[LOOP]]:51; CHECK-NEXT: [[A1:%.*]] = phi i32 [ [[V:%.*]], %[[LOOP]] ], [ [[X1_PROMOTED]], %[[ENTRY]] ]52; CHECK-NEXT: [[V]] = add i32 [[A1]], 153; CHECK-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]54; CHECK: [[EXIT]]:55; CHECK-NEXT: [[V_LCSSA:%.*]] = phi i32 [ [[V]], %[[LOOP]] ]56; CHECK-NEXT: store i32 [[V_LCSSA]], ptr [[X1]], align 457; CHECK-NEXT: ret void58;59Entry:60 br label %Loop61 62Loop: ; preds = %Loop, %063 %X1 = getelementptr i32, ptr @X, i64 1 ; <ptr> [#uses=1]64 %A = load i32, ptr %X1 ; <i32> [#uses=1]65 %V = add i32 %A, 1 ; <i32> [#uses=1]66 %X2 = getelementptr i32, ptr @X, i64 1 ; <ptr> [#uses=1]67 store i32 %V, ptr %X268 br i1 false, label %Loop, label %Exit69 70Exit: ; preds = %Loop71 ret void72}73 74define void @test3(i32 %i) {75; CHECK-LABEL: define void @test3(76; CHECK-SAME: i32 [[I:%.*]]) {77; CHECK-NEXT: br label %[[LOOP:.*]]78; CHECK: [[LOOP]]:79; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr @X, align 480; CHECK-NEXT: [[X2:%.*]] = add i32 [[X]], 181; CHECK-NEXT: store i32 [[X2]], ptr @X, align 482; CHECK-NEXT: br i1 true, label %[[OUT:.*]], label %[[LOOP]]83; CHECK: [[OUT]]:84; CHECK-NEXT: ret void85;86 br label %Loop87Loop:88 ; Should not promote this to a register89 %x = load volatile i32, ptr @X90 %x2 = add i32 %x, 191 store i32 %x2, ptr @X92 br i1 true, label %Out, label %Loop93 94Out: ; preds = %Loop95 ret void96}97 98; Should not promote this to a register99define void @test3b(i32 %i) {100; CHECK-LABEL: define void @test3b(101; CHECK-SAME: i32 [[I:%.*]]) {102; CHECK-NEXT: br label %[[LOOP:.*]]103; CHECK: [[LOOP]]:104; CHECK-NEXT: [[X:%.*]] = load i32, ptr @X, align 4105; CHECK-NEXT: [[X2:%.*]] = add i32 [[X]], 1106; CHECK-NEXT: store volatile i32 [[X2]], ptr @X, align 4107; CHECK-NEXT: br i1 true, label %[[OUT:.*]], label %[[LOOP]]108; CHECK: [[OUT]]:109; CHECK-NEXT: ret void110;111 br label %Loop112Loop:113 %x = load i32, ptr @X114 %x2 = add i32 %x, 1115 store volatile i32 %x2, ptr @X116 br i1 true, label %Out, label %Loop117 118Out: ; preds = %Loop119 ret void120}121 122; PR8041123; Should have promoted 'handle2' accesses.124; Should not have promoted offsetx1 loads.125define void @test4(ptr %x, i8 %n) {126; CHECK-LABEL: define void @test4(127; CHECK-SAME: ptr [[X:%.*]], i8 [[N:%.*]]) {128; CHECK-NEXT: [[HANDLE1:%.*]] = alloca ptr, align 8129; CHECK-NEXT: [[HANDLE2:%.*]] = alloca ptr, align 8130; CHECK-NEXT: store ptr [[X]], ptr [[HANDLE1]], align 8131; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr [[X]], i64 8132; CHECK-NEXT: [[OFFSETX1:%.*]] = load ptr, ptr [[HANDLE1]], align 8133; CHECK-NEXT: br label %[[LOOP:.*]]134; CHECK: [[LOOP]]:135; CHECK-NEXT: br label %[[SUBLOOP:.*]]136; CHECK: [[SUBLOOP]]:137; CHECK-NEXT: [[NEWOFFSETX21:%.*]] = phi ptr [ [[TMP]], %[[LOOP]] ], [ [[NEWOFFSETX2:%.*]], %[[SUBLOOP]] ]138; CHECK-NEXT: [[COUNT:%.*]] = phi i8 [ 0, %[[LOOP]] ], [ [[NEXTCOUNT:%.*]], %[[SUBLOOP]] ]139; CHECK-NEXT: store i8 [[N]], ptr [[NEWOFFSETX21]], align 1140; CHECK-NEXT: [[NEWOFFSETX2]] = getelementptr i8, ptr [[NEWOFFSETX21]], i64 -1141; CHECK-NEXT: [[NEXTCOUNT]] = add i8 [[COUNT]], 1142; CHECK-NEXT: [[INNEREXITCOND:%.*]] = icmp sge i8 [[NEXTCOUNT]], 8143; CHECK-NEXT: br i1 [[INNEREXITCOND]], label %[[INNEREXIT:.*]], label %[[SUBLOOP]]144; CHECK: [[INNEREXIT]]:145; CHECK-NEXT: [[NEWOFFSETX2_LCSSA:%.*]] = phi ptr [ [[NEWOFFSETX2]], %[[SUBLOOP]] ]146; CHECK-NEXT: [[VAL:%.*]] = load i8, ptr [[OFFSETX1]], align 1147; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL]], [[N]]148; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]149; CHECK: [[EXIT]]:150; CHECK-NEXT: [[NEWOFFSETX2_LCSSA_LCSSA:%.*]] = phi ptr [ [[NEWOFFSETX2_LCSSA]], %[[INNEREXIT]] ]151; CHECK-NEXT: store ptr [[NEWOFFSETX2_LCSSA_LCSSA]], ptr [[HANDLE2]], align 8152; CHECK-NEXT: ret void153;154 %handle1 = alloca ptr155 %handle2 = alloca ptr156 store ptr %x, ptr %handle1157 br label %loop158 159loop:160 %tmp = getelementptr i8, ptr %x, i64 8161 store ptr %tmp, ptr %handle2162 br label %subloop163 164subloop:165 %count = phi i8 [ 0, %loop ], [ %nextcount, %subloop ]166 %offsetx2 = load ptr, ptr %handle2167 store i8 %n, ptr %offsetx2168 %newoffsetx2 = getelementptr i8, ptr %offsetx2, i64 -1169 store ptr %newoffsetx2, ptr %handle2170 %nextcount = add i8 %count, 1171 %innerexitcond = icmp sge i8 %nextcount, 8172 br i1 %innerexitcond, label %innerexit, label %subloop173 174innerexit:175 %offsetx1 = load ptr, ptr %handle1176 %val = load i8, ptr %offsetx1177 %cond = icmp eq i8 %val, %n178 br i1 %cond, label %exit, label %loop179 180exit:181 ret void182}183 184define void @test5(i32 %i, ptr noalias %P2) {185; CHECK-LABEL: define void @test5(186; CHECK-SAME: i32 [[I:%.*]], ptr noalias [[P2:%.*]]) {187; CHECK-NEXT: [[ENTRY:.*]]:188; CHECK-NEXT: [[X_PROMOTED:%.*]] = load i32, ptr @X, align 4189; CHECK-NEXT: br label %[[LOOP:.*]]190; CHECK: [[LOOP]]:191; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[X_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[LOOP]] ]192; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ]193; CHECK-NEXT: [[X2]] = add i32 [[X21]], 1194; CHECK-NEXT: store atomic ptr @X, ptr [[P2]] monotonic, align 8195; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1196; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0197; CHECK-NEXT: br i1 [[COND]], label %[[OUT:.*]], label %[[LOOP]]198; CHECK: [[OUT]]:199; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[LOOP]] ]200; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr @X, align 4201; CHECK-NEXT: ret void202;203Entry:204 br label %Loop205 206Loop: ; preds = %Loop, %0207 %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ] ; <i32> [#uses=1]208 %x = load i32, ptr @X ; <i32> [#uses=1]209 %x2 = add i32 %x, 1 ; <i32> [#uses=1]210 store i32 %x2, ptr @X211 212 store atomic ptr @X, ptr %P2 monotonic, align 8213 214 %Next = add i32 %j, 1 ; <i32> [#uses=2]215 %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]216 br i1 %cond, label %Out, label %Loop217 218Out:219 ret void220 221}222 223 224; PR14753 - Preserve TBAA tags when promoting values in a loop.225define void @test6(i32 %n, ptr nocapture %a, ptr %gi) {226; CHECK-LABEL: define void @test6(227; CHECK-SAME: i32 [[N:%.*]], ptr captures(none) [[A:%.*]], ptr [[GI:%.*]]) {228; CHECK-NEXT: [[ENTRY:.*:]]229; CHECK-NEXT: store i32 0, ptr [[GI]], align 4, !tbaa [[INT_TBAA0:![0-9]+]]230; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[N]]231; CHECK-NEXT: br i1 [[CMP1]], label %[[FOR_BODY_LR_PH:.*]], label %[[FOR_END:.*]]232; CHECK: [[FOR_BODY_LR_PH]]:233; CHECK-NEXT: [[GI_PROMOTED:%.*]] = load i32, ptr [[GI]], align 4, !tbaa [[INT_TBAA0]]234; CHECK-NEXT: br label %[[FOR_BODY:.*]]235; CHECK: [[FOR_BODY]]:236; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ [[GI_PROMOTED]], %[[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], %[[FOR_BODY]] ]237; CHECK-NEXT: [[STOREMERGE2:%.*]] = phi i32 [ 0, %[[FOR_BODY_LR_PH]] ], [ [[INC]], %[[FOR_BODY]] ]238; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[STOREMERGE2]] to i64239; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[A]], i64 [[IDXPROM]]240; CHECK-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX]], align 4, !tbaa [[FLOAT_TBAA4:![0-9]+]]241; CHECK-NEXT: [[INC]] = add nsw i32 [[INC1]], 1242; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[N]]243; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_FOR_END_CRIT_EDGE:.*]]244; CHECK: [[FOR_COND_FOR_END_CRIT_EDGE]]:245; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], %[[FOR_BODY]] ]246; CHECK-NEXT: store i32 [[INC_LCSSA]], ptr [[GI]], align 4, !tbaa [[INT_TBAA0]]247; CHECK-NEXT: br label %[[FOR_END]]248; CHECK: [[FOR_END]]:249; CHECK-NEXT: ret void250;251entry:252 store i32 0, ptr %gi, align 4, !tbaa !0253 %cmp1 = icmp slt i32 0, %n254 br i1 %cmp1, label %for.body.lr.ph, label %for.end255 256for.body.lr.ph: ; preds = %entry257 br label %for.body258 259for.body: ; preds = %for.body.lr.ph, %for.body260 %storemerge2 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]261 %idxprom = sext i32 %storemerge2 to i64262 %arrayidx = getelementptr inbounds float, ptr %a, i64 %idxprom263 store float 0.000000e+00, ptr %arrayidx, align 4, !tbaa !3264 %0 = load i32, ptr %gi, align 4, !tbaa !0265 %inc = add nsw i32 %0, 1266 store i32 %inc, ptr %gi, align 4, !tbaa !0267 %cmp = icmp slt i32 %inc, %n268 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge269 270for.cond.for.end_crit_edge: ; preds = %for.body271 br label %for.end272 273for.end: ; preds = %for.cond.for.end_crit_edge, %entry274 ret void275 276}277 278declare i32 @opaque(i32) argmemonly279declare void @capture(ptr)280 281; We can promote even if opaque may throw.282define i32 @test7() {283; CHECK-LABEL: define i32 @test7() {284; CHECK-NEXT: [[ENTRY:.*]]:285; CHECK-NEXT: [[LOCAL:%.*]] = alloca i32, align 4286; CHECK-NEXT: call void @capture(ptr [[LOCAL]])287; CHECK-NEXT: [[LOCAL_PROMOTED:%.*]] = load i32, ptr [[LOCAL]], align 4288; CHECK-NEXT: br label %[[LOOP:.*]]289; CHECK: [[LOOP]]:290; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[LOCAL_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[LOOP]] ]291; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ]292; CHECK-NEXT: [[X2]] = call i32 @opaque(i32 [[X21]])293; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1294; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0295; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]296; CHECK: [[EXIT]]:297; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[LOOP]] ]298; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr [[LOCAL]], align 4299; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[LOCAL]], align 4300; CHECK-NEXT: ret i32 [[RET]]301;302entry:303 %local = alloca i32304 call void @capture(ptr %local)305 br label %loop306 307loop:308 %j = phi i32 [ 0, %entry ], [ %next, %loop ]309 %x = load i32, ptr %local310 %x2 = call i32 @opaque(i32 %x) ; Note this does not capture %local311 store i32 %x2, ptr %local312 %next = add i32 %j, 1313 %cond = icmp eq i32 %next, 0314 br i1 %cond, label %exit, label %loop315 316exit:317 %ret = load i32, ptr %local318 ret i32 %ret319}320 321; Hoist the load even if we cannot sink the store, since the store is really322; control-flow dependent.323define i32 @test7bad() {324; CHECK-LABEL: define i32 @test7bad() {325; CHECK-NEXT: [[ENTRY:.*]]:326; CHECK-NEXT: [[LOCAL:%.*]] = alloca i32, align 4327; CHECK-NEXT: call void @capture(ptr [[LOCAL]])328; CHECK-NEXT: [[LOCAL_PROMOTED:%.*]] = load i32, ptr [[LOCAL]], align 4329; CHECK-NEXT: br label %[[LOOP:.*]]330; CHECK: [[LOOP]]:331; CHECK-NEXT: [[X22:%.*]] = phi i32 [ [[LOCAL_PROMOTED]], %[[ENTRY]] ], [ [[X21:%.*]], %[[ELSE:.*]] ]332; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[ELSE]] ]333; CHECK-NEXT: [[X2:%.*]] = call i32 @opaque(i32 [[X22]])334; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X2]], 0335; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[ELSE]]336; CHECK: [[IF]]:337; CHECK-NEXT: store i32 [[X2]], ptr [[LOCAL]], align 4338; CHECK-NEXT: br label %[[ELSE]]339; CHECK: [[ELSE]]:340; CHECK-NEXT: [[X21]] = phi i32 [ [[X2]], %[[IF]] ], [ [[X22]], %[[LOOP]] ]341; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1342; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0343; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]344; CHECK: [[EXIT]]:345; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[LOCAL]], align 4346; CHECK-NEXT: ret i32 [[RET]]347;348entry:349 %local = alloca i32350 call void @capture(ptr %local)351 br label %loop352loop:353 %j = phi i32 [ 0, %entry ], [ %next, %else ]354 %x = load i32, ptr %local355 %x2 = call i32 @opaque(i32 %x) ; Note this does not capture %local356 %cmp = icmp eq i32 %x2, 0357 br i1 %cmp, label %if, label %else358 359if:360 store i32 %x2, ptr %local361 br label %else362 363else:364 %next = add i32 %j, 1365 %cond = icmp eq i32 %next, 0366 br i1 %cond, label %exit, label %loop367 368exit:369 %ret = load i32, ptr %local370 ret i32 %ret371}372 373; Even if neither the load nor the store or guaranteed to execute because374; opaque() may throw, we can still promote - the load not being guaranteed375; doesn't block us, because %local is always dereferenceable.376define i32 @test8() {377; CHECK-LABEL: define i32 @test8() {378; CHECK-NEXT: [[ENTRY:.*]]:379; CHECK-NEXT: [[LOCAL:%.*]] = alloca i32, align 4380; CHECK-NEXT: call void @capture(ptr [[LOCAL]])381; CHECK-NEXT: [[LOCAL_PROMOTED:%.*]] = load i32, ptr [[LOCAL]], align 4382; CHECK-NEXT: br label %[[LOOP:.*]]383; CHECK: [[LOOP]]:384; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[LOCAL_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[LOOP]] ]385; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ]386; CHECK-NEXT: [[THROWAWAY:%.*]] = call i32 @opaque(i32 [[J]])387; CHECK-NEXT: [[X2]] = call i32 @opaque(i32 [[X21]])388; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1389; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0390; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]391; CHECK: [[EXIT]]:392; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[LOOP]] ]393; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr [[LOCAL]], align 4394; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[LOCAL]], align 4395; CHECK-NEXT: ret i32 [[RET]]396;397entry:398 %local = alloca i32399 call void @capture(ptr %local)400 br label %loop401 402loop:403 %j = phi i32 [ 0, %entry ], [ %next, %loop ]404 %throwaway = call i32 @opaque(i32 %j)405 %x = load i32, ptr %local406 %x2 = call i32 @opaque(i32 %x)407 store i32 %x2, ptr %local408 %next = add i32 %j, 1409 %cond = icmp eq i32 %next, 0410 br i1 %cond, label %exit, label %loop411 412exit:413 %ret = load i32, ptr %local414 ret i32 %ret415}416 417 418; If the store is "guaranteed modulo exceptions", and the load depends on419; control flow, we can only promote if the pointer is otherwise known to be420; dereferenceable421define i32 @test9() {422; CHECK-LABEL: define i32 @test9() {423; CHECK-NEXT: [[ENTRY:.*]]:424; CHECK-NEXT: [[LOCAL:%.*]] = alloca i32, align 4425; CHECK-NEXT: call void @capture(ptr [[LOCAL]])426; CHECK-NEXT: [[LOCAL_PROMOTED:%.*]] = load i32, ptr [[LOCAL]], align 4427; CHECK-NEXT: br label %[[LOOP:.*]]428; CHECK: [[LOOP]]:429; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[LOCAL_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[ELSE:.*]] ]430; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[ELSE]] ]431; CHECK-NEXT: [[J2:%.*]] = call i32 @opaque(i32 [[J]])432; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[J2]], 0433; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[ELSE]]434; CHECK: [[IF]]:435; CHECK-NEXT: br label %[[ELSE]]436; CHECK: [[ELSE]]:437; CHECK-NEXT: [[X2]] = phi i32 [ 0, %[[LOOP]] ], [ [[X21]], %[[IF]] ]438; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1439; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0440; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]441; CHECK: [[EXIT]]:442; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[ELSE]] ]443; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr [[LOCAL]], align 4444; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[LOCAL]], align 4445; CHECK-NEXT: ret i32 [[RET]]446;447entry:448 %local = alloca i32449 call void @capture(ptr %local)450 br label %loop451 452loop:453 %j = phi i32 [ 0, %entry ], [ %next, %else ]454 %j2 = call i32 @opaque(i32 %j)455 %cmp = icmp eq i32 %j2, 0456 br i1 %cmp, label %if, label %else457 458if:459 %x = load i32, ptr %local460 br label %else461 462else:463 %x2 = phi i32 [ 0, %loop ], [ %x, %if]464 store i32 %x2, ptr %local465 %next = add i32 %j, 1466 %cond = icmp eq i32 %next, 0467 br i1 %cond, label %exit, label %loop468 469exit:470 %ret = load i32, ptr %local471 ret i32 %ret472}473 474define i32 @test9bad(i32 %i) {475; CHECK-LABEL: define i32 @test9bad(476; CHECK-SAME: i32 [[I:%.*]]) {477; CHECK-NEXT: [[ENTRY:.*]]:478; CHECK-NEXT: [[LOCAL:%.*]] = alloca i32, align 4479; CHECK-NEXT: call void @capture(ptr [[LOCAL]])480; CHECK-NEXT: [[NOTDEREF:%.*]] = getelementptr i32, ptr [[LOCAL]], i32 [[I]]481; CHECK-NEXT: br label %[[LOOP:.*]]482; CHECK: [[LOOP]]:483; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[ELSE:.*]] ]484; CHECK-NEXT: [[J2:%.*]] = call i32 @opaque(i32 [[J]])485; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[J2]], 0486; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[ELSE]]487; CHECK: [[IF]]:488; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[NOTDEREF]], align 4489; CHECK-NEXT: br label %[[ELSE]]490; CHECK: [[ELSE]]:491; CHECK-NEXT: [[X2:%.*]] = phi i32 [ 0, %[[LOOP]] ], [ [[X]], %[[IF]] ]492; CHECK-NEXT: store i32 [[X2]], ptr [[NOTDEREF]], align 4493; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1494; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0495; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]496; CHECK: [[EXIT]]:497; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[NOTDEREF]], align 4498; CHECK-NEXT: ret i32 [[RET]]499;500entry:501 %local = alloca i32502 call void @capture(ptr %local)503 %notderef = getelementptr i32, ptr %local, i32 %i504 br label %loop505 506loop:507 %j = phi i32 [ 0, %entry ], [ %next, %else ]508 %j2 = call i32 @opaque(i32 %j)509 %cmp = icmp eq i32 %j2, 0510 br i1 %cmp, label %if, label %else511 512if:513 %x = load i32, ptr %notderef514 br label %else515 516else:517 %x2 = phi i32 [ 0, %loop ], [ %x, %if]518 store i32 %x2, ptr %notderef519 %next = add i32 %j, 1520 %cond = icmp eq i32 %next, 0521 br i1 %cond, label %exit, label %loop522 523exit:524 %ret = load i32, ptr %notderef525 ret i32 %ret526}527 528define void @test10(i32 %i) {529; CHECK-LABEL: define void @test10(530; CHECK-SAME: i32 [[I:%.*]]) {531; CHECK-NEXT: [[ENTRY:.*]]:532; CHECK-NEXT: [[X_PROMOTED:%.*]] = load atomic i32, ptr @X unordered, align 4533; CHECK-NEXT: br label %[[LOOP:.*]]534; CHECK: [[LOOP]]:535; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[X_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[LOOP]] ]536; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ]537; CHECK-NEXT: [[X2]] = add i32 [[X21]], 1538; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1539; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0540; CHECK-NEXT: br i1 [[COND]], label %[[OUT:.*]], label %[[LOOP]]541; CHECK: [[OUT]]:542; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[LOOP]] ]543; CHECK-NEXT: store atomic i32 [[X2_LCSSA]], ptr @X unordered, align 4544; CHECK-NEXT: ret void545;546Entry:547 br label %Loop548 549 550Loop: ; preds = %Loop, %0551 %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ] ; <i32> [#uses=1]552 %x = load atomic i32, ptr @X unordered, align 4553 %x2 = add i32 %x, 1554 store atomic i32 %x2, ptr @X unordered, align 4555 %Next = add i32 %j, 1556 %cond = icmp eq i32 %Next, 0557 br i1 %cond, label %Out, label %Loop558 559Out:560 ret void561 562}563 564; Early exit is known not to be taken on first iteration and thus doesn't565; effect whether load is known to execute.566define void @test11(i32 %i) {567; CHECK-LABEL: define void @test11(568; CHECK-SAME: i32 [[I:%.*]]) {569; CHECK-NEXT: [[ENTRY:.*]]:570; CHECK-NEXT: [[X_PROMOTED:%.*]] = load i32, ptr @X, align 4571; CHECK-NEXT: br label %[[LOOP:.*]]572; CHECK: [[LOOP]]:573; CHECK-NEXT: [[X21:%.*]] = phi i32 [ [[X_PROMOTED]], %[[ENTRY]] ], [ [[X2:%.*]], %[[BODY:.*]] ]574; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[BODY]] ]575; CHECK-NEXT: [[EARLY_TEST:%.*]] = icmp ult i32 [[J]], 32576; CHECK-NEXT: br i1 [[EARLY_TEST]], label %[[BODY]], label %[[EARLY:.*]]577; CHECK: [[BODY]]:578; CHECK-NEXT: [[X2]] = add i32 [[X21]], 1579; CHECK-NEXT: [[NEXT]] = add i32 [[J]], 1580; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[NEXT]], 0581; CHECK-NEXT: br i1 [[COND]], label %[[OUT:.*]], label %[[LOOP]]582; CHECK: [[EARLY]]:583; CHECK-NEXT: [[X21_LCSSA:%.*]] = phi i32 [ [[X21]], %[[LOOP]] ]584; CHECK-NEXT: store i32 [[X21_LCSSA]], ptr @X, align 4585; CHECK-NEXT: ret void586; CHECK: [[OUT]]:587; CHECK-NEXT: [[X2_LCSSA:%.*]] = phi i32 [ [[X2]], %[[BODY]] ]588; CHECK-NEXT: store i32 [[X2_LCSSA]], ptr @X, align 4589; CHECK-NEXT: ret void590;591Entry:592 br label %Loop593 594 595Loop: ; preds = %Loop, %0596 %j = phi i32 [ 0, %Entry ], [ %Next, %body ] ; <i32> [#uses=1]597 %early.test = icmp ult i32 %j, 32598 br i1 %early.test, label %body, label %Early599body:600 %x = load i32, ptr @X ; <i32> [#uses=1]601 %x2 = add i32 %x, 1 ; <i32> [#uses=1]602 store i32 %x2, ptr @X603 %Next = add i32 %j, 1 ; <i32> [#uses=2]604 %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]605 br i1 %cond, label %Out, label %Loop606 607Early:608 ret void609Out:610 ret void611 612}613 614define i8 @test_hoistable_existing_load_sinkable_store_writeonly(ptr dereferenceable(8) %ptr, i8 %start) writeonly {615; CHECK: Function Attrs: memory(write)616; CHECK-LABEL: define i8 @test_hoistable_existing_load_sinkable_store_writeonly(617; CHECK-SAME: ptr dereferenceable(8) [[PTR:%.*]], i8 [[START:%.*]]) #[[ATTR1:[0-9]+]] {618; CHECK-NEXT: [[ENTRY:.*]]:619; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i8, ptr [[PTR]], align 1620; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]621; CHECK: [[LOOP_HEADER]]:622; CHECK-NEXT: [[INC1:%.*]] = phi i8 [ [[PTR_PROMOTED]], %[[ENTRY]] ], [ [[INC1]], %[[LOOP_LATCH:.*]] ]623; CHECK-NEXT: [[I:%.*]] = phi i8 [ [[START]], %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP_LATCH]] ]624; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], 4625; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]626; CHECK: [[LOOP_LATCH]]:627; CHECK-NEXT: store i8 [[INC1]], ptr [[PTR]], align 1628; CHECK-NEXT: [[ADD]] = add i8 [[I]], [[INC1]]629; CHECK-NEXT: br label %[[LOOP_HEADER]]630; CHECK: [[EXIT]]:631; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i8 [ [[I]], %[[LOOP_HEADER]] ]632; CHECK-NEXT: ret i8 [[I_LCSSA]]633;634entry:635 br label %loop.header636 637loop.header:638 %i = phi i8 [ %start, %entry ], [ %add, %loop.latch ]639 %cmp = icmp ult i8 %i, 4640 br i1 %cmp, label %loop.latch, label %exit641 642loop.latch:643 %div = sdiv i8 %i, 3644 %inc = load i8, ptr %ptr645 store i8 %inc, ptr %ptr646 %add = add i8 %i, %inc647 br label %loop.header648 649exit:650 ret i8 %i651}652 653@glb = external global i8, align 1654 655; Test case for PR51248.656define void @test_sink_store_only() writeonly {657; CHECK: Function Attrs: memory(write)658; CHECK-LABEL: define void @test_sink_store_only(659; CHECK-SAME: ) #[[ATTR1]] {660; CHECK-NEXT: [[ENTRY:.*]]:661; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]662; CHECK: [[LOOP_HEADER]]:663; CHECK-NEXT: [[DIV1:%.*]] = phi i8 [ poison, %[[ENTRY]] ], [ [[DIV:%.*]], %[[LOOP_LATCH:.*]] ]664; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP_LATCH]] ]665; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], 4666; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]667; CHECK: [[LOOP_LATCH]]:668; CHECK-NEXT: [[DIV]] = sdiv i8 [[I]], 3669; CHECK-NEXT: [[ADD]] = add i8 [[I]], 4670; CHECK-NEXT: br label %[[LOOP_HEADER]]671; CHECK: [[EXIT]]:672; CHECK-NEXT: [[DIV1_LCSSA:%.*]] = phi i8 [ [[DIV1]], %[[LOOP_HEADER]] ]673; CHECK-NEXT: store i8 [[DIV1_LCSSA]], ptr @glb, align 1674; CHECK-NEXT: ret void675;676entry:677 br label %loop.header678 679loop.header:680 %i = phi i8 [ 0, %entry ], [ %add, %loop.latch ]681 %cmp = icmp ult i8 %i, 4682 br i1 %cmp, label %loop.latch, label %exit683 684loop.latch:685 %div = sdiv i8 %i, 3686 store i8 %div, ptr @glb, align 1687 %add = add i8 %i, 4688 br label %loop.header689 690exit:691 ret void692}693 694define void @test_sink_store_to_local_object_only_loop_must_execute() writeonly {695; CHECK: Function Attrs: memory(write)696; CHECK-LABEL: define void @test_sink_store_to_local_object_only_loop_must_execute(697; CHECK-SAME: ) #[[ATTR1]] {698; CHECK-NEXT: [[ENTRY:.*]]:699; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1700; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]701; CHECK: [[LOOP_HEADER]]:702; CHECK-NEXT: [[DIV1:%.*]] = phi i8 [ poison, %[[ENTRY]] ], [ [[DIV:%.*]], %[[LOOP_LATCH:.*]] ]703; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP_LATCH]] ]704; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], 4705; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]706; CHECK: [[LOOP_LATCH]]:707; CHECK-NEXT: [[DIV]] = sdiv i8 [[I]], 3708; CHECK-NEXT: [[ADD]] = add i8 [[I]], 4709; CHECK-NEXT: br label %[[LOOP_HEADER]]710; CHECK: [[EXIT]]:711; CHECK-NEXT: [[DIV1_LCSSA:%.*]] = phi i8 [ [[DIV1]], %[[LOOP_HEADER]] ]712; CHECK-NEXT: store i8 [[DIV1_LCSSA]], ptr [[A]], align 1713; CHECK-NEXT: ret void714;715entry:716 %a = alloca i8717 br label %loop.header718 719loop.header:720 %i = phi i8 [ 0, %entry ], [ %add, %loop.latch ]721 %cmp = icmp ult i8 %i, 4722 br i1 %cmp, label %loop.latch, label %exit723 724loop.latch:725 %div = sdiv i8 %i, 3726 store i8 %div, ptr %a, align 1727 %add = add i8 %i, 4728 br label %loop.header729 730exit:731 ret void732}733 734; The store in the loop may not execute, so we need to introduce a load in the735; pre-header. Make sure the writeonly attribute is dropped.736define void @test_sink_store_to_local_object_only_loop_may_not_execute(i8 %n) writeonly {737; CHECK: Function Attrs: memory(write)738; CHECK-LABEL: define void @test_sink_store_to_local_object_only_loop_may_not_execute(739; CHECK-SAME: i8 [[N:%.*]]) #[[ATTR1]] {740; CHECK-NEXT: [[ENTRY:.*]]:741; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1742; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i8, ptr [[A]], align 1743; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]744; CHECK: [[LOOP_HEADER]]:745; CHECK-NEXT: [[DIV1:%.*]] = phi i8 [ [[A_PROMOTED]], %[[ENTRY]] ], [ [[DIV:%.*]], %[[LOOP_LATCH:.*]] ]746; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP_LATCH]] ]747; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], [[N]]748; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]749; CHECK: [[LOOP_LATCH]]:750; CHECK-NEXT: [[DIV]] = sdiv i8 [[I]], 3751; CHECK-NEXT: [[ADD]] = add i8 [[I]], 4752; CHECK-NEXT: br label %[[LOOP_HEADER]]753; CHECK: [[EXIT]]:754; CHECK-NEXT: [[DIV1_LCSSA:%.*]] = phi i8 [ [[DIV1]], %[[LOOP_HEADER]] ]755; CHECK-NEXT: store i8 [[DIV1_LCSSA]], ptr [[A]], align 1756; CHECK-NEXT: ret void757;758entry:759 %a = alloca i8760 br label %loop.header761 762loop.header:763 %i = phi i8 [ 0, %entry ], [ %add, %loop.latch ]764 %cmp = icmp ult i8 %i, %n765 br i1 %cmp, label %loop.latch, label %exit766 767loop.latch:768 %div = sdiv i8 %i, 3769 store i8 %div, ptr %a, align 1770 %add = add i8 %i, 4771 br label %loop.header772 773exit:774 ret void775}776 777declare dereferenceable(8) noalias ptr @alloc_writeonly() writeonly778 779define void @test_sink_store_to_noalias_call_object_only_loop_may_not_execute1(i8 %n) writeonly {780; CHECK: Function Attrs: memory(write)781; CHECK-LABEL: define void @test_sink_store_to_noalias_call_object_only_loop_may_not_execute1(782; CHECK-SAME: i8 [[N:%.*]]) #[[ATTR1]] {783; CHECK-NEXT: [[ENTRY:.*]]:784; CHECK-NEXT: [[A:%.*]] = call noalias dereferenceable(8) ptr @alloc_writeonly()785; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i8, ptr [[A]], align 1786; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]787; CHECK: [[LOOP_HEADER]]:788; CHECK-NEXT: [[DIV1:%.*]] = phi i8 [ [[A_PROMOTED]], %[[ENTRY]] ], [ [[DIV:%.*]], %[[LOOP_LATCH:.*]] ]789; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP_LATCH]] ]790; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], [[N]]791; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]792; CHECK: [[LOOP_LATCH]]:793; CHECK-NEXT: [[DIV]] = sdiv i8 [[I]], 3794; CHECK-NEXT: [[ADD]] = add i8 [[I]], 4795; CHECK-NEXT: br label %[[LOOP_HEADER]]796; CHECK: [[EXIT]]:797; CHECK-NEXT: [[DIV1_LCSSA:%.*]] = phi i8 [ [[DIV1]], %[[LOOP_HEADER]] ]798; CHECK-NEXT: store i8 [[DIV1_LCSSA]], ptr [[A]], align 1799; CHECK-NEXT: ret void800;801entry:802 %a = call dereferenceable(8) noalias ptr @alloc_writeonly()803 br label %loop.header804 805loop.header:806 %i = phi i8 [ 0, %entry ], [ %add, %loop.latch ]807 %cmp = icmp ult i8 %i, %n808 br i1 %cmp, label %loop.latch, label %exit809 810loop.latch:811 %div = sdiv i8 %i, 3812 store i8 %div, ptr %a, align 1813 %add = add i8 %i, 4814 br label %loop.header815 816exit:817 ret void818}819 820define void @test_sink_store_only_no_phi_needed() writeonly {821; CHECK: Function Attrs: memory(write)822; CHECK-LABEL: define void @test_sink_store_only_no_phi_needed(823; CHECK-SAME: ) #[[ATTR1]] {824; CHECK-NEXT: [[ENTRY:.*]]:825; CHECK-NEXT: br label %[[LOOP:.*]]826; CHECK: [[LOOP]]:827; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[LOOP]] ]828; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[I]], 4829; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[I]], 3830; CHECK-NEXT: [[ADD]] = add i8 [[I]], 4831; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]832; CHECK: [[EXIT]]:833; CHECK-NEXT: [[DIV_LCSSA:%.*]] = phi i8 [ [[DIV]], %[[LOOP]] ]834; CHECK-NEXT: store i8 [[DIV_LCSSA]], ptr @glb, align 1835; CHECK-NEXT: ret void836;837entry:838 br label %loop839 840loop:841 %i = phi i8 [ 0, %entry ], [ %add, %loop ]842 %cmp = icmp ult i8 %i, 4843 %div = sdiv i8 %i, 3844 store i8 %div, ptr @glb, align 1845 %add = add i8 %i, 4846 br i1 %cmp, label %loop, label %exit847 848exit:849 ret void850}851 852define void @sink_store_lcssa_phis(ptr %ptr, i1 %c) {853; CHECK-LABEL: define void @sink_store_lcssa_phis(854; CHECK-SAME: ptr [[PTR:%.*]], i1 [[C:%.*]]) {855; CHECK-NEXT: [[ENTRY:.*:]]856; CHECK-NEXT: br label %[[LOOP_1_HEADER:.*]]857; CHECK: [[LOOP_1_HEADER]]:858; CHECK-NEXT: br label %[[LOOP_2_HEADER:.*]]859; CHECK: [[LOOP_2_HEADER]]:860; CHECK-NEXT: br i1 false, label %[[LOOP_3_HEADER_PREHEADER:.*]], label %[[LOOP_1_LATCH:.*]]861; CHECK: [[LOOP_3_HEADER_PREHEADER]]:862; CHECK-NEXT: br label %[[LOOP_3_HEADER:.*]]863; CHECK: [[LOOP_3_HEADER]]:864; CHECK-NEXT: [[I_11:%.*]] = phi i32 [ [[I_1:%.*]], %[[LOOP_3_LATCH:.*]] ], [ poison, %[[LOOP_3_HEADER_PREHEADER]] ]865; CHECK-NEXT: [[I_1]] = phi i32 [ 1, %[[LOOP_3_LATCH]] ], [ 0, %[[LOOP_3_HEADER_PREHEADER]] ]866; CHECK-NEXT: br i1 true, label %[[LOOP_3_LATCH]], label %[[LOOP_2_LATCH:.*]]867; CHECK: [[LOOP_3_LATCH]]:868; CHECK-NEXT: br label %[[LOOP_3_HEADER]]869; CHECK: [[LOOP_2_LATCH]]:870; CHECK-NEXT: [[I_11_LCSSA:%.*]] = phi i32 [ [[I_11]], %[[LOOP_3_HEADER]] ]871; CHECK-NEXT: store i32 [[I_11_LCSSA]], ptr [[PTR]], align 4872; CHECK-NEXT: br label %[[LOOP_2_HEADER]]873; CHECK: [[LOOP_1_LATCH]]:874; CHECK-NEXT: br i1 [[C]], label %[[LOOP_1_HEADER]], label %[[EXIT:.*]]875; CHECK: [[EXIT]]:876; CHECK-NEXT: ret void877;878entry:879 br label %loop.1.header880 881loop.1.header:882 br label %loop.2.header883 884loop.2.header:885 br i1 false, label %loop.3.header, label %loop.1.latch886 887loop.3.header:888 %i.1 = phi i32 [ 1, %loop.3.latch ], [ 0, %loop.2.header ]889 br i1 true, label %loop.3.latch, label %loop.2.latch890 891loop.3.latch:892 store i32 %i.1, ptr %ptr, align 4893 br label %loop.3.header894 895loop.2.latch:896 br label %loop.2.header897 898loop.1.latch:899 br i1 %c, label %loop.1.header, label %exit900 901exit:902 ret void903}904 905define void @cond_store_writable_dereferenceable(ptr noalias writable dereferenceable(4) %ptr) {906; CHECK-LABEL: define void @cond_store_writable_dereferenceable(907; CHECK-SAME: ptr noalias writable dereferenceable(4) [[PTR:%.*]]) {908; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i32, ptr [[PTR]], align 4909; CHECK-NEXT: br label %[[LOOP:.*]]910; CHECK: [[LOOP]]:911; CHECK-NEXT: [[V_INC1:%.*]] = phi i32 [ [[V_INC:%.*]], %[[LOOP_LATCH:.*]] ], [ [[PTR_PROMOTED]], [[TMP0:%.*]] ]912; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[V_INC1]], 10913; CHECK-NEXT: br i1 [[C]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]914; CHECK: [[LOOP_LATCH]]:915; CHECK-NEXT: [[V_INC]] = add i32 [[V_INC1]], 1916; CHECK-NEXT: br label %[[LOOP]]917; CHECK: [[EXIT]]:918; CHECK-NEXT: [[V_INC1_LCSSA:%.*]] = phi i32 [ [[V_INC1]], %[[LOOP]] ]919; CHECK-NEXT: store i32 [[V_INC1_LCSSA]], ptr [[PTR]], align 4920; CHECK-NEXT: ret void921;922 br label %loop923 924loop:925 %v = load i32, ptr %ptr926 %c = icmp ult i32 %v, 10927 br i1 %c, label %loop.latch, label %exit928 929loop.latch:930 %v.inc = add i32 %v, 1931 store i32 %v.inc, ptr %ptr932 br label %loop933 934exit:935 ret void936}937 938define void @cond_store_writable_not_sufficiently_dereferenceable(ptr noalias writable dereferenceable(2) %ptr) {939; CHECK-LABEL: define void @cond_store_writable_not_sufficiently_dereferenceable(940; CHECK-SAME: ptr noalias writable dereferenceable(2) [[PTR:%.*]]) {941; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i32, ptr [[PTR]], align 4942; CHECK-NEXT: br label %[[LOOP:.*]]943; CHECK: [[LOOP]]:944; CHECK-NEXT: [[V_INC1:%.*]] = phi i32 [ [[V_INC:%.*]], %[[LOOP_LATCH:.*]] ], [ [[PTR_PROMOTED]], [[TMP0:%.*]] ]945; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[V_INC1]], 10946; CHECK-NEXT: br i1 [[C]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]947; CHECK: [[LOOP_LATCH]]:948; CHECK-NEXT: [[V_INC]] = add i32 [[V_INC1]], 1949; CHECK-NEXT: store i32 [[V_INC]], ptr [[PTR]], align 4950; CHECK-NEXT: br label %[[LOOP]]951; CHECK: [[EXIT]]:952; CHECK-NEXT: ret void953;954 br label %loop955 956loop:957 %v = load i32, ptr %ptr958 %c = icmp ult i32 %v, 10959 br i1 %c, label %loop.latch, label %exit960 961loop.latch:962 %v.inc = add i32 %v, 1963 store i32 %v.inc, ptr %ptr964 br label %loop965 966exit:967 ret void968}969 970!0 = !{!4, !4, i64 0}971!1 = !{!"omnipotent char", !2}972!2 = !{!"Simple C/C++ TBAA"}973!3 = !{!5, !5, i64 0}974!4 = !{!"int", !1}975!5 = !{!"float", !1}976;.977; CHECK: [[INT_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}978; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]]}979; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]]}980; CHECK: [[META3]] = !{!"Simple C/C++ TBAA"}981; CHECK: [[FLOAT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}982; CHECK: [[META5]] = !{!"float", [[META2]]}983;.984