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