1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare double @llvm.pow.f64(double, double)
5 declare void @use(double)
8 ; pow(a,b) * a --> pow(a, b+1) (requires reassoc)
10 define double @pow_ab_a(double %a, double %b) {
11 ; CHECK-LABEL: @pow_ab_a(
12 ; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
13 ; CHECK-NEXT: [[M:%.*]] = fmul double [[P]], [[A]]
14 ; CHECK-NEXT: ret double [[M]]
16 %p = call double @llvm.pow.f64(double %a, double %b)
17 %m = fmul double %p, %a
21 ; pow(a,b) * a --> pow(a, b+1)
23 define double @pow_ab_a_reassoc(double %a, double %b) {
24 ; CHECK-LABEL: @pow_ab_a_reassoc(
25 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], 1.000000e+00
26 ; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
27 ; CHECK-NEXT: ret double [[M]]
29 %p = call double @llvm.pow.f64(double %a, double %b)
30 %m = fmul reassoc double %p, %a
34 ; a * pow(a,b) --> pow(a, b+1)
36 define double @pow_ab_a_reassoc_commute(double %pa, double %b) {
37 ; CHECK-LABEL: @pow_ab_a_reassoc_commute(
38 ; CHECK-NEXT: [[A:%.*]] = fadd double [[PA:%.*]], 4.200000e+01
39 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], 1.000000e+00
40 ; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[TMP1]])
41 ; CHECK-NEXT: ret double [[M]]
43 %a = fadd double %pa, 42.0 ; thwart complexity-based canonicalization
44 %p = call double @llvm.pow.f64(double %a, double %b)
45 %m = fmul reassoc double %a, %p
49 ; negative test - extra uses not allowed
51 define double @pow_ab_a_reassoc_use(double %a, double %b) {
52 ; CHECK-LABEL: @pow_ab_a_reassoc_use(
53 ; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
54 ; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[P]], [[A]]
55 ; CHECK-NEXT: call void @use(double [[P]])
56 ; CHECK-NEXT: ret double [[M]]
58 %p = call double @llvm.pow.f64(double %a, double %b)
59 %m = fmul reassoc double %p, %a
60 call void @use(double %p)
65 ; pow(a,b) * 1.0/a --> pow(a, b-1) (requires reassoc)
67 define double @pow_ab_recip_a(double %a, double %b) {
68 ; CHECK-LABEL: @pow_ab_recip_a(
69 ; CHECK-NEXT: [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]
70 ; CHECK-NEXT: [[P:%.*]] = call double @llvm.pow.f64(double [[A]], double [[B:%.*]])
71 ; CHECK-NEXT: [[M:%.*]] = fmul double [[R]], [[P]]
72 ; CHECK-NEXT: ret double [[M]]
74 %r = fdiv double 1.0, %a
75 %p = call double @llvm.pow.f64(double %a, double %b)
76 %m = fmul double %r, %p
80 ; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
82 define double @pow_ab_recip_a_reassoc(double %a, double %b) {
83 ; CHECK-LABEL: @pow_ab_recip_a_reassoc(
84 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
85 ; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
86 ; CHECK-NEXT: ret double [[M]]
88 %r = fdiv reassoc double 1.0, %a
89 %p = call reassoc double @llvm.pow.f64(double %a, double %b)
90 %m = fmul reassoc double %r, %p
94 ; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
96 define double @pow_ab_recip_a_reassoc_commute(double %a, double %b) {
97 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_commute(
98 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
99 ; CHECK-NEXT: [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
100 ; CHECK-NEXT: ret double [[M]]
102 %r = fdiv reassoc double 1.0, %a
103 %p = call reassoc double @llvm.pow.f64(double %a, double %b)
104 %m = fmul reassoc double %p, %r
108 ; TODO: extra use prevents conversion to fmul, so this needs a different pattern match.
110 define double @pow_ab_recip_a_reassoc_use1(double %a, double %b) {
111 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use1(
112 ; CHECK-NEXT: [[R:%.*]] = fdiv reassoc double 1.000000e+00, [[A:%.*]]
113 ; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[B:%.*]])
114 ; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[R]], [[P]]
115 ; CHECK-NEXT: call void @use(double [[R]])
116 ; CHECK-NEXT: ret double [[M]]
118 %r = fdiv reassoc double 1.0, %a
119 %p = call reassoc double @llvm.pow.f64(double %a, double %b)
120 %m = fmul reassoc double %r, %p
121 call void @use(double %r)
125 ; negative test - extra pow uses not allowed
127 define double @pow_ab_recip_a_reassoc_use2(double %a, double %b) {
128 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use2(
129 ; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
130 ; CHECK-NEXT: [[M:%.*]] = fdiv reassoc double [[P]], [[A]]
131 ; CHECK-NEXT: call void @use(double [[P]])
132 ; CHECK-NEXT: ret double [[M]]
134 %r = fdiv reassoc double 1.0, %a
135 %p = call reassoc double @llvm.pow.f64(double %a, double %b)
136 %m = fmul reassoc double %r, %p
137 call void @use(double %p)
141 ; negative test - extra pow uses not allowed
143 define double @pow_ab_recip_a_reassoc_use3(double %a, double %b) {
144 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use3(
145 ; CHECK-NEXT: [[R:%.*]] = fdiv reassoc double 1.000000e+00, [[A:%.*]]
146 ; CHECK-NEXT: [[P:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[B:%.*]])
147 ; CHECK-NEXT: [[M:%.*]] = fmul reassoc double [[R]], [[P]]
148 ; CHECK-NEXT: call void @use(double [[R]])
149 ; CHECK-NEXT: call void @use(double [[P]])
150 ; CHECK-NEXT: ret double [[M]]
152 %r = fdiv reassoc double 1.0, %a
153 %p = call reassoc double @llvm.pow.f64(double %a, double %b)
154 %m = fmul reassoc double %r, %p
155 call void @use(double %r)
156 call void @use(double %p)
161 ; (a**b) * (c**b) --> (a*c) ** b (if mul is reassoc)
163 define double @pow_ab_pow_cb(double %a, double %b, double %c) {
164 ; CHECK-LABEL: @pow_ab_pow_cb(
165 ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
166 ; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])
167 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP2]], [[TMP1]]
168 ; CHECK-NEXT: ret double [[MUL]]
170 %1 = call double @llvm.pow.f64(double %a, double %b)
171 %2 = call double @llvm.pow.f64(double %c, double %b)
172 %mul = fmul double %2, %1
176 ; (a**b) * (c**b) --> (a*c) ** b
178 define double @pow_ab_pow_cb_reassoc(double %a, double %b, double %c) {
179 ; CHECK-LABEL: @pow_ab_pow_cb_reassoc(
180 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[C:%.*]], [[A:%.*]]
181 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B:%.*]])
182 ; CHECK-NEXT: ret double [[MUL]]
184 %1 = call double @llvm.pow.f64(double %a, double %b)
185 %2 = call double @llvm.pow.f64(double %c, double %b)
186 %mul = fmul reassoc double %2, %1
190 ; (a**b) * (c**b) --> (a*c) ** b
192 define double @pow_ab_pow_cb_reassoc_use1(double %a, double %b, double %c) {
193 ; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use1(
194 ; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
195 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A]], [[C:%.*]]
196 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])
197 ; CHECK-NEXT: call void @use(double [[AB]])
198 ; CHECK-NEXT: ret double [[MUL]]
200 %ab = call double @llvm.pow.f64(double %a, double %b)
201 %cb = call double @llvm.pow.f64(double %c, double %b)
202 %mul = fmul reassoc double %ab, %cb
203 call void @use(double %ab)
207 ; (a**b) * (c**b) --> (a*c) ** b
209 define double @pow_ab_pow_cb_reassoc_use2(double %a, double %b, double %c) {
210 ; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use2(
211 ; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B:%.*]])
212 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[A:%.*]], [[C]]
213 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[TMP1]], double [[B]])
214 ; CHECK-NEXT: call void @use(double [[CB]])
215 ; CHECK-NEXT: ret double [[MUL]]
217 %ab = call double @llvm.pow.f64(double %a, double %b)
218 %cb = call double @llvm.pow.f64(double %c, double %b)
219 %mul = fmul reassoc double %ab, %cb
220 call void @use(double %cb)
224 ; negative test - too many extra uses
226 define double @pow_ab_pow_cb_reassoc_use3(double %a, double %b, double %c) {
227 ; CHECK-LABEL: @pow_ab_pow_cb_reassoc_use3(
228 ; CHECK-NEXT: [[AB:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
229 ; CHECK-NEXT: [[CB:%.*]] = call double @llvm.pow.f64(double [[C:%.*]], double [[B]])
230 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[AB]], [[CB]]
231 ; CHECK-NEXT: call void @use(double [[AB]])
232 ; CHECK-NEXT: call void @use(double [[CB]])
233 ; CHECK-NEXT: ret double [[MUL]]
235 %ab = call double @llvm.pow.f64(double %a, double %b)
236 %cb = call double @llvm.pow.f64(double %c, double %b)
237 %mul = fmul reassoc double %ab, %cb
238 call void @use(double %ab)
239 call void @use(double %cb)
243 define double @pow_ab_pow_ac(double %a, double %b, double %c) {
244 ; CHECK-LABEL: @pow_ab_pow_ac(
245 ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
246 ; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])
247 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP2]], [[TMP1]]
248 ; CHECK-NEXT: ret double [[MUL]]
250 %1 = call double @llvm.pow.f64(double %a, double %b)
251 %2 = call double @llvm.pow.f64(double %a, double %c)
252 %mul = fmul double %2, %1
256 define double @pow_ab_x_pow_ac_reassoc(double %a, double %b, double %c) {
257 ; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc(
258 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[C:%.*]], [[B:%.*]]
259 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
260 ; CHECK-NEXT: ret double [[MUL]]
262 %1 = call double @llvm.pow.f64(double %a, double %b)
263 %2 = call double @llvm.pow.f64(double %a, double %c)
264 %mul = fmul reassoc double %2, %1
268 define double @pow_ab_reassoc(double %a, double %b) {
269 ; CHECK-LABEL: @pow_ab_reassoc(
270 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], [[B]]
271 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
272 ; CHECK-NEXT: ret double [[MUL]]
274 %1 = call double @llvm.pow.f64(double %a, double %b)
275 %mul = fmul reassoc double %1, %1
279 define double @pow_ab_reassoc_extra_use(double %a, double %b) {
280 ; CHECK-LABEL: @pow_ab_reassoc_extra_use(
281 ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
282 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP1]]
283 ; CHECK-NEXT: call void @use(double [[TMP1]])
284 ; CHECK-NEXT: ret double [[MUL]]
286 %1 = call double @llvm.pow.f64(double %a, double %b)
287 %mul = fmul reassoc double %1, %1
288 call void @use(double %1)
292 define double @pow_ab_x_pow_ac_reassoc_extra_use(double %a, double %b, double %c) {
293 ; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc_extra_use(
294 ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
295 ; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc double [[B]], [[C:%.*]]
296 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.pow.f64(double [[A]], double [[TMP2]])
297 ; CHECK-NEXT: call void @use(double [[TMP1]])
298 ; CHECK-NEXT: ret double [[MUL]]
300 %1 = call double @llvm.pow.f64(double %a, double %b)
301 %2 = call double @llvm.pow.f64(double %a, double %c)
302 %mul = fmul reassoc double %1, %2
303 call void @use(double %1)
307 define double @pow_ab_x_pow_ac_reassoc_multiple_uses(double %a, double %b, double %c) {
308 ; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc_multiple_uses(
309 ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
310 ; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])
311 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP2]]
312 ; CHECK-NEXT: call void @use(double [[TMP1]])
313 ; CHECK-NEXT: call void @use(double [[TMP2]])
314 ; CHECK-NEXT: ret double [[MUL]]
316 %1 = call double @llvm.pow.f64(double %a, double %b)
317 %2 = call double @llvm.pow.f64(double %a, double %c)
318 %mul = fmul reassoc double %1, %2
319 call void @use(double %1)
320 call void @use(double %2)