1; RUN: opt -S -licm < %s | FileCheck %s 2; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s 3 4declare void @use_nothrow(i64 %a) nounwind 5declare void @use(i64 %a) 6 7define void @nothrow(i64 %x, i64 %y, i1* %cond) { 8; CHECK-LABEL: nothrow 9; CHECK-LABEL: entry 10; CHECK: %div = udiv i64 %x, %y 11; CHECK-LABEL: loop 12; CHECK: call void @use_nothrow(i64 %div) 13entry: 14 br label %loop 15 16loop: ; preds = %entry, %for.inc 17 %div = udiv i64 %x, %y 18 br label %loop2 19 20loop2: 21 call void @use_nothrow(i64 %div) 22 br label %loop 23} 24; Negative test 25define void @throw_header(i64 %x, i64 %y, i1* %cond) { 26; CHECK-LABEL: throw_header 27; CHECK-LABEL: loop 28; CHECK: %div = udiv i64 %x, %y 29; CHECK: call void @use(i64 %div) 30entry: 31 br label %loop 32 33loop: ; preds = %entry, %for.inc 34 %div = udiv i64 %x, %y 35 call void @use(i64 %div) 36 br label %loop 37} 38 39; The header is known no throw, but the loop is not. We can 40; still lift out of the header. 41define void @nothrow_header(i64 %x, i64 %y, i1 %cond) { 42; CHECK-LABEL: nothrow_header 43; CHECK-LABEL: entry 44; CHECK: %div = udiv i64 %x, %y 45; CHECK-LABEL: loop 46; CHECK: call void @use(i64 %div) 47entry: 48 br label %loop 49loop: ; preds = %entry, %for.inc 50 %div = udiv i64 %x, %y 51 br i1 %cond, label %loop-if, label %exit 52loop-if: 53 call void @use(i64 %div) 54 br label %loop 55exit: 56 ret void 57} 58; Negative test - can't move out of throwing block 59define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) { 60; CHECK-LABEL: nothrow_header_neg 61; CHECK-LABEL: entry 62; CHECK-LABEL: loop 63; CHECK: %div = udiv i64 %x, %y 64; CHECK: call void @use(i64 %div) 65entry: 66 br label %loop 67loop: ; preds = %entry, %for.inc 68 br label %loop-if 69loop-if: 70 %div = udiv i64 %x, %y 71 call void @use(i64 %div) 72 br label %loop 73} 74