brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.5 KiB · 3af65df Raw
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