1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
3 ; Test numbering remains continuous across:
4 ; - InstCombine/fast-basictest.ll
5 ; - PhaseOrdering/fast-basictest.ll
6 ; - PhaseOrdering/fast-reassociate-gvn.ll
7 ; - Reassociate/fast-basictest.ll
9 ; RUN: opt < %s -passes=reassociate -S | FileCheck %s
11 ; ((a + (-3)) + b) + 3 -> a + b
12 ; That only works with both instcombine and reassociate passes enabled.
13 ; Check that reassociate is not enough.
15 ; TODO: check if we can eliminate zero add.
16 define float @test2(float %reg109, float %reg1111) {
17 ; CHECK-LABEL: @test2(
18 ; CHECK-NEXT: [[REG116:%.*]] = fadd fast float [[REG109:%.*]], 0.000000e+00
19 ; CHECK-NEXT: [[REG117:%.*]] = fadd fast float [[REG116]], [[REG1111:%.*]]
20 ; CHECK-NEXT: ret float [[REG117]]
22 %reg115 = fadd fast float %reg109, -3.000000e+01
23 %reg116 = fadd fast float %reg115, %reg1111
24 %reg117 = fadd fast float %reg116, 3.000000e+01
28 define float @test2_no_FMF(float %reg109, float %reg1111) {
29 ; CHECK-LABEL: @test2_no_FMF(
30 ; CHECK-NEXT: [[REG115:%.*]] = fadd float [[REG109:%.*]], -3.000000e+01
31 ; CHECK-NEXT: [[REG116:%.*]] = fadd float [[REG115]], [[REG1111:%.*]]
32 ; CHECK-NEXT: [[REG117:%.*]] = fadd float [[REG116]], 3.000000e+01
33 ; CHECK-NEXT: ret float [[REG117]]
35 %reg115 = fadd float %reg109, -3.000000e+01
36 %reg116 = fadd float %reg115, %reg1111
37 %reg117 = fadd float %reg116, 3.000000e+01
41 define float @test2_reassoc(float %reg109, float %reg1111) {
42 ; CHECK-LABEL: @test2_reassoc(
43 ; CHECK-NEXT: [[REG115:%.*]] = fadd reassoc float [[REG109:%.*]], -3.000000e+01
44 ; CHECK-NEXT: [[REG116:%.*]] = fadd reassoc float [[REG115]], [[REG1111:%.*]]
45 ; CHECK-NEXT: [[REG117:%.*]] = fadd reassoc float [[REG116]], 3.000000e+01
46 ; CHECK-NEXT: ret float [[REG117]]
48 %reg115 = fadd reassoc float %reg109, -3.000000e+01
49 %reg116 = fadd reassoc float %reg115, %reg1111
50 %reg117 = fadd reassoc float %reg116, 3.000000e+01
54 @fe = external global float
55 @fa = external global float
56 @fb = external global float
57 @fc = external global float
58 @ff = external global float
60 ; If two sums of the same operands in different order are counted with 'fast'
61 ; flag and then stored to global variables, we can reuse the same value twice.
63 ; - test3: (a+b)+c and (a+c)+b
64 ; - test4: c+(a+b) and (c+a)+b
65 ; - test5: c+(b+a) and (c+a)+b
67 ; That only works with both gvn and reassociate passes enabled.
68 ; Check that reassociate is not enough.
70 define void @test3() {
71 ; CHECK-LABEL: @test3(
72 ; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
73 ; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
74 ; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
75 ; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
76 ; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
77 ; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
78 ; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
79 ; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
80 ; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
81 ; CHECK-NEXT: ret void
83 %A = load float, ptr @fa
84 %B = load float, ptr @fb
85 %C = load float, ptr @fc
86 %t1 = fadd fast float %A, %B
87 %t2 = fadd fast float %t1, %C
88 %t3 = fadd fast float %A, %C
89 %t4 = fadd fast float %t3, %B
91 store float %t2, ptr @fe
93 store float %t4, ptr @ff
97 define void @test4() {
98 ; CHECK-LABEL: @test4(
99 ; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
100 ; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
101 ; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
102 ; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
103 ; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
104 ; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
105 ; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
106 ; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
107 ; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
108 ; CHECK-NEXT: ret void
110 %A = load float, ptr @fa
111 %B = load float, ptr @fb
112 %C = load float, ptr @fc
113 %t1 = fadd fast float %A, %B
114 %t2 = fadd fast float %C, %t1
115 %t3 = fadd fast float %C, %A
116 %t4 = fadd fast float %t3, %B
118 store float %t2, ptr @fe
120 store float %t4, ptr @ff
124 define void @test5() {
125 ; CHECK-LABEL: @test5(
126 ; CHECK-NEXT: [[A:%.*]] = load float, ptr @fa, align 4
127 ; CHECK-NEXT: [[B:%.*]] = load float, ptr @fb, align 4
128 ; CHECK-NEXT: [[C:%.*]] = load float, ptr @fc, align 4
129 ; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]]
130 ; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]]
131 ; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]]
132 ; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]]
133 ; CHECK-NEXT: store float [[T2]], ptr @fe, align 4
134 ; CHECK-NEXT: store float [[T4]], ptr @ff, align 4
135 ; CHECK-NEXT: ret void
137 %A = load float, ptr @fa
138 %B = load float, ptr @fb
139 %C = load float, ptr @fc
140 %t1 = fadd fast float %B, %A
141 %t2 = fadd fast float %C, %t1
142 %t3 = fadd fast float %C, %A
143 %t4 = fadd fast float %t3, %B
145 store float %t2, ptr @fe
147 store float %t4, ptr @ff
151 define float @test6(float %A, float %B, float %C) {
152 ; CHECK-LABEL: @test6(
153 ; CHECK-NEXT: [[REASS_ADD1:%.*]] = fadd fast float [[C:%.*]], [[B:%.*]]
154 ; CHECK-NEXT: [[REASS_MUL2:%.*]] = fmul fast float [[A:%.*]], [[A]]
155 ; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast float [[REASS_MUL2]], [[REASS_ADD1]]
156 ; CHECK-NEXT: ret float [[REASS_MUL]]
158 %aa = fmul fast float %A, %A
159 %aab = fmul fast float %aa, %B
160 %ac = fmul fast float %A, %C
161 %aac = fmul fast float %ac, %A
162 %r = fadd fast float %aab, %aac
166 define float @test6_reassoc(float %A, float %B, float %C) {
167 ; CHECK-LABEL: @test6_reassoc(
168 ; CHECK-NEXT: [[AA:%.*]] = fmul reassoc float [[A:%.*]], [[A]]
169 ; CHECK-NEXT: [[AAB:%.*]] = fmul reassoc float [[AA]], [[B:%.*]]
170 ; CHECK-NEXT: [[AC:%.*]] = fmul reassoc float [[A]], [[C:%.*]]
171 ; CHECK-NEXT: [[AAC:%.*]] = fmul reassoc float [[A]], [[AC]]
172 ; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[AAB]], [[AAC]]
173 ; CHECK-NEXT: ret float [[R]]
175 %aa = fmul reassoc float %A, %A
176 %aab = fmul reassoc float %aa, %B
177 %ac = fmul reassoc float %A, %C
178 %aac = fmul reassoc float %ac, %A
179 %r = fadd reassoc float %aab, %aac
183 ; (-X)*Y + Z -> Z-X*Y
184 define float @test7(float %X, float %Y, float %Z) {
185 ; CHECK-LABEL: @test7(
186 ; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]]
187 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]]
188 ; CHECK-NEXT: ret float [[TMP1]]
190 %A = fsub fast float 0.0, %X
191 %B = fmul fast float %A, %Y
192 %C = fadd fast float %B, %Z
196 define float @test7_unary_fneg(float %X, float %Y, float %Z) {
197 ; CHECK-LABEL: @test7_unary_fneg(
198 ; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]]
199 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]]
200 ; CHECK-NEXT: ret float [[TMP1]]
202 %A = fneg fast float %X
203 %B = fmul fast float %A, %Y
204 %C = fadd fast float %B, %Z
208 define float @test7_reassoc_nsz(float %X, float %Y, float %Z) {
209 ; CHECK-LABEL: @test7_reassoc_nsz(
210 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[Y:%.*]], [[X:%.*]]
211 ; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[B]]
212 ; CHECK-NEXT: ret float [[TMP1]]
214 %A = fsub reassoc nsz float 0.0, %X
215 %B = fmul reassoc nsz float %A, %Y
216 %C = fadd reassoc nsz float %B, %Z
220 ; Verify that fold is not done only with 'reassoc' ('nsz' is required)
221 define float @test7_reassoc(float %X, float %Y, float %Z) {
222 ; CHECK-LABEL: @test7_reassoc(
223 ; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X:%.*]]
224 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[Y:%.*]]
225 ; CHECK-NEXT: [[C:%.*]] = fadd reassoc float [[B]], [[Z:%.*]]
226 ; CHECK-NEXT: ret float [[C]]
228 %A = fsub reassoc float 0.0, %X
229 %B = fmul reassoc float %A, %Y
230 %C = fadd reassoc float %B, %Z
234 ; Integer version of:
235 ; (-X)*Y + Z -> Z-X*Y
236 ; TODO: check if we can change the mul of -1 and the add to a sub.
237 define i32 @test7_int(i32 %X, i32 %Y, i32 %Z) {
238 ; CHECK-LABEL: @test7_int(
239 ; CHECK-NEXT: [[A:%.*]] = mul i32 [[Y:%.*]], [[X:%.*]]
240 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[A]], -1
241 ; CHECK-NEXT: [[C:%.*]] = add i32 [[B]], [[Z:%.*]]
242 ; CHECK-NEXT: ret i32 [[C]]
250 define float @test8(float %X) {
251 ; CHECK-LABEL: @test8(
252 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 9.400000e+01
253 ; CHECK-NEXT: ret float [[FACTOR]]
255 %Y = fmul fast float %X, 4.700000e+01
256 %Z = fadd fast float %Y, %Y
260 ; Side note: (x + x + x) and (3*x) each have only a single rounding. So
261 ; transforming x+x+x to 3*x is always safe, even without any FMF.
262 ; To avoid that special-case, we have the addition of 'x' four times, here.
263 define float @test9(float %X) {
264 ; CHECK-LABEL: @test9(
265 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 4.000000e+00
266 ; CHECK-NEXT: ret float [[FACTOR]]
268 %Y = fadd fast float %X ,%X
269 %Z = fadd fast float %Y, %X
270 %W = fadd fast float %Z, %X
274 define float @test10(float %W) {
275 ; CHECK-LABEL: @test10(
276 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[W:%.*]], 3.810000e+02
277 ; CHECK-NEXT: ret float [[FACTOR]]
279 %X = fmul fast float %W, 127.0
280 %Y = fadd fast float %X ,%X
281 %Z = fadd fast float %Y, %X
285 define float @test11(float %X) {
286 ; CHECK-LABEL: @test11(
287 ; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], -3.000000e+00
288 ; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[FACTOR]], 6.000000e+00
289 ; CHECK-NEXT: ret float [[Z]]
291 %A = fsub fast float 1.000000e+00, %X
292 %B = fsub fast float 2.000000e+00, %X
293 %C = fsub fast float 3.000000e+00, %X
294 %Y = fadd fast float %A ,%B
295 %Z = fadd fast float %Y, %C
299 define float @test12(float %X1, float %X2, float %X3) {
300 ; CHECK-LABEL: @test12(
301 ; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]]
302 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]]
303 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]]
304 ; CHECK-NEXT: ret float [[TMP1]]
306 %A = fsub fast float 0.000000e+00, %X1
307 %B = fmul fast float %A, %X2 ; -X1*X2
308 %C = fmul fast float %X1, %X3 ; X1*X3
309 %D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
313 define float @test12_unary_fneg(float %X1, float %X2, float %X3) {
314 ; CHECK-LABEL: @test12_unary_fneg(
315 ; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]]
316 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]]
317 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]]
318 ; CHECK-NEXT: ret float [[TMP1]]
320 %A = fneg fast float %X1
321 %B = fmul fast float %A, %X2 ; -X1*X2
322 %C = fmul fast float %X1, %X3 ; X1*X3
323 %D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
327 define float @test12_reassoc_nsz(float %X1, float %X2, float %X3) {
328 ; CHECK-LABEL: @test12_reassoc_nsz(
329 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[X2:%.*]], [[X1:%.*]]
330 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X3:%.*]], [[X1]]
331 ; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[C]], [[B]]
332 ; CHECK-NEXT: ret float [[TMP1]]
334 %A = fsub reassoc nsz float 0.000000e+00, %X1
335 %B = fmul reassoc nsz float %A, %X2 ; -X1*X2
336 %C = fmul reassoc nsz float %X1, %X3 ; X1*X3
337 %D = fadd reassoc nsz float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
341 ; TODO: check if 'nsz' is technically required. Currently the optimization
342 ; is not done with only 'reassoc' without 'nsz'.
343 define float @test12_reassoc(float %X1, float %X2, float %X3) {
344 ; CHECK-LABEL: @test12_reassoc(
345 ; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X1:%.*]]
346 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[X2:%.*]]
347 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X1]], [[X3:%.*]]
348 ; CHECK-NEXT: [[D:%.*]] = fadd reassoc float [[B]], [[C]]
349 ; CHECK-NEXT: ret float [[D]]
351 %A = fsub reassoc float 0.000000e+00, %X1
352 %B = fmul reassoc float %A, %X2 ; -X1*X2
353 %C = fmul reassoc float %X1, %X3 ; X1*X3
354 %D = fadd reassoc float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
358 ; (x1 * 47) + (x2 * -47) => (x1 - x2) * 47
359 ; That only works with both instcombine and reassociate passes enabled.
360 ; Check that reassociate is not enough.
362 define float @test13(float %X1, float %X2) {
363 ; CHECK-LABEL: @test13(
364 ; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X1:%.*]], 4.700000e+01
365 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X2:%.*]], 4.700000e+01
366 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[B]], [[C]]
367 ; CHECK-NEXT: ret float [[TMP1]]
369 %B = fmul fast float %X1, 47. ; X1*47
370 %C = fmul fast float %X2, -47. ; X2*-47
371 %D = fadd fast float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
375 define float @test13_reassoc_nsz(float %X1, float %X2) {
376 ; CHECK-LABEL: @test13_reassoc_nsz(
377 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[X1:%.*]], 4.700000e+01
378 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X2:%.*]], 4.700000e+01
379 ; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[B]], [[C]]
380 ; CHECK-NEXT: ret float [[TMP1]]
382 %B = fmul reassoc nsz float %X1, 47. ; X1*47
383 %C = fmul reassoc nsz float %X2, -47. ; X2*-47
384 %D = fadd reassoc nsz float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
388 define float @test13_reassoc(float %X1, float %X2) {
389 ; CHECK-LABEL: @test13_reassoc(
390 ; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[X1:%.*]], 4.700000e+01
391 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X2:%.*]], 4.700000e+01
392 ; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc float [[B]], [[C]]
393 ; CHECK-NEXT: ret float [[TMP1]]
395 %B = fmul reassoc float %X1, 47. ; X1*47
396 %C = fmul reassoc float %X2, -47. ; X2*-47
397 %D = fadd reassoc float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
401 define float @test14(float %arg) {
402 ; CHECK-LABEL: @test14(
403 ; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[ARG:%.*]], 1.440000e+02
404 ; CHECK-NEXT: ret float [[T2]]
406 %t1 = fmul fast float 1.200000e+01, %arg
407 %t2 = fmul fast float %t1, 1.200000e+01
411 ; TODO: check if we can transform the code with 'reassoc' only.
412 ; The same IR is transformed to one fmul in instcombine pass.
413 define float @test14_reassoc(float %arg) {
414 ; CHECK-LABEL: @test14_reassoc(
415 ; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[ARG:%.*]], 1.200000e+01
416 ; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[T1]], 1.200000e+01
417 ; CHECK-NEXT: ret float [[T2]]
419 %t1 = fmul reassoc float 1.200000e+01, %arg
420 %t2 = fmul reassoc float %t1, 1.200000e+01
424 ; (b+(a+1234))+-a -> b+1234
425 ; That only works with both instcombine and reassociate passes enabled.
426 ; Check that reassociate is not enough.
428 ; TODO: check if we can remove dead fsub.
429 define float @test15(float %b, float %a) {
430 ; CHECK-LABEL: @test15(
431 ; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float 0.000000e+00, [[A:%.*]]
432 ; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
433 ; CHECK-NEXT: ret float [[TMP2]]
435 %1 = fadd fast float %a, 1234.0
436 %2 = fadd fast float %b, %1
437 %3 = fsub fast float 0.0, %a
438 %4 = fadd fast float %2, %3
442 ; TODO: check if we can remove dead fneg.
443 define float @test15_unary_fneg(float %b, float %a) {
444 ; CHECK-LABEL: @test15_unary_fneg(
445 ; CHECK-NEXT: [[TMP1:%.*]] = fneg fast float [[A:%.*]]
446 ; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
447 ; CHECK-NEXT: ret float [[TMP2]]
449 %1 = fadd fast float %a, 1234.0
450 %2 = fadd fast float %b, %1
451 %3 = fneg fast float %a
452 %4 = fadd fast float %2, %3
456 ; TODO: check if we can remove dead fsub.
457 define float @test15_reassoc_nsz(float %b, float %a) {
458 ; CHECK-LABEL: @test15_reassoc_nsz(
459 ; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float 0.000000e+00, [[A:%.*]]
460 ; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc nsz float [[B:%.*]], 1.234000e+03
461 ; CHECK-NEXT: ret float [[TMP2]]
463 %1 = fadd reassoc nsz float %a, 1234.0
464 %2 = fadd reassoc nsz float %b, %1
465 %3 = fsub reassoc nsz float 0.0, %a
466 %4 = fadd reassoc nsz float %2, %3
470 define float @test15_reassoc(float %b, float %a) {
471 ; CHECK-LABEL: @test15_reassoc(
472 ; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[A:%.*]], 1.234000e+03
473 ; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[B:%.*]], [[TMP1]]
474 ; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float 0.000000e+00, [[A]]
475 ; CHECK-NEXT: [[TMP4:%.*]] = fadd reassoc float [[TMP3]], [[TMP2]]
476 ; CHECK-NEXT: ret float [[TMP4]]
478 %1 = fadd reassoc float %a, 1234.0
479 %2 = fadd reassoc float %b, %1
480 %3 = fsub reassoc float 0.0, %a
481 %4 = fadd reassoc float %2, %3
485 ; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z.
486 ; That only works with both instcombine and reassociate passes enabled.
487 ; Check that reassociate is not enough.
489 define float @test16(float %a, float %b, float %z) {
490 ; CHECK-LABEL: @test16(
491 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
492 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[B:%.*]]
493 ; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
494 ; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[F]], 0.000000e+00
495 ; CHECK-NEXT: ret float [[TMP1]]
497 %c = fsub fast float 0.000000e+00, %z
498 %d = fmul fast float %a, %b
499 %e = fmul fast float %c, %d
500 %f = fmul fast float %e, 1.234500e+04
501 %g = fsub fast float 0.000000e+00, %f
505 define float @test16_unary_fneg(float %a, float %b, float %z) {
506 ; CHECK-LABEL: @test16_unary_fneg(
507 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
508 ; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[B:%.*]]
509 ; CHECK-NEXT: [[G:%.*]] = fmul fast float [[F]], [[Z:%.*]]
510 ; CHECK-NEXT: ret float [[G]]
512 %c = fneg fast float %z
513 %d = fmul fast float %a, %b
514 %e = fmul fast float %c, %d
515 %f = fmul fast float %e, 1.234500e+04
516 %g = fneg fast float %f
520 define float @test16_reassoc(float %a, float %b, float %z) {
521 ; CHECK-LABEL: @test16_reassoc(
522 ; CHECK-NEXT: [[C:%.*]] = fsub reassoc float 0.000000e+00, [[Z:%.*]]
523 ; CHECK-NEXT: [[D:%.*]] = fmul reassoc float [[A:%.*]], [[B:%.*]]
524 ; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[D]], [[C]]
525 ; CHECK-NEXT: [[F:%.*]] = fmul reassoc float [[E]], 1.234500e+04
526 ; CHECK-NEXT: [[G:%.*]] = fsub reassoc float 0.000000e+00, [[F]]
527 ; CHECK-NEXT: ret float [[G]]
529 %c = fsub reassoc float 0.000000e+00, %z
530 %d = fmul reassoc float %a, %b
531 %e = fmul reassoc float %c, %d
532 %f = fmul reassoc float %e, 1.234500e+04
533 %g = fsub reassoc float 0.000000e+00, %f
537 ; TODO: check if we can remove:
539 ; ... as 'fast' implies 'nsz'
540 define float @test17(float %a, float %b, float %z) {
541 ; CHECK-LABEL: @test17(
542 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
543 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[Z:%.*]]
544 ; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[E]], 0.000000e+00
545 ; CHECK-NEXT: ret float [[TMP1]]
547 %d = fmul fast float %z, 4.000000e+01
548 %c = fsub fast float 0.000000e+00, %d
549 %e = fmul fast float %a, %c
550 %f = fsub fast float 0.000000e+00, %e
554 define float @test17_unary_fneg(float %a, float %b, float %z) {
555 ; CHECK-LABEL: @test17_unary_fneg(
556 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
557 ; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
558 ; CHECK-NEXT: ret float [[F]]
560 %d = fmul fast float %z, 4.000000e+01
561 %c = fneg fast float %d
562 %e = fmul fast float %a, %c
563 %f = fneg fast float %e
567 ; With sub reassociation, constant folding can eliminate the 12 and -12 constants.
568 ; TODO: check if we can remove fadd fast x, 0 as 'fast' implies 'nsz'
569 define float @test18(float %A, float %B) {
570 ; CHECK-LABEL: @test18(
571 ; CHECK-NEXT: [[B_NEG:%.*]] = fneg fast float [[B:%.*]]
572 ; CHECK-NEXT: [[Y:%.*]] = fadd fast float [[A:%.*]], 0.000000e+00
573 ; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[Y]], [[B_NEG]]
574 ; CHECK-NEXT: ret float [[Z]]
576 %X = fadd fast float -1.200000e+01, %A
577 %Y = fsub fast float %X, %B
578 %Z = fadd fast float %Y, 1.200000e+01