152 lines · plain
1; RUN: opt -S -passes=licm < %s | FileCheck %s2; 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 %s3 4declare void @use_nothrow(i64 %a) nounwind5declare void @use(i64 %a)6declare void @maythrow()7 8define void @nothrow(i64 %x, i64 %y, ptr %cond) {9; CHECK-LABEL: nothrow10; CHECK-LABEL: entry11; CHECK: %div = udiv i64 %x, %y12; CHECK-LABEL: loop13; CHECK: call void @use_nothrow(i64 %div)14entry:15 br label %loop16 17loop: ; preds = %entry, %for.inc18 %div = udiv i64 %x, %y19 br label %loop220 21loop2:22 call void @use_nothrow(i64 %div)23 br label %loop24}25 26; The udiv is guarantee to execute if the loop is27define void @throw_header_after(i64 %x, i64 %y, ptr %cond) {28; CHECK-LABEL: throw_header_after29; CHECK: %div = udiv i64 %x, %y30; CHECK-LABEL: loop31; CHECK: call void @use(i64 %div)32entry:33 br label %loop34 35loop: ; preds = %entry, %for.inc36 %div = udiv i64 %x, %y37 call void @use(i64 %div)38 br label %loop39}40define void @throw_header_after_rec(ptr %xp, ptr %yp, ptr %cond) {41; CHECK-LABEL: throw_header_after_rec42; CHECK: %x = load i64, ptr %xp43; CHECK: %y = load i64, ptr %yp44; CHECK: %div = udiv i64 %x, %y45; CHECK-LABEL: loop46; CHECK: call void @use(i64 %div)47entry:48 br label %loop49 50loop: ; preds = %entry, %for.inc51 %x = load i64, ptr %xp52 %y = load i64, ptr %yp53 %div = udiv i64 %x, %y54 call void @use(i64 %div) readonly55 br label %loop56}57 58; Similiar to the above, but the hoistable instruction (%y in this case)59; happens not to be the first instruction in the block.60define void @throw_header_after_nonfirst(ptr %xp, ptr %yp, ptr %cond) {61; CHECK-LABEL: throw_header_after_nonfirst62; CHECK: %y = load i64, ptr %yp63; CHECK-LABEL: loop64; CHECK: %x = load i64, ptr %gep65; CHECK: %div = udiv i64 %x, %y66; CHECK: call void @use(i64 %div)67entry:68 br label %loop69 70loop: ; preds = %entry, %for.inc71 %iv = phi i64 [0, %entry], [%div, %loop]72 %gep = getelementptr i64, ptr %xp, i64 %iv73 %x = load i64, ptr %gep74 %y = load i64, ptr %yp75 %div = udiv i64 %x, %y76 call void @use(i64 %div) readonly77 br label %loop78}79 80; Negative test81define void @throw_header_before(i64 %x, i64 %y, ptr %cond) {82; CHECK-LABEL: throw_header_before83; CHECK-LABEL: loop84; CHECK: %div = udiv i64 %x, %y85; CHECK: call void @use(i64 %div)86entry:87 br label %loop88 89loop: ; preds = %entry, %for.inc90 call void @maythrow()91 %div = udiv i64 %x, %y92 call void @use(i64 %div)93 br label %loop94}95 96; The header is known no throw, but the loop is not. We can97; still lift out of the header.98define void @nothrow_header(i64 %x, i64 %y, i1 %cond) {99; CHECK-LABEL: nothrow_header100; CHECK-LABEL: entry101; CHECK: %div = udiv i64 %x, %y102; CHECK-LABEL: loop103 ; CHECK: call void @use(i64 %div)104entry:105 br label %loop106loop: ; preds = %entry, %for.inc107 %div = udiv i64 %x, %y108 br i1 %cond, label %loop-if, label %exit109loop-if:110 call void @use(i64 %div)111 br label %loop112exit:113 ret void114}115 116; Positive test - can hoist something that happens before thrower.117define void @nothrow_header_pos(i64 %x, i64 %y, i1 %cond) {118; CHECK-LABEL: nothrow_header_pos119; CHECK-LABEL: entry120; CHECK: %div = udiv i64 %x, %y121; CHECK-LABEL: loop122; CHECK: call void @use(i64 %div)123entry:124 br label %loop125loop: ; preds = %entry, %for.inc126 br label %loop-if127loop-if:128 %div = udiv i64 %x, %y129 call void @use(i64 %div)130 br label %loop131}132 133 134; Negative test - can't move out of throwing block135define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) {136; CHECK-LABEL: nothrow_header_neg137; CHECK-LABEL: entry138; CHECK-LABEL: loop139; CHECK: call void @maythrow()140; CHECK: %div = udiv i64 %x, %y141; CHECK: call void @use(i64 %div)142entry:143 br label %loop144loop: ; preds = %entry, %for.inc145 br label %loop-if146loop-if:147 call void @maythrow()148 %div = udiv i64 %x, %y149 call void @use(i64 %div)150 br label %loop151}152