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