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