1 ; RUN: opt -S -passes=licm < %s | FileCheck %s
2 ; 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 %s
4 declare void @use_nothrow(i64 %a) nounwind
5 declare void @use(i64 %a)
6 declare void @maythrow()
8 define void @nothrow(i64 %x, i64 %y, ptr %cond) {
11 ; CHECK: %div = udiv i64 %x, %y
13 ; CHECK: call void @use_nothrow(i64 %div)
17 loop: ; preds = %entry, %for.inc
18 %div = udiv i64 %x, %y
22 call void @use_nothrow(i64 %div)
26 ; The udiv is guarantee to execute if the loop is
27 define void @throw_header_after(i64 %x, i64 %y, ptr %cond) {
28 ; CHECK-LABEL: throw_header_after
29 ; CHECK: %div = udiv i64 %x, %y
31 ; CHECK: call void @use(i64 %div)
35 loop: ; preds = %entry, %for.inc
36 %div = udiv i64 %x, %y
37 call void @use(i64 %div)
40 define void @throw_header_after_rec(ptr %xp, ptr %yp, ptr %cond) {
41 ; CHECK-LABEL: throw_header_after_rec
42 ; CHECK: %x = load i64, ptr %xp
43 ; CHECK: %y = load i64, ptr %yp
44 ; CHECK: %div = udiv i64 %x, %y
46 ; CHECK: call void @use(i64 %div)
50 loop: ; preds = %entry, %for.inc
51 %x = load i64, ptr %xp
52 %y = load i64, ptr %yp
53 %div = udiv i64 %x, %y
54 call void @use(i64 %div) readonly
58 ; Similiar to the above, but the hoistable instruction (%y in this case)
59 ; happens not to be the first instruction in the block.
60 define void @throw_header_after_nonfirst(ptr %xp, ptr %yp, ptr %cond) {
61 ; CHECK-LABEL: throw_header_after_nonfirst
62 ; CHECK: %y = load i64, ptr %yp
64 ; CHECK: %x = load i64, ptr %gep
65 ; CHECK: %div = udiv i64 %x, %y
66 ; CHECK: call void @use(i64 %div)
70 loop: ; preds = %entry, %for.inc
71 %iv = phi i64 [0, %entry], [%div, %loop]
72 %gep = getelementptr i64, ptr %xp, i64 %iv
73 %x = load i64, ptr %gep
74 %y = load i64, ptr %yp
75 %div = udiv i64 %x, %y
76 call void @use(i64 %div) readonly
81 define void @throw_header_before(i64 %x, i64 %y, ptr %cond) {
82 ; CHECK-LABEL: throw_header_before
84 ; CHECK: %div = udiv i64 %x, %y
85 ; CHECK: call void @use(i64 %div)
89 loop: ; preds = %entry, %for.inc
91 %div = udiv i64 %x, %y
92 call void @use(i64 %div)
96 ; The header is known no throw, but the loop is not. We can
97 ; still lift out of the header.
98 define void @nothrow_header(i64 %x, i64 %y, i1 %cond) {
99 ; CHECK-LABEL: nothrow_header
101 ; CHECK: %div = udiv i64 %x, %y
103 ; CHECK: call void @use(i64 %div)
106 loop: ; preds = %entry, %for.inc
107 %div = udiv i64 %x, %y
108 br i1 %cond, label %loop-if, label %exit
110 call void @use(i64 %div)
116 ; Positive test - can hoist something that happens before thrower.
117 define void @nothrow_header_pos(i64 %x, i64 %y, i1 %cond) {
118 ; CHECK-LABEL: nothrow_header_pos
120 ; CHECK: %div = udiv i64 %x, %y
122 ; CHECK: call void @use(i64 %div)
125 loop: ; preds = %entry, %for.inc
128 %div = udiv i64 %x, %y
129 call void @use(i64 %div)
134 ; Negative test - can't move out of throwing block
135 define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) {
136 ; CHECK-LABEL: nothrow_header_neg
139 ; CHECK: call void @maythrow()
140 ; CHECK: %div = udiv i64 %x, %y
141 ; CHECK: call void @use(i64 %div)
144 loop: ; preds = %entry, %for.inc
147 call void @maythrow()
148 %div = udiv i64 %x, %y
149 call void @use(i64 %div)