1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
4 declare double @llvm.powi.f64.i32(double, i32)
5 declare float @llvm.powi.f32.i32(float, i32)
6 declare double @llvm.powi.f64.i64(double, i64)
7 declare double @llvm.fabs.f64(double)
8 declare double @llvm.copysign.f64(double, double)
9 declare void @use(double)
11 define double @powi_fneg_even_int(double %x) {
12 ; CHECK-LABEL: @powi_fneg_even_int(
14 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
15 ; CHECK-NEXT: ret double [[R]]
18 %fneg = fneg double %x
19 %r = tail call double @llvm.powi.f64.i32(double %fneg, i32 4)
23 define double @powi_fabs_even_int(double %x) {
24 ; CHECK-LABEL: @powi_fabs_even_int(
26 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
27 ; CHECK-NEXT: ret double [[R]]
30 %f = tail call double @llvm.fabs.f64(double %x)
31 %r = tail call double @llvm.powi.f64.i32(double %f, i32 4)
35 define double @powi_copysign_even_int(double %x, double %y) {
36 ; CHECK-LABEL: @powi_copysign_even_int(
38 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
39 ; CHECK-NEXT: ret double [[R]]
42 %cs = tail call double @llvm.copysign.f64(double %x, double %y)
43 %r = tail call double @llvm.powi.f64.i32(double %cs, i32 4)
47 define double @powi_fneg_odd_int(double %x) {
48 ; CHECK-LABEL: @powi_fneg_odd_int(
50 ; CHECK-NEXT: [[FNEG:%.*]] = fneg double [[X:%.*]]
51 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[FNEG]], i32 5)
52 ; CHECK-NEXT: ret double [[R]]
55 %fneg = fneg double %x
56 %r = tail call double @llvm.powi.f64.i32(double %fneg, i32 5)
60 define double @powi_fabs_odd_int(double %x) {
61 ; CHECK-LABEL: @powi_fabs_odd_int(
63 ; CHECK-NEXT: [[F:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
64 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[F]], i32 5)
65 ; CHECK-NEXT: ret double [[R]]
68 %f = tail call double @llvm.fabs.f64(double %x)
69 %r = tail call double @llvm.powi.f64.i32(double %f, i32 5)
73 define double @powi_copysign_odd_int(double %x, double %y) {
74 ; CHECK-LABEL: @powi_copysign_odd_int(
76 ; CHECK-NEXT: [[CS:%.*]] = tail call double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]])
77 ; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[CS]], i32 5)
78 ; CHECK-NEXT: ret double [[R]]
81 %cs = tail call double @llvm.copysign.f64(double %x, double %y)
82 %r = tail call double @llvm.powi.f64.i32(double %cs, i32 5)
86 define double @powi_fmul_arg0_no_reassoc(double %x, i32 %i) {
87 ; CHECK-LABEL: @powi_fmul_arg0_no_reassoc(
89 ; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])
90 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[POW]], [[X]]
91 ; CHECK-NEXT: ret double [[MUL]]
94 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)
95 %mul = fmul double %pow, %x
100 define double @powi_fmul_arg0(double %x, i32 %i) {
101 ; CHECK-LABEL: @powi_fmul_arg0(
103 ; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])
104 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[POW]], [[X]]
105 ; CHECK-NEXT: ret double [[MUL]]
108 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)
109 %mul = fmul reassoc double %pow, %x
113 define double @powi_fmul_arg0_use(double %x, i32 %i) {
114 ; CHECK-LABEL: @powi_fmul_arg0_use(
116 ; CHECK-NEXT: [[POW:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[I:%.*]])
117 ; CHECK-NEXT: tail call void @use(double [[POW]])
118 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[POW]], [[X]]
119 ; CHECK-NEXT: ret double [[MUL]]
122 %pow = tail call double @llvm.powi.f64.i32(double %x, i32 %i)
123 tail call void @use(double %pow)
124 %mul = fmul reassoc double %pow, %x
128 ; Negative test: Missing reassoc flag on fmul
129 define double @powi_fmul_powi_no_reassoc1(double %x, i32 %y, i32 %z) {
130 ; CHECK-LABEL: @powi_fmul_powi_no_reassoc1(
132 ; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
133 ; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
134 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]]
135 ; CHECK-NEXT: ret double [[MUL]]
138 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
139 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
140 %mul = fmul double %p2, %p1
144 ; Negative test: Missing reassoc flag on 2nd operand
145 define double @powi_fmul_powi_no_reassoc2(double %x, i32 %y, i32 %z) {
146 ; CHECK-LABEL: @powi_fmul_powi_no_reassoc2(
148 ; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
149 ; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
150 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
151 ; CHECK-NEXT: ret double [[MUL]]
154 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
155 %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z)
156 %mul = fmul reassoc double %p2, %p1
160 ; Negative test: Missing reassoc flag on 1st operand
161 define double @powi_fmul_powi_no_reassoc3(double %x, i32 %y, i32 %z) {
162 ; CHECK-LABEL: @powi_fmul_powi_no_reassoc3(
164 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
165 ; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
166 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
167 ; CHECK-NEXT: ret double [[MUL]]
170 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
171 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
172 %mul = fmul reassoc double %p2, %p1
176 ; All of the fmul and its operands should have the reassoc flags
177 define double @powi_fmul_powi(double %x, i32 %y, i32 %z) {
178 ; CHECK-LABEL: @powi_fmul_powi(
180 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Z:%.*]], [[Y:%.*]]
181 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])
182 ; CHECK-NEXT: ret double [[MUL]]
185 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
186 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
187 %mul = fmul reassoc double %p2, %p1
191 define double @powi_fmul_powi_fast_on_fmul(double %x, i32 %y, i32 %z) {
192 ; CHECK-LABEL: @powi_fmul_powi_fast_on_fmul(
194 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Z:%.*]], [[Y:%.*]]
195 ; CHECK-NEXT: [[MUL:%.*]] = call fast double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])
196 ; CHECK-NEXT: ret double [[MUL]]
199 %p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y)
200 %p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z)
201 %mul = fmul fast double %p2, %p1
205 define double @powi_fmul_powi_fast_on_powi(double %x, i32 %y, i32 %z) {
206 ; CHECK-LABEL: @powi_fmul_powi_fast_on_powi(
208 ; CHECK-NEXT: [[P1:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
209 ; CHECK-NEXT: [[P2:%.*]] = tail call fast double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]])
210 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]]
211 ; CHECK-NEXT: ret double [[MUL]]
214 %p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y)
215 %p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z)
216 %mul = fmul double %p2, %p1
220 define double @powi_fmul_powi_same_power(double %x, i32 %y, i32 %z) {
221 ; CHECK-LABEL: @powi_fmul_powi_same_power(
223 ; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[Y:%.*]], 1
224 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[TMP0]])
225 ; CHECK-NEXT: ret double [[MUL]]
228 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
229 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
230 %mul = fmul reassoc double %p2, %p1
234 define double @powi_fmul_powi_different_integer_types(double %x, i32 %y, i16 %z) {
235 ; CHECK-LABEL: @powi_fmul_powi_different_integer_types(
237 ; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
238 ; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i16(double [[X]], i16 [[Z:%.*]])
239 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
240 ; CHECK-NEXT: ret double [[MUL]]
243 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
244 %p2 = tail call reassoc double @llvm.powi.f64.i16(double %x, i16 %z)
245 %mul = fmul reassoc double %p2, %p1
249 define double @powi_fmul_powi_use_first(double %x, i32 %y, i32 %z) {
250 ; CHECK-LABEL: @powi_fmul_powi_use_first(
252 ; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
253 ; CHECK-NEXT: tail call void @use(double [[P1]])
254 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y]], [[Z:%.*]]
255 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])
256 ; CHECK-NEXT: ret double [[MUL]]
259 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
260 tail call void @use(double %p1)
261 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
262 %mul = fmul reassoc double %p1, %p2
266 define double @powi_fmul_powi_use_second(double %x, i32 %y, i32 %z) {
267 ; CHECK-LABEL: @powi_fmul_powi_use_second(
269 ; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]])
270 ; CHECK-NEXT: tail call void @use(double [[P1]])
271 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y:%.*]], [[Z]]
272 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]])
273 ; CHECK-NEXT: ret double [[MUL]]
276 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z)
277 tail call void @use(double %p1)
278 %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
279 %mul = fmul reassoc double %p2, %p1
283 define double @powi_fmul_different_base(double %x, double %m, i32 %y, i32 %z) {
284 ; CHECK-LABEL: @powi_fmul_different_base(
286 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
287 ; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[M:%.*]], i32 [[Z:%.*]])
288 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
289 ; CHECK-NEXT: ret double [[MUL]]
292 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
293 %p2 = tail call double @llvm.powi.f64.i32(double %m, i32 %z)
294 %mul = fmul reassoc double %p2, %p1
298 define double @different_types_powi(double %x, i32 %y, i64 %z) {
299 ; CHECK-LABEL: @different_types_powi(
300 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
301 ; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i64(double [[X]], i64 [[Z:%.*]])
302 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]]
303 ; CHECK-NEXT: ret double [[MUL]]
305 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y)
306 %p2 = tail call double @llvm.powi.f64.i64(double %x, i64 %z)
307 %mul = fmul reassoc double %p2, %p1
311 define double @fdiv_pow_powi(double %x) {
312 ; CHECK-LABEL: @fdiv_pow_powi(
313 ; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]]
314 ; CHECK-NEXT: ret double [[DIV]]
316 %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 3)
317 %div = fdiv reassoc nnan double %p1, %x
321 define float @fdiv_powf_powi(float %x) {
322 ; CHECK-LABEL: @fdiv_powf_powi(
323 ; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan float @llvm.powi.f32.i32(float [[X:%.*]], i32 99)
324 ; CHECK-NEXT: ret float [[DIV]]
326 %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100)
327 %div = fdiv reassoc nnan float %p1, %x
331 ; TODO: Multi-use may be also better off creating Powi(x,y-1) then creating
332 ; (mul, Powi(x,y-1),x) to replace the Powi(x,y).
333 define double @fdiv_pow_powi_multi_use(double %x) {
334 ; CHECK-LABEL: @fdiv_pow_powi_multi_use(
335 ; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
336 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]
337 ; CHECK-NEXT: tail call void @use(double [[P1]])
338 ; CHECK-NEXT: ret double [[DIV]]
340 %p1 = call double @llvm.powi.f64.i32(double %x, i32 3)
341 %div = fdiv reassoc nnan double %p1, %x
342 tail call void @use(double %p1)
346 ; Negative test: Miss part of the fmf flag for the fdiv instruction
347 define float @fdiv_powf_powi_missing_reassoc(float %x) {
348 ; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc(
349 ; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
350 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan float [[P1]], [[X]]
351 ; CHECK-NEXT: ret float [[DIV]]
353 %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)
354 %div = fdiv reassoc nnan float %p1, %x
358 define float @fdiv_powf_powi_missing_reassoc1(float %x) {
359 ; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc1(
360 ; CHECK-NEXT: [[P1:%.*]] = call reassoc float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
361 ; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]]
362 ; CHECK-NEXT: ret float [[DIV]]
364 %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100)
365 %div = fdiv nnan float %p1, %x
369 define float @fdiv_powf_powi_missing_nnan(float %x) {
370 ; CHECK-LABEL: @fdiv_powf_powi_missing_nnan(
371 ; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100)
372 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float [[P1]], [[X]]
373 ; CHECK-NEXT: ret float [[DIV]]
375 %p1 = call float @llvm.powi.f32.i32(float %x, i32 100)
376 %div = fdiv reassoc float %p1, %x
380 ; Negative test: Illegal because (Y - 1) wraparound
381 define double @fdiv_pow_powi_negative(double %x) {
382 ; CHECK-LABEL: @fdiv_pow_powi_negative(
383 ; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 -2147483648)
384 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]
385 ; CHECK-NEXT: ret double [[DIV]]
387 %p1 = call double @llvm.powi.f64.i32(double %x, i32 -2147483648) ; INT_MIN
388 %div = fdiv reassoc nnan double %p1, %x
392 ; Negative test: The 2nd powi argument is a variable
393 define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) {
394 ; CHECK-LABEL: @fdiv_pow_powi_negative_variable(
395 ; CHECK-NEXT: [[P1:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
396 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]]
397 ; CHECK-NEXT: ret double [[DIV]]
399 %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 %y)
400 %div = fdiv reassoc nnan double %p1, %x
404 ; powi(X,C1)/ (X * Z) --> powi(X,C1 - 1)/ Z
405 define double @fdiv_fmul_powi(double %a, double %z) {
406 ; CHECK-LABEL: @fdiv_fmul_powi(
407 ; CHECK-NEXT: [[TMP1:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 4)
408 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[TMP1]], [[Z:%.*]]
409 ; CHECK-NEXT: ret double [[DIV]]
411 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
412 %square = fmul reassoc double %z, %a
413 %div = fdiv reassoc nnan double %pow, %square
417 ; powi(X, 5)/ (X * X) --> powi(X, 4)/ X -> powi(X, 3)
418 define double @fdiv_fmul_powi_2(double %a) {
419 ; CHECK-LABEL: @fdiv_fmul_powi_2(
420 ; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 3)
421 ; CHECK-NEXT: ret double [[DIV]]
423 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
424 %square = fmul reassoc double %a, %a
425 %div = fdiv reassoc nnan double %pow, %square
429 define <2 x float> @fdiv_fmul_powi_vector(<2 x float> %a) {
430 ; CHECK-LABEL: @fdiv_fmul_powi_vector(
431 ; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan <2 x float> @llvm.powi.v2f32.i32(<2 x float> [[A:%.*]], i32 3)
432 ; CHECK-NEXT: ret <2 x float> [[DIV]]
434 %pow = call reassoc <2 x float> @llvm.powi.v2f32.i32(<2 x float> %a, i32 5)
435 %square = fmul reassoc <2 x float> %a, %a
436 %div = fdiv reassoc nnan <2 x float> %pow, %square
441 define double @fdiv_fmul_powi_missing_reassoc1(double %a) {
442 ; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc1(
443 ; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)
444 ; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]
445 ; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan double [[POW]], [[SQUARE]]
446 ; CHECK-NEXT: ret double [[DIV]]
448 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
449 %square = fmul reassoc double %a, %a
450 %div = fdiv nnan double %pow, %square
454 define double @fdiv_fmul_powi_missing_reassoc2(double %a) {
455 ; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc2(
456 ; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)
457 ; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[A]], [[A]]
458 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]
459 ; CHECK-NEXT: ret double [[DIV]]
461 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
462 %square = fmul double %a, %a
463 %div = fdiv reassoc nnan double %pow, %square
467 define double @fdiv_fmul_powi_missing_reassoc3(double %a) {
468 ; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc3(
469 ; CHECK-NEXT: [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)
470 ; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]
471 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]
472 ; CHECK-NEXT: ret double [[DIV]]
474 %pow = call double @llvm.powi.f64.i32(double %a, i32 5)
475 %square = fmul reassoc double %a, %a
476 %div = fdiv reassoc nnan double %pow, %square
480 define double @fdiv_fmul_powi_missing_nnan(double %a) {
481 ; CHECK-LABEL: @fdiv_fmul_powi_missing_nnan(
482 ; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)
483 ; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]
484 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[POW]], [[SQUARE]]
485 ; CHECK-NEXT: ret double [[DIV]]
487 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
488 %square = fmul reassoc double %a, %a
489 %div = fdiv reassoc double %pow, %square
493 define double @fdiv_fmul_powi_negative_wrap(double noundef %x) {
494 ; CHECK-LABEL: @fdiv_fmul_powi_negative_wrap(
495 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 -2147483648)
496 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]
497 ; CHECK-NEXT: ret double [[MUL]]
499 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 -2147483648) ; INT_MIN
500 %mul = fmul reassoc double %p1, %x
504 define double @fdiv_fmul_powi_multi_use(double %a) {
505 ; CHECK-LABEL: @fdiv_fmul_powi_multi_use(
506 ; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5)
507 ; CHECK-NEXT: tail call void @use(double [[POW]])
508 ; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]]
509 ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]]
510 ; CHECK-NEXT: ret double [[DIV]]
512 %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5)
513 tail call void @use(double %pow)
514 %square = fmul reassoc double %a, %a
515 %div = fdiv reassoc nnan double %pow, %square
519 ; powi(X, Y) * X --> powi(X, Y+1)
520 define double @powi_fmul_powi_x(double noundef %x) {
521 ; CHECK-LABEL: @powi_fmul_powi_x(
522 ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
523 ; CHECK-NEXT: ret double [[MUL]]
525 %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 3)
526 %mul = fmul reassoc double %p1, %x
530 ; Negative test: Multi-use
531 define double @powi_fmul_powi_x_multi_use(double noundef %x) {
532 ; CHECK-LABEL: @powi_fmul_powi_x_multi_use(
533 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
534 ; CHECK-NEXT: tail call void @use(double [[P1]])
535 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]
536 ; CHECK-NEXT: ret double [[MUL]]
538 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
539 tail call void @use(double %p1)
540 %mul = fmul reassoc double %p1, %x
544 ; Negative test: Miss fmf flag
545 define double @powi_fmul_powi_x_missing_reassoc(double noundef %x) {
546 ; CHECK-LABEL: @powi_fmul_powi_x_missing_reassoc(
547 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3)
548 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P1]], [[X]]
549 ; CHECK-NEXT: ret double [[MUL]]
551 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3)
552 %mul = fmul double %p1, %x
556 ; Negative test: overflow
557 define double @powi_fmul_powi_x_overflow(double noundef %x) {
558 ; CHECK-LABEL: @powi_fmul_powi_x_overflow(
559 ; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 2147483647)
560 ; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]]
561 ; CHECK-NEXT: ret double [[MUL]]
563 %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 2147483647) ; INT_MAX
564 %mul = fmul reassoc double %p1, %x