1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
| ; RUN: opt -S -licm < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
declare void @use_nothrow(i64 %a) nounwind
declare void @use(i64 %a)
declare void @maythrow()
define void @nothrow(i64 %x, i64 %y, i1* %cond) {
; CHECK-LABEL: nothrow
; CHECK-LABEL: entry
; CHECK: %div = udiv i64 %x, %y
; CHECK-LABEL: loop
; CHECK: call void @use_nothrow(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
%div = udiv i64 %x, %y
br label %loop2
loop2:
call void @use_nothrow(i64 %div)
br label %loop
}
; The udiv is guarantee to execute if the loop is
define void @throw_header_after(i64 %x, i64 %y, i1* %cond) {
; CHECK-LABEL: throw_header_after
; CHECK: %div = udiv i64 %x, %y
; CHECK-LABEL: loop
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
%div = udiv i64 %x, %y
call void @use(i64 %div)
br label %loop
}
define void @throw_header_after_rec(i64* %xp, i64* %yp, i1* %cond) {
; CHECK-LABEL: throw_header_after_rec
; CHECK: %x = load i64, i64* %xp
; CHECK: %y = load i64, i64* %yp
; CHECK: %div = udiv i64 %x, %y
; CHECK-LABEL: loop
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
%x = load i64, i64* %xp
%y = load i64, i64* %yp
%div = udiv i64 %x, %y
call void @use(i64 %div) readonly
br label %loop
}
; Similiar to the above, but the hoistable instruction (%y in this case)
; happens not to be the first instruction in the block.
define void @throw_header_after_nonfirst(i64* %xp, i64* %yp, i1* %cond) {
; CHECK-LABEL: throw_header_after_nonfirst
; CHECK: %y = load i64, i64* %yp
; CHECK-LABEL: loop
; CHECK: %x = load i64, i64* %gep
; CHECK: %div = udiv i64 %x, %y
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
%iv = phi i64 [0, %entry], [%div, %loop]
%gep = getelementptr i64, i64* %xp, i64 %iv
%x = load i64, i64* %gep
%y = load i64, i64* %yp
%div = udiv i64 %x, %y
call void @use(i64 %div) readonly
br label %loop
}
; Negative test
define void @throw_header_before(i64 %x, i64 %y, i1* %cond) {
; CHECK-LABEL: throw_header_before
; CHECK-LABEL: loop
; CHECK: %div = udiv i64 %x, %y
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
call void @maythrow()
%div = udiv i64 %x, %y
call void @use(i64 %div)
br label %loop
}
; The header is known no throw, but the loop is not. We can
; still lift out of the header.
define void @nothrow_header(i64 %x, i64 %y, i1 %cond) {
; CHECK-LABEL: nothrow_header
; CHECK-LABEL: entry
; CHECK: %div = udiv i64 %x, %y
; CHECK-LABEL: loop
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
%div = udiv i64 %x, %y
br i1 %cond, label %loop-if, label %exit
loop-if:
call void @use(i64 %div)
br label %loop
exit:
ret void
}
; Positive test - can hoist something that happens before thrower.
define void @nothrow_header_pos(i64 %x, i64 %y, i1 %cond) {
; CHECK-LABEL: nothrow_header_pos
; CHECK-LABEL: entry
; CHECK: %div = udiv i64 %x, %y
; CHECK-LABEL: loop
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
br label %loop-if
loop-if:
%div = udiv i64 %x, %y
call void @use(i64 %div)
br label %loop
}
; Negative test - can't move out of throwing block
define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) {
; CHECK-LABEL: nothrow_header_neg
; CHECK-LABEL: entry
; CHECK-LABEL: loop
; CHECK: call void @maythrow()
; CHECK: %div = udiv i64 %x, %y
; CHECK: call void @use(i64 %div)
entry:
br label %loop
loop: ; preds = %entry, %for.inc
br label %loop-if
loop-if:
call void @maythrow()
%div = udiv i64 %x, %y
call void @use(i64 %div)
br label %loop
}
|