brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.4 KiB · aa8c8bb Raw
591 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=licm %s | FileCheck %s3; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s4 5declare i32 @load(ptr %p) argmemonly readonly nounwind6 7define void @test_load(ptr noalias %loc, ptr noalias %sink) {8; CHECK-LABEL: define void @test_load(9; CHECK-SAME: ptr noalias [[LOC:%.*]], ptr noalias [[SINK:%.*]]) {10; CHECK-NEXT:  [[ENTRY:.*]]:11; CHECK-NEXT:    [[RET:%.*]] = call i32 @load(ptr [[LOC]])12; CHECK-NEXT:    br label %[[LOOP:.*]]13; CHECK:       [[LOOP]]:14; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]15; CHECK-NEXT:    store volatile i32 [[RET]], ptr [[SINK]], align 416; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 117; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 20018; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]19; CHECK:       [[EXIT]]:20; CHECK-NEXT:    ret void21;22entry:23  br label %loop24 25loop:26  %iv = phi i32 [0, %entry], [%iv.next, %loop]27  %ret = call i32 @load(ptr %loc)28  store volatile i32 %ret, ptr %sink29  %iv.next = add i32 %iv, 130  %cmp = icmp slt i32 %iv, 20031  br i1 %cmp, label %loop, label %exit32 33exit:34  ret void35}36 37declare i32 @spec(ptr %p, ptr %q) readonly argmemonly nounwind speculatable38 39; We should strip the dereferenceable callsite attribute on spec call's argument since it is40; can cause UB in the speculatable call when hoisted to preheader.41; However, we need not strip the nonnull attribute since it just propagates42; poison if the parameter was indeed null.43define void @test_strip_attribute(ptr noalias %loc, ptr noalias %sink, ptr %q) {44; CHECK-LABEL: define void @test_strip_attribute(45; CHECK-SAME: ptr noalias [[LOC:%.*]], ptr noalias [[SINK:%.*]], ptr [[Q:%.*]]) {46; CHECK-NEXT:  [[ENTRY:.*]]:47; CHECK-NEXT:    [[RET:%.*]] = call i32 @load(ptr [[LOC]])48; CHECK-NEXT:    [[NULLCHK:%.*]] = icmp eq ptr [[Q]], null49; CHECK-NEXT:    [[RET2:%.*]] = call i32 @spec(ptr nonnull [[Q]], ptr [[LOC]])50; CHECK-NEXT:    br label %[[LOOP:.*]]51; CHECK:       [[LOOP]]:52; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[ISNULL:.*]] ]53; CHECK-NEXT:    br i1 [[NULLCHK]], label %[[ISNULL]], label %[[NONNULLBB:.*]]54; CHECK:       [[NONNULLBB]]:55; CHECK-NEXT:    br label %[[ISNULL]]56; CHECK:       [[ISNULL]]:57; CHECK-NEXT:    store volatile i32 [[RET]], ptr [[SINK]], align 458; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 159; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 20060; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]61; CHECK:       [[EXIT]]:62; CHECK-NEXT:    ret void63;64entry:65  br label %loop66 67loop:68  %iv = phi i32 [0, %entry], [%iv.next, %isnull ]69  %ret = call i32 @load(ptr %loc)70  %nullchk = icmp eq ptr %q, null71  br i1 %nullchk, label %isnull, label %nonnullbb72 73nonnullbb:74  %ret2 = call i32 @spec(ptr nonnull %q, ptr dereferenceable(12) %loc)75  br label %isnull76 77isnull:78  store volatile i32 %ret, ptr %sink79  %iv.next = add i32 %iv, 180  %cmp = icmp slt i32 %iv, 20081  br i1 %cmp, label %loop, label %exit82 83exit:84  ret void85}86 87declare i32 @load_not_argmemonly() readonly nounwind willreturn88 89define void @test_load_not_argmemonly(ptr noalias %sink) {90; CHECK-LABEL: define void @test_load_not_argmemonly(91; CHECK-SAME: ptr noalias [[SINK:%.*]]) {92; CHECK-NEXT:  [[ENTRY:.*]]:93; CHECK-NEXT:    [[RET:%.*]] = call i32 @load_not_argmemonly()94; CHECK-NEXT:    store i32 [[RET]], ptr [[SINK]], align 495; CHECK-NEXT:    br label %[[LOOP:.*]]96; CHECK:       [[LOOP]]:97; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]98; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 199; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200100; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]101; CHECK:       [[EXIT]]:102; CHECK-NEXT:    ret void103;104entry:105  br label %loop106 107loop:108  %iv = phi i32 [0, %entry], [%iv.next, %loop]109  %ret = call i32 @load_not_argmemonly()110  store i32 %ret, ptr %sink111  %iv.next = add i32 %iv, 1112  %cmp = icmp slt i32 %iv, 200113  br i1 %cmp, label %loop, label %exit114 115exit:116  ret void117}118 119declare void @store(i32 %val, ptr %p) argmemonly writeonly nounwind120 121; loop invariant calls to writeonly functions such as the above122; should be hoisted123define void @test(ptr %loc) {124; CHECK-LABEL: define void @test(125; CHECK-SAME: ptr [[LOC:%.*]]) {126; CHECK-NEXT:  [[ENTRY:.*]]:127; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])128; CHECK-NEXT:    br label %[[LOOP:.*]]129; CHECK:       [[LOOP]]:130; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]131; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1132; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200133; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]134; CHECK:       [[EXIT]]:135; CHECK-NEXT:    ret void136;137entry:138  br label %loop139 140loop:141  %iv = phi i32 [0, %entry], [%iv.next, %loop]142  call void @store(i32 0, ptr %loc)143  %iv.next = add i32 %iv, 1144  %cmp = icmp slt i32 %iv, 200145  br i1 %cmp, label %loop, label %exit146 147exit:148  ret void149}150 151define void @test_multiexit(ptr %loc, i1 %earlycnd) {152; CHECK-LABEL: define void @test_multiexit(153; CHECK-SAME: ptr [[LOC:%.*]], i1 [[EARLYCND:%.*]]) {154; CHECK-NEXT:  [[ENTRY:.*]]:155; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])156; CHECK-NEXT:    br label %[[LOOP:.*]]157; CHECK:       [[LOOP]]:158; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[BACKEDGE:.*]] ]159; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1160; CHECK-NEXT:    br i1 [[EARLYCND]], label %[[EXIT1:.*]], label %[[BACKEDGE]]161; CHECK:       [[BACKEDGE]]:162; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200163; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT2:.*]]164; CHECK:       [[EXIT1]]:165; CHECK-NEXT:    ret void166; CHECK:       [[EXIT2]]:167; CHECK-NEXT:    ret void168;169entry:170  br label %loop171 172loop:173  %iv = phi i32 [0, %entry], [%iv.next, %backedge]174  call void @store(i32 0, ptr %loc)175  %iv.next = add i32 %iv, 1176  br i1 %earlycnd, label %exit1, label %backedge177 178backedge:179  %cmp = icmp slt i32 %iv, 200180  br i1 %cmp, label %loop, label %exit2181 182exit1:183  ret void184exit2:185  ret void186}187 188; cannot be hoisted because the two pointers can alias one another189define void @neg_two_pointer(ptr %loc, ptr %otherloc) {190; CHECK-LABEL: define void @neg_two_pointer(191; CHECK-SAME: ptr [[LOC:%.*]], ptr [[OTHERLOC:%.*]]) {192; CHECK-NEXT:  [[ENTRY:.*]]:193; CHECK-NEXT:    br label %[[LOOP:.*]]194; CHECK:       [[LOOP]]:195; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]196; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])197; CHECK-NEXT:    call void @store(i32 1, ptr [[OTHERLOC]])198; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1199; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200200; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]201; CHECK:       [[EXIT]]:202; CHECK-NEXT:    ret void203;204entry:205  br label %loop206 207loop:208  %iv = phi i32 [0, %entry], [%iv.next, %loop]209  call void @store(i32 0, ptr %loc)210  call void @store(i32 1, ptr %otherloc)211  %iv.next = add i32 %iv, 1212  %cmp = icmp slt i32 %iv, 200213  br i1 %cmp, label %loop, label %exit214exit:215  ret void216}217 218; hoisted due to pointers not aliasing219define void @two_pointer_noalias(ptr noalias %loc, ptr noalias %otherloc) {220; CHECK-LABEL: define void @two_pointer_noalias(221; CHECK-SAME: ptr noalias [[LOC:%.*]], ptr noalias [[OTHERLOC:%.*]]) {222; CHECK-NEXT:  [[ENTRY:.*]]:223; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])224; CHECK-NEXT:    call void @store(i32 1, ptr [[OTHERLOC]])225; CHECK-NEXT:    br label %[[LOOP:.*]]226; CHECK:       [[LOOP]]:227; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]228; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1229; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200230; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]231; CHECK:       [[EXIT]]:232; CHECK-NEXT:    ret void233;234entry:235  br label %loop236 237loop:238  %iv = phi i32 [0, %entry], [%iv.next, %loop]239  call void @store(i32 0, ptr %loc)240  call void @store(i32 1, ptr %otherloc)241  %iv.next = add i32 %iv, 1242  %cmp = icmp slt i32 %iv, 200243  br i1 %cmp, label %loop, label %exit244exit:245  ret void246}247 248; when there's a conflicting read, store call should not be hoisted249define void @neg_conflicting_read(ptr noalias %loc, ptr noalias %otherloc) {250; CHECK-LABEL: define void @neg_conflicting_read(251; CHECK-SAME: ptr noalias [[LOC:%.*]], ptr noalias [[OTHERLOC:%.*]]) {252; CHECK-NEXT:  [[ENTRY:.*]]:253; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])254; CHECK-NEXT:    br label %[[LOOP:.*]]255; CHECK:       [[LOOP]]:256; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]257; CHECK-NEXT:    call void @load(i32 0, ptr [[LOC]])258; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])259; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1260; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200261; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]262; CHECK:       [[EXIT]]:263; CHECK-NEXT:    ret void264;265entry:266  call void @store(i32 0, ptr %loc)267  br label %loop268loop:269  %iv = phi i32 [0, %entry], [%iv.next, %loop]270  call void @load(i32 0, ptr %loc)271  call void @store(i32 0, ptr %loc)272  %iv.next = add i32 %iv, 1273  %cmp = icmp slt i32 %iv, 200274  br i1 %cmp, label %loop, label %exit275exit:276  ret void277}278 279define void @neg_lv_value(ptr %loc) {280; CHECK-LABEL: define void @neg_lv_value(281; CHECK-SAME: ptr [[LOC:%.*]]) {282; CHECK-NEXT:  [[ENTRY:.*]]:283; CHECK-NEXT:    br label %[[LOOP:.*]]284; CHECK:       [[LOOP]]:285; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]286; CHECK-NEXT:    call void @store(i32 [[IV]], ptr [[LOC]])287; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1288; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200289; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]290; CHECK:       [[EXIT]]:291; CHECK-NEXT:    ret void292;293entry:294  br label %loop295 296loop:297  %iv = phi i32 [0, %entry], [%iv.next, %loop]298  call void @store(i32 %iv, ptr %loc)299  %iv.next = add i32 %iv, 1300  %cmp = icmp slt i32 %iv, 200301  br i1 %cmp, label %loop, label %exit302 303exit:304  ret void305}306 307define void @neg_lv_addr(ptr %loc) {308; CHECK-LABEL: define void @neg_lv_addr(309; CHECK-SAME: ptr [[LOC:%.*]]) {310; CHECK-NEXT:  [[ENTRY:.*]]:311; CHECK-NEXT:    br label %[[LOOP:.*]]312; CHECK:       [[LOOP]]:313; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]314; CHECK-NEXT:    [[P:%.*]] = getelementptr i32, ptr [[LOC]], i32 [[IV]]315; CHECK-NEXT:    call void @store(i32 0, ptr [[P]])316; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1317; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200318; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]319; CHECK:       [[EXIT]]:320; CHECK-NEXT:    ret void321;322entry:323  br label %loop324 325loop:326  %iv = phi i32 [0, %entry], [%iv.next, %loop]327  %p = getelementptr i32, ptr %loc, i32 %iv328  call void @store(i32 0, ptr %p)329  %iv.next = add i32 %iv, 1330  %cmp = icmp slt i32 %iv, 200331  br i1 %cmp, label %loop, label %exit332 333exit:334  ret void335}336 337define void @neg_mod(ptr %loc) {338; CHECK-LABEL: define void @neg_mod(339; CHECK-SAME: ptr [[LOC:%.*]]) {340; CHECK-NEXT:  [[ENTRY:.*]]:341; CHECK-NEXT:    br label %[[LOOP:.*]]342; CHECK:       [[LOOP]]:343; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]344; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])345; CHECK-NEXT:    store i32 [[IV]], ptr [[LOC]], align 4346; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1347; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200348; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]349; CHECK:       [[EXIT]]:350; CHECK-NEXT:    ret void351;352entry:353  br label %loop354 355loop:356  %iv = phi i32 [0, %entry], [%iv.next, %loop]357  call void @store(i32 0, ptr %loc)358  store i32 %iv, ptr %loc359  %iv.next = add i32 %iv, 1360  %cmp = icmp slt i32 %iv, 200361  br i1 %cmp, label %loop, label %exit362 363exit:364  ret void365}366 367define void @neg_ref(ptr %loc) {368; CHECK-LABEL: define void @neg_ref(369; CHECK-SAME: ptr [[LOC:%.*]]) {370; CHECK-NEXT:  [[ENTRY:.*]]:371; CHECK-NEXT:    br label %[[LOOP:.*]]372; CHECK:       [[LOOP]]:373; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[BACKEDGE:.*]] ]374; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])375; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[LOC]], align 4376; CHECK-NEXT:    [[EARLYCND:%.*]] = icmp eq i32 [[V]], 198377; CHECK-NEXT:    br i1 [[EARLYCND]], label %[[EXIT1:.*]], label %[[BACKEDGE]]378; CHECK:       [[BACKEDGE]]:379; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1380; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200381; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT2:.*]]382; CHECK:       [[EXIT1]]:383; CHECK-NEXT:    ret void384; CHECK:       [[EXIT2]]:385; CHECK-NEXT:    ret void386;387entry:388  br label %loop389 390loop:391  %iv = phi i32 [0, %entry], [%iv.next, %backedge]392  call void @store(i32 0, ptr %loc)393  %v = load i32, ptr %loc394  %earlycnd = icmp eq i32 %v, 198395  br i1 %earlycnd, label %exit1, label %backedge396 397backedge:398  %iv.next = add i32 %iv, 1399  %cmp = icmp slt i32 %iv, 200400  br i1 %cmp, label %loop, label %exit2401 402exit1:403  ret void404exit2:405  ret void406}407 408declare void @modref()409 410define void @neg_modref(ptr %loc) {411; CHECK-LABEL: define void @neg_modref(412; CHECK-SAME: ptr [[LOC:%.*]]) {413; CHECK-NEXT:  [[ENTRY:.*]]:414; CHECK-NEXT:    br label %[[LOOP:.*]]415; CHECK:       [[LOOP]]:416; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]417; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])418; CHECK-NEXT:    call void @modref()419; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1420; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200421; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]422; CHECK:       [[EXIT]]:423; CHECK-NEXT:    ret void424;425entry:426  br label %loop427 428loop:429  %iv = phi i32 [0, %entry], [%iv.next, %loop]430  call void @store(i32 0, ptr %loc)431  call void @modref()432  %iv.next = add i32 %iv, 1433  %cmp = icmp slt i32 %iv, 200434  br i1 %cmp, label %loop, label %exit435 436exit:437  ret void438}439 440define void @neg_fence(ptr %loc) {441; CHECK-LABEL: define void @neg_fence(442; CHECK-SAME: ptr [[LOC:%.*]]) {443; CHECK-NEXT:  [[ENTRY:.*]]:444; CHECK-NEXT:    br label %[[LOOP:.*]]445; CHECK:       [[LOOP]]:446; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]447; CHECK-NEXT:    call void @store(i32 0, ptr [[LOC]])448; CHECK-NEXT:    fence seq_cst449; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1450; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200451; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]452; CHECK:       [[EXIT]]:453; CHECK-NEXT:    ret void454;455entry:456  br label %loop457 458loop:459  %iv = phi i32 [0, %entry], [%iv.next, %loop]460  call void @store(i32 0, ptr %loc)461  fence seq_cst462  %iv.next = add i32 %iv, 1463  %cmp = icmp slt i32 %iv, 200464  br i1 %cmp, label %loop, label %exit465 466exit:467  ret void468}469 470declare void @not_nounwind(i32 %v, ptr %p) writeonly argmemonly471declare void @not_argmemonly(i32 %v, ptr %p) writeonly nounwind472declare void @not_writeonly(i32 %v, ptr %p) argmemonly nounwind473 474define void @neg_not_nounwind(ptr %loc) {475; CHECK-LABEL: define void @neg_not_nounwind(476; CHECK-SAME: ptr [[LOC:%.*]]) {477; CHECK-NEXT:  [[ENTRY:.*]]:478; CHECK-NEXT:    br label %[[LOOP:.*]]479; CHECK:       [[LOOP]]:480; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]481; CHECK-NEXT:    call void @not_nounwind(i32 0, ptr [[LOC]])482; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1483; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200484; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]485; CHECK:       [[EXIT]]:486; CHECK-NEXT:    ret void487;488entry:489  br label %loop490 491loop:492  %iv = phi i32 [0, %entry], [%iv.next, %loop]493  call void @not_nounwind(i32 0, ptr %loc)494  %iv.next = add i32 %iv, 1495  %cmp = icmp slt i32 %iv, 200496  br i1 %cmp, label %loop, label %exit497 498exit:499  ret void500}501 502; when the call is not argmemonly and is not the only memory access we503; do not hoist504define void @neg_not_argmemonly(ptr %loc, ptr %loc2) {505; CHECK-LABEL: define void @neg_not_argmemonly(506; CHECK-SAME: ptr [[LOC:%.*]], ptr [[LOC2:%.*]]) {507; CHECK-NEXT:  [[ENTRY:.*]]:508; CHECK-NEXT:    br label %[[LOOP:.*]]509; CHECK:       [[LOOP]]:510; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]511; CHECK-NEXT:    call void @not_argmemonly(i32 0, ptr [[LOC]])512; CHECK-NEXT:    call void @load(i32 0, ptr [[LOC2]])513; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1514; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200515; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]516; CHECK:       [[EXIT]]:517; CHECK-NEXT:    ret void518;519entry:520  br label %loop521 522loop:523  %iv = phi i32 [0, %entry], [%iv.next, %loop]524  call void @not_argmemonly(i32 0, ptr %loc)525  call void @load(i32 0, ptr %loc2)526  %iv.next = add i32 %iv, 1527  %cmp = icmp slt i32 %iv, 200528  br i1 %cmp, label %loop, label %exit529 530exit:531  ret void532}533 534; when the call is not argmemonly and is only memory access we hoist it535define void @not_argmemonly_hoisted(ptr %loc, ptr %loc2) {536; CHECK-LABEL: define void @not_argmemonly_hoisted(537; CHECK-SAME: ptr [[LOC:%.*]], ptr [[LOC2:%.*]]) {538; CHECK-NEXT:  [[ENTRY:.*]]:539; CHECK-NEXT:    call void @not_argmemonly(i32 0, ptr [[LOC]])540; CHECK-NEXT:    br label %[[LOOP:.*]]541; CHECK:       [[LOOP]]:542; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]543; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1544; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200545; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]546; CHECK:       [[EXIT]]:547; CHECK-NEXT:    ret void548;549entry:550  br label %loop551 552loop:553  %iv = phi i32 [0, %entry], [%iv.next, %loop]554  call void @not_argmemonly(i32 0, ptr %loc)555  %iv.next = add i32 %iv, 1556  %cmp = icmp slt i32 %iv, 200557  br i1 %cmp, label %loop, label %exit558 559exit:560  ret void561}562 563define void @neg_not_writeonly(ptr %loc) {564; CHECK-LABEL: define void @neg_not_writeonly(565; CHECK-SAME: ptr [[LOC:%.*]]) {566; CHECK-NEXT:  [[ENTRY:.*]]:567; CHECK-NEXT:    br label %[[LOOP:.*]]568; CHECK:       [[LOOP]]:569; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]570; CHECK-NEXT:    call void @not_writeonly(i32 0, ptr [[LOC]])571; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1572; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV]], 200573; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]574; CHECK:       [[EXIT]]:575; CHECK-NEXT:    ret void576;577entry:578  br label %loop579 580loop:581  %iv = phi i32 [0, %entry], [%iv.next, %loop]582  call void @not_writeonly(i32 0, ptr %loc)583  %iv.next = add i32 %iv, 1584  %cmp = icmp slt i32 %iv, 200585  br i1 %cmp, label %loop, label %exit586 587exit:588  ret void589}590 591