1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -reassociate -gvn -instcombine -S | FileCheck %s
3
4; With reassociation, constant folding can eliminate the 12 and -12 constants.
5define float @test1(float %arg) {
6; CHECK-LABEL: @test1(
7; CHECK-NEXT:    [[ARG_NEG:%.*]] = fneg fast float [[ARG:%.*]]
8; CHECK-NEXT:    ret float [[ARG_NEG]]
9;
10  %t1 = fsub fast float -1.200000e+01, %arg
11  %t2 = fadd fast float %t1, 1.200000e+01
12  ret float %t2
13}
14
15; Check again using the minimal subset of FMF.
16; Both 'reassoc' and 'nsz' are required.
17define float @test1_minimal(float %arg) {
18; CHECK-LABEL: @test1_minimal(
19; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc nsz float [[ARG:%.*]]
20; CHECK-NEXT:    ret float [[TMP1]]
21;
22  %t1 = fsub reassoc nsz float -1.200000e+01, %arg
23  %t2 = fadd reassoc nsz float %t1, 1.200000e+01
24  ret float %t2
25}
26
27; Verify the fold is not done with only 'reassoc' ('nsz' is required).
28define float @test1_reassoc(float %arg) {
29; CHECK-LABEL: @test1_reassoc(
30; CHECK-NEXT:    [[T1:%.*]] = fsub reassoc float -1.200000e+01, [[ARG:%.*]]
31; CHECK-NEXT:    [[T2:%.*]] = fadd reassoc float [[T1]], 1.200000e+01
32; CHECK-NEXT:    ret float [[T2]]
33;
34  %t1 = fsub reassoc float -1.200000e+01, %arg
35  %t2 = fadd reassoc float %t1, 1.200000e+01
36  ret float %t2
37}
38
39define float @test2(float %reg109, float %reg1111) {
40; CHECK-LABEL: @test2(
41; CHECK-NEXT:    [[REG115:%.*]] = fadd float [[REG109:%.*]], -3.000000e+01
42; CHECK-NEXT:    [[REG116:%.*]] = fadd float [[REG115]], [[REG1111:%.*]]
43; CHECK-NEXT:    [[REG117:%.*]] = fadd float [[REG116]], 3.000000e+01
44; CHECK-NEXT:    ret float [[REG117]]
45;
46  %reg115 = fadd float %reg109, -3.000000e+01
47  %reg116 = fadd float %reg115, %reg1111
48  %reg117 = fadd float %reg116, 3.000000e+01
49  ret float %reg117
50}
51
52define float @test3(float %reg109, float %reg1111) {
53; CHECK-LABEL: @test3(
54; CHECK-NEXT:    [[REG117:%.*]] = fadd fast float [[REG109:%.*]], [[REG1111:%.*]]
55; CHECK-NEXT:    ret float [[REG117]]
56;
57  %reg115 = fadd fast float %reg109, -3.000000e+01
58  %reg116 = fadd fast float %reg115, %reg1111
59  %reg117 = fadd fast float %reg116, 3.000000e+01
60  ret float %reg117
61}
62
63define float @test3_reassoc(float %reg109, float %reg1111) {
64; CHECK-LABEL: @test3_reassoc(
65; CHECK-NEXT:    [[REG115:%.*]] = fadd reassoc float [[REG109:%.*]], -3.000000e+01
66; CHECK-NEXT:    [[REG116:%.*]] = fadd reassoc float [[REG115]], [[REG1111:%.*]]
67; CHECK-NEXT:    [[REG117:%.*]] = fadd reassoc float [[REG116]], 3.000000e+01
68; CHECK-NEXT:    ret float [[REG117]]
69;
70  %reg115 = fadd reassoc float %reg109, -3.000000e+01
71  %reg116 = fadd reassoc float %reg115, %reg1111
72  %reg117 = fadd reassoc float %reg116, 3.000000e+01
73  ret float %reg117
74}
75
76@fe = external global float
77@fa = external global float
78@fb = external global float
79@fc = external global float
80@ff = external global float
81
82define void @test4() {
83; CHECK-LABEL: @test4(
84; CHECK-NEXT:    [[A:%.*]] = load float, float* @fa, align 4
85; CHECK-NEXT:    [[B:%.*]] = load float, float* @fb, align 4
86; CHECK-NEXT:    [[C:%.*]] = load float, float* @fc, align 4
87; CHECK-NEXT:    [[T1:%.*]] = fadd fast float [[B]], [[A]]
88; CHECK-NEXT:    [[T2:%.*]] = fadd fast float [[T1]], [[C]]
89; CHECK-NEXT:    store float [[T2]], float* @fe, align 4
90; CHECK-NEXT:    store float [[T2]], float* @ff, align 4
91; CHECK-NEXT:    ret void
92;
93  %A = load float, float* @fa
94  %B = load float, float* @fb
95  %C = load float, float* @fc
96  %t1 = fadd fast float %A, %B
97  %t2 = fadd fast float %t1, %C
98  %t3 = fadd fast float %C, %A
99  %t4 = fadd fast float %t3, %B
100  ; e = (a+b)+c;
101  store float %t2, float* @fe
102  ; f = (a+c)+b
103  store float %t4, float* @ff
104  ret void
105}
106
107define void @test5() {
108; CHECK-LABEL: @test5(
109; CHECK-NEXT:    [[A:%.*]] = load float, float* @fa, align 4
110; CHECK-NEXT:    [[B:%.*]] = load float, float* @fb, align 4
111; CHECK-NEXT:    [[C:%.*]] = load float, float* @fc, align 4
112; CHECK-NEXT:    [[T1:%.*]] = fadd fast float [[B]], [[A]]
113; CHECK-NEXT:    [[T2:%.*]] = fadd fast float [[T1]], [[C]]
114; CHECK-NEXT:    store float [[T2]], float* @fe, align 4
115; CHECK-NEXT:    store float [[T2]], float* @ff, align 4
116; CHECK-NEXT:    ret void
117;
118  %A = load float, float* @fa
119  %B = load float, float* @fb
120  %C = load float, float* @fc
121  %t1 = fadd fast float %A, %B
122  %t2 = fadd fast float %t1, %C
123  %t3 = fadd fast float %C, %A
124  %t4 = fadd fast float %t3, %B
125  ; e = c+(a+b)
126  store float %t2, float* @fe
127  ; f = (c+a)+b
128  store float %t4, float* @ff
129  ret void
130}
131
132define void @test6() {
133; CHECK-LABEL: @test6(
134; CHECK-NEXT:    [[A:%.*]] = load float, float* @fa, align 4
135; CHECK-NEXT:    [[B:%.*]] = load float, float* @fb, align 4
136; CHECK-NEXT:    [[C:%.*]] = load float, float* @fc, align 4
137; CHECK-NEXT:    [[T1:%.*]] = fadd fast float [[B]], [[A]]
138; CHECK-NEXT:    [[T2:%.*]] = fadd fast float [[T1]], [[C]]
139; CHECK-NEXT:    store float [[T2]], float* @fe, align 4
140; CHECK-NEXT:    store float [[T2]], float* @ff, align 4
141; CHECK-NEXT:    ret void
142;
143  %A = load float, float* @fa
144  %B = load float, float* @fb
145  %C = load float, float* @fc
146  %t1 = fadd fast float %B, %A
147  %t2 = fadd fast float %t1, %C
148  %t3 = fadd fast float %C, %A
149  %t4 = fadd fast float %t3, %B
150  ; e = c+(b+a)
151  store float %t2, float* @fe
152  ; f = (c+a)+b
153  store float %t4, float* @ff
154  ret void
155}
156
157define float @test7(float %A, float %B, float %C) {
158; CHECK-LABEL: @test7(
159; CHECK-NEXT:    [[REASS_ADD1:%.*]] = fadd fast float [[C:%.*]], [[B:%.*]]
160; CHECK-NEXT:    [[REASS_MUL2:%.*]] = fmul fast float [[A:%.*]], [[A]]
161; CHECK-NEXT:    [[REASS_MUL:%.*]] = fmul fast float [[REASS_MUL2]], [[REASS_ADD1]]
162; CHECK-NEXT:    ret float [[REASS_MUL]]
163;
164  %aa = fmul fast float %A, %A
165  %aab = fmul fast float %aa, %B
166  %ac = fmul fast float %A, %C
167  %aac = fmul fast float %ac, %A
168  %r = fadd fast float %aab, %aac
169  ret float %r
170}
171
172define float @test7_reassoc(float %A, float %B, float %C) {
173; CHECK-LABEL: @test7_reassoc(
174; CHECK-NEXT:    [[AA:%.*]] = fmul reassoc float [[A:%.*]], [[A]]
175; CHECK-NEXT:    [[AAB:%.*]] = fmul reassoc float [[AA]], [[B:%.*]]
176; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[A]], [[A]]
177; CHECK-NEXT:    [[AAC:%.*]] = fmul reassoc float [[TMP1]], [[C:%.*]]
178; CHECK-NEXT:    [[R:%.*]] = fadd reassoc float [[AAB]], [[AAC]]
179; CHECK-NEXT:    ret float [[R]]
180;
181  %aa = fmul reassoc float %A, %A
182  %aab = fmul reassoc float %aa, %B
183  %ac = fmul reassoc float %A, %C
184  %aac = fmul reassoc float %ac, %A
185  %r = fadd reassoc float %aab, %aac
186  ret float %r
187}
188
189; (-X)*Y + Z -> Z-X*Y
190
191define float @test8(float %X, float %Y, float %Z) {
192; CHECK-LABEL: @test8(
193; CHECK-NEXT:    [[A:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]]
194; CHECK-NEXT:    [[C:%.*]] = fsub fast float [[Z:%.*]], [[A]]
195; CHECK-NEXT:    ret float [[C]]
196;
197  %A = fsub fast float 0.0, %X
198  %B = fmul fast float %A, %Y
199  %C = fadd fast float %B, %Z
200  ret float %C
201}
202
203define float @test8_unary_fneg(float %X, float %Y, float %Z) {
204; CHECK-LABEL: @test8_unary_fneg(
205; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
206; CHECK-NEXT:    [[C:%.*]] = fsub fast float [[Z:%.*]], [[TMP1]]
207; CHECK-NEXT:    ret float [[C]]
208;
209  %A = fneg fast float %X
210  %B = fmul fast float %A, %Y
211  %C = fadd fast float %B, %Z
212  ret float %C
213}
214
215define float @test8_reassoc(float %X, float %Y, float %Z) {
216; CHECK-LABEL: @test8_reassoc(
217; CHECK-NEXT:    [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X:%.*]]
218; CHECK-NEXT:    [[B:%.*]] = fmul reassoc float [[A]], [[Y:%.*]]
219; CHECK-NEXT:    [[C:%.*]] = fadd reassoc float [[B]], [[Z:%.*]]
220; CHECK-NEXT:    ret float [[C]]
221;
222  %A = fsub reassoc float 0.0, %X
223  %B = fmul reassoc float %A, %Y
224  %C = fadd reassoc float %B, %Z
225  ret float %C
226}
227
228define float @test9(float %X) {
229; CHECK-LABEL: @test9(
230; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 9.400000e+01
231; CHECK-NEXT:    ret float [[FACTOR]]
232;
233  %Y = fmul fast float %X, 4.700000e+01
234  %Z = fadd fast float %Y, %Y
235  ret float %Z
236}
237
238; Check again with 'reassoc' and 'nsz' ('nsz' not technically required).
239define float @test9_reassoc_nsz(float %X) {
240; CHECK-LABEL: @test9_reassoc_nsz(
241; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], 9.400000e+01
242; CHECK-NEXT:    ret float [[TMP1]]
243;
244  %Y = fmul reassoc nsz float %X, 4.700000e+01
245  %Z = fadd reassoc nsz float %Y, %Y
246  ret float %Z
247}
248
249; TODO: This doesn't require 'nsz'.  It should fold to X * 94.0
250define float @test9_reassoc(float %X) {
251; CHECK-LABEL: @test9_reassoc(
252; CHECK-NEXT:    [[Y:%.*]] = fmul reassoc float [[X:%.*]], 4.700000e+01
253; CHECK-NEXT:    [[Z:%.*]] = fadd reassoc float [[Y]], [[Y]]
254; CHECK-NEXT:    ret float [[Z]]
255;
256  %Y = fmul reassoc float %X, 4.700000e+01
257  %Z = fadd reassoc float %Y, %Y
258  ret float %Z
259}
260
261; Side note: (x + x + x) and (3*x) each have only a single rounding.  So
262; transforming x+x+x to 3*x is always safe, even without any FMF.
263; To avoid that special-case, we have the addition of 'x' four times, here.
264define float @test10(float %X) {
265; CHECK-LABEL: @test10(
266; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 4.000000e+00
267; CHECK-NEXT:    ret float [[FACTOR]]
268;
269  %Y = fadd fast float %X ,%X
270  %Z = fadd fast float %Y, %X
271  %W = fadd fast float %Z, %X
272  ret float %W
273}
274
275; Check again with 'reassoc' and 'nsz' ('nsz' not technically required).
276define float @test10_reassoc_nsz(float %X) {
277; CHECK-LABEL: @test10_reassoc_nsz(
278; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.000000e+00
279; CHECK-NEXT:    ret float [[TMP1]]
280;
281  %Y = fadd reassoc nsz float %X ,%X
282  %Z = fadd reassoc nsz float %Y, %X
283  %W = fadd reassoc nsz float %Z, %X
284  ret float %W
285}
286
287; TODO: This doesn't require 'nsz'.  It should fold to 4 * x
288define float @test10_reassoc(float %X) {
289; CHECK-LABEL: @test10_reassoc(
290; CHECK-NEXT:    [[Y:%.*]] = fadd reassoc float [[X:%.*]], [[X]]
291; CHECK-NEXT:    [[Z:%.*]] = fadd reassoc float [[Y]], [[X]]
292; CHECK-NEXT:    [[W:%.*]] = fadd reassoc float [[Z]], [[X]]
293; CHECK-NEXT:    ret float [[W]]
294;
295  %Y = fadd reassoc float %X ,%X
296  %Z = fadd reassoc float %Y, %X
297  %W = fadd reassoc float %Z, %X
298  ret float %W
299}
300
301define float @test11(float %W) {
302; CHECK-LABEL: @test11(
303; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast float [[W:%.*]], 3.810000e+02
304; CHECK-NEXT:    ret float [[FACTOR]]
305;
306  %X = fmul fast float %W, 127.0
307  %Y = fadd fast float %X ,%X
308  %Z = fadd fast float %Y, %X
309  ret float %Z
310}
311
312; Check again using the minimal subset of FMF.
313; Check again with 'reassoc' and 'nsz' ('nsz' not technically required).
314define float @test11_reassoc_nsz(float %W) {
315; CHECK-LABEL: @test11_reassoc_nsz(
316; CHECK-NEXT:    [[Z:%.*]] = fmul reassoc nsz float [[W:%.*]], 3.810000e+02
317; CHECK-NEXT:    ret float [[Z]]
318;
319  %X = fmul reassoc nsz float %W, 127.0
320  %Y = fadd reassoc nsz float %X ,%X
321  %Z = fadd reassoc nsz float %Y, %X
322  ret float %Z
323}
324
325; TODO: This doesn't require 'nsz'.  It should fold to W*381.0.
326define float @test11_reassoc(float %W) {
327; CHECK-LABEL: @test11_reassoc(
328; CHECK-NEXT:    [[X:%.*]] = fmul reassoc float [[W:%.*]], 1.270000e+02
329; CHECK-NEXT:    [[Y:%.*]] = fadd reassoc float [[X]], [[X]]
330; CHECK-NEXT:    [[Z:%.*]] = fadd reassoc float [[X]], [[Y]]
331; CHECK-NEXT:    ret float [[Z]]
332;
333  %X = fmul reassoc float %W, 127.0
334  %Y = fadd reassoc float %X ,%X
335  %Z = fadd reassoc float %Y, %X
336  ret float %Z
337}
338
339define float @test12(float %X) {
340; CHECK-LABEL: @test12(
341; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast float [[X:%.*]], -3.000000e+00
342; CHECK-NEXT:    [[Z:%.*]] = fadd fast float [[FACTOR]], 6.000000e+00
343; CHECK-NEXT:    ret float [[Z]]
344;
345  %A = fsub fast float 1.000000e+00, %X
346  %B = fsub fast float 2.000000e+00, %X
347  %C = fsub fast float 3.000000e+00, %X
348  %Y = fadd fast float %A ,%B
349  %Z = fadd fast float %Y, %C
350  ret float %Z
351}
352
353; Check again with 'reassoc' and 'nsz' ('nsz' not technically required).
354define float @test12_reassoc_nsz(float %X) {
355; CHECK-LABEL: @test12_reassoc_nsz(
356; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], -3.000000e+00
357; CHECK-NEXT:    [[TMP2:%.*]] = fadd reassoc nsz float [[TMP1]], 6.000000e+00
358; CHECK-NEXT:    ret float [[TMP2]]
359;
360  %A = fsub reassoc nsz float 1.000000e+00, %X
361  %B = fsub reassoc nsz float 2.000000e+00, %X
362  %C = fsub reassoc nsz float 3.000000e+00, %X
363  %Y = fadd reassoc nsz float %A ,%B
364  %Z = fadd reassoc nsz float %Y, %C
365  ret float %Z
366}
367
368; TODO: This doesn't require 'nsz'.  It should fold to (6.0 - 3.0*x)
369define float @test12_reassoc(float %X) {
370; CHECK-LABEL: @test12_reassoc(
371; CHECK-NEXT:    [[A:%.*]] = fsub reassoc float 1.000000e+00, [[X:%.*]]
372; CHECK-NEXT:    [[B:%.*]] = fsub reassoc float 2.000000e+00, [[X]]
373; CHECK-NEXT:    [[C:%.*]] = fsub reassoc float 3.000000e+00, [[X]]
374; CHECK-NEXT:    [[Y:%.*]] = fadd reassoc float [[A]], [[B]]
375; CHECK-NEXT:    [[Z:%.*]] = fadd reassoc float [[C]], [[Y]]
376; CHECK-NEXT:    ret float [[Z]]
377;
378  %A = fsub reassoc float 1.000000e+00, %X
379  %B = fsub reassoc float 2.000000e+00, %X
380  %C = fsub reassoc float 3.000000e+00, %X
381  %Y = fadd reassoc float %A ,%B
382  %Z = fadd reassoc float %Y, %C
383  ret float %Z
384}
385
386define float @test13(float %X1, float %X2, float %X3) {
387; CHECK-LABEL: @test13(
388; CHECK-NEXT:    [[REASS_ADD:%.*]] = fsub fast float [[X3:%.*]], [[X2:%.*]]
389; CHECK-NEXT:    [[REASS_MUL:%.*]] = fmul fast float [[REASS_ADD]], [[X1:%.*]]
390; CHECK-NEXT:    ret float [[REASS_MUL]]
391;
392  %A = fsub fast float 0.000000e+00, %X1
393  %B = fmul fast float %A, %X2   ; -X1*X2
394  %C = fmul fast float %X1, %X3  ; X1*X3
395  %D = fadd fast float %B, %C    ; -X1*X2 + X1*X3 -> X1*(X3-X2)
396  ret float %D
397}
398
399define float @test13_unary_fneg(float %X1, float %X2, float %X3) {
400; CHECK-LABEL: @test13_unary_fneg(
401; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast float [[X3:%.*]], [[X2:%.*]]
402; CHECK-NEXT:    [[D:%.*]] = fmul fast float [[TMP1]], [[X1:%.*]]
403; CHECK-NEXT:    ret float [[D]]
404;
405  %A = fneg fast float %X1
406  %B = fmul fast float %A, %X2   ; -X1*X2
407  %C = fmul fast float %X1, %X3  ; X1*X3
408  %D = fadd fast float %B, %C    ; -X1*X2 + X1*X3 -> X1*(X3-X2)
409  ret float %D
410}
411
412define float @test13_reassoc(float %X1, float %X2, float %X3) {
413; CHECK-LABEL: @test13_reassoc(
414; CHECK-NEXT:    [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X1:%.*]]
415; CHECK-NEXT:    [[B:%.*]] = fmul reassoc float [[A]], [[X2:%.*]]
416; CHECK-NEXT:    [[C:%.*]] = fmul reassoc float [[X1]], [[X3:%.*]]
417; CHECK-NEXT:    [[D:%.*]] = fadd reassoc float [[B]], [[C]]
418; CHECK-NEXT:    ret float [[D]]
419;
420  %A = fsub reassoc float 0.000000e+00, %X1
421  %B = fmul reassoc float %A, %X2   ; -X1*X2
422  %C = fmul reassoc float %X1, %X3  ; X1*X3
423  %D = fadd reassoc float %B, %C    ; -X1*X2 + X1*X3 -> X1*(X3-X2)
424  ret float %D
425}
426
427define float @test14(float %X1, float %X2) {
428; CHECK-LABEL: @test14(
429; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast float [[X1:%.*]], [[X2:%.*]]
430; CHECK-NEXT:    [[D1:%.*]] = fmul fast float [[TMP1]], 4.700000e+01
431; CHECK-NEXT:    ret float [[D1]]
432;
433  %B = fmul fast float %X1, 47.   ; X1*47
434  %C = fmul fast float %X2, -47.  ; X2*-47
435  %D = fadd fast float %B, %C    ; X1*47 + X2*-47 -> 47*(X1-X2)
436  ret float %D
437}
438
439; (x1 * 47) + (x2 * -47) => (x1 - x2) * 47
440; Check again with 'reassoc' and 'nsz' ('nsz' not technically required).
441define float @test14_reassoc_nsz(float %X1, float %X2) {
442; CHECK-LABEL: @test14_reassoc_nsz(
443; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X1:%.*]], [[X2:%.*]]
444; CHECK-NEXT:    [[D1:%.*]] = fmul reassoc nsz float [[TMP1]], 4.700000e+01
445; CHECK-NEXT:    ret float [[D1]]
446;
447  %B = fmul reassoc nsz float %X1, 47.   ; X1*47
448  %C = fmul reassoc nsz float %X2, -47.  ; X2*-47
449  %D = fadd reassoc nsz float %B, %C    ; X1*47 + X2*-47 -> 47*(X1-X2)
450  ret float %D
451}
452
453; TODO: This doesn't require 'nsz'.  It should fold to ((x1 - x2) * 47.0)
454define float @test14_reassoc(float %X1, float %X2) {
455; CHECK-LABEL: @test14_reassoc(
456; CHECK-NEXT:    [[B:%.*]] = fmul reassoc float [[X1:%.*]], 4.700000e+01
457; CHECK-NEXT:    [[C:%.*]] = fmul reassoc float [[X2:%.*]], 4.700000e+01
458; CHECK-NEXT:    [[D1:%.*]] = fsub reassoc float [[B]], [[C]]
459; CHECK-NEXT:    ret float [[D1]]
460;
461  %B = fmul reassoc float %X1, 47.   ; X1*47
462  %C = fmul reassoc float %X2, -47.  ; X2*-47
463  %D = fadd reassoc float %B, %C    ; X1*47 + X2*-47 -> 47*(X1-X2)
464  ret float %D
465}
466
467define float @test15(float %arg) {
468; CHECK-LABEL: @test15(
469; CHECK-NEXT:    [[T2:%.*]] = fmul fast float [[ARG:%.*]], 1.440000e+02
470; CHECK-NEXT:    ret float [[T2]]
471;
472  %t1 = fmul fast float 1.200000e+01, %arg
473  %t2 = fmul fast float %t1, 1.200000e+01
474  ret float %t2
475}
476
477define float @test15_reassoc(float %arg) {
478; CHECK-LABEL: @test15_reassoc(
479; CHECK-NEXT:    [[T2:%.*]] = fmul reassoc float [[ARG:%.*]], 1.440000e+02
480; CHECK-NEXT:    ret float [[T2]]
481;
482  %t1 = fmul reassoc float 1.200000e+01, %arg
483  %t2 = fmul reassoc float %t1, 1.200000e+01
484  ret float %t2
485}
486
487; (b+(a+1234))+-a -> b+1234
488define float @test16(float %b, float %a) {
489; CHECK-LABEL: @test16(
490; CHECK-NEXT:    [[TMP1:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
491; CHECK-NEXT:    ret float [[TMP1]]
492;
493  %1 = fadd fast float %a, 1234.0
494  %2 = fadd fast float %b, %1
495  %3 = fsub fast float 0.0, %a
496  %4 = fadd fast float %2, %3
497  ret float %4
498}
499
500define float @test16_unary_fneg(float %b, float %a) {
501; CHECK-LABEL: @test16_unary_fneg(
502; CHECK-NEXT:    [[TMP1:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03
503; CHECK-NEXT:    ret float [[TMP1]]
504;
505  %1 = fadd fast float %a, 1234.0
506  %2 = fadd fast float %b, %1
507  %3 = fneg fast float %a
508  %4 = fadd fast float %2, %3
509  ret float %4
510}
511
512define float @test16_reassoc(float %b, float %a) {
513; CHECK-LABEL: @test16_reassoc(
514; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc float [[A:%.*]], 1.234000e+03
515; CHECK-NEXT:    [[TMP2:%.*]] = fadd reassoc float [[TMP1]], [[B:%.*]]
516; CHECK-NEXT:    [[TMP3:%.*]] = fsub reassoc float 0.000000e+00, [[A]]
517; CHECK-NEXT:    [[TMP4:%.*]] = fadd reassoc float [[TMP3]], [[TMP2]]
518; CHECK-NEXT:    ret float [[TMP4]]
519;
520  %1 = fadd reassoc float %a, 1234.0
521  %2 = fadd reassoc float %b, %1
522  %3 = fsub reassoc float 0.0, %a
523  %4 = fadd reassoc float %2, %3
524  ret float %4
525}
526
527; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z.
528
529define float @test17(float %a, float %b, float %z) {
530; CHECK-LABEL: @test17(
531; CHECK-NEXT:    [[E:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
532; CHECK-NEXT:    [[F:%.*]] = fmul fast float [[E]], [[B:%.*]]
533; CHECK-NEXT:    [[G:%.*]] = fmul fast float [[F]], [[Z:%.*]]
534; CHECK-NEXT:    ret float [[G]]
535;
536  %c = fsub fast float 0.000000e+00, %z
537  %d = fmul fast float %a, %b
538  %e = fmul fast float %c, %d
539  %f = fmul fast float %e, 1.234500e+04
540  %g = fsub fast float 0.000000e+00, %f
541  ret float %g
542}
543
544define float @test17_unary_fneg(float %a, float %b, float %z) {
545; CHECK-LABEL: @test17_unary_fneg(
546; CHECK-NEXT:    [[D:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04
547; CHECK-NEXT:    [[E:%.*]] = fmul fast float [[D]], [[B:%.*]]
548; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[E]], [[Z:%.*]]
549; CHECK-NEXT:    ret float [[TMP1]]
550;
551  %c = fneg fast float %z
552  %d = fmul fast float %a, %b
553  %e = fmul fast float %c, %d
554  %f = fmul fast float %e, 1.234500e+04
555  %g = fneg fast float %f
556  ret float %g
557}
558
559define float @test17_reassoc(float %a, float %b, float %z) {
560; CHECK-LABEL: @test17_reassoc(
561; CHECK-NEXT:    [[C:%.*]] = fsub reassoc float 0.000000e+00, [[Z:%.*]]
562; CHECK-NEXT:    [[D:%.*]] = fmul reassoc float [[A:%.*]], [[B:%.*]]
563; CHECK-NEXT:    [[E:%.*]] = fmul reassoc float [[D]], [[C]]
564; CHECK-NEXT:    [[F:%.*]] = fmul reassoc float [[E]], 1.234500e+04
565; CHECK-NEXT:    [[G:%.*]] = fsub reassoc float 0.000000e+00, [[F]]
566; CHECK-NEXT:    ret float [[G]]
567;
568  %c = fsub reassoc float 0.000000e+00, %z
569  %d = fmul reassoc float %a, %b
570  %e = fmul reassoc float %c, %d
571  %f = fmul reassoc float %e, 1.234500e+04
572  %g = fsub reassoc float 0.000000e+00, %f
573  ret float %g
574}
575
576define float @test18(float %a, float %b, float %z) {
577; CHECK-LABEL: @test18(
578; CHECK-NEXT:    [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
579; CHECK-NEXT:    [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
580; CHECK-NEXT:    ret float [[F]]
581;
582  %d = fmul fast float %z, 4.000000e+01
583  %c = fsub fast float 0.000000e+00, %d
584  %e = fmul fast float %a, %c
585  %f = fsub fast float 0.000000e+00, %e
586  ret float %f
587}
588
589define float @test18_unary_fneg(float %a, float %b, float %z) {
590; CHECK-LABEL: @test18_unary_fneg(
591; CHECK-NEXT:    [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
592; CHECK-NEXT:    [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
593; CHECK-NEXT:    ret float [[F]]
594;
595  %d = fmul fast float %z, 4.000000e+01
596  %c = fneg fast float %d
597  %e = fmul fast float %a, %c
598  %f = fneg fast float %e
599  ret float %f
600}
601
602define float @test18_reassoc(float %a, float %b, float %z) {
603; CHECK-LABEL: @test18_reassoc(
604; CHECK-NEXT:    [[D:%.*]] = fmul reassoc float [[Z:%.*]], 4.000000e+01
605; CHECK-NEXT:    [[C:%.*]] = fsub reassoc float 0.000000e+00, [[D]]
606; CHECK-NEXT:    [[E:%.*]] = fmul reassoc float [[C]], [[A:%.*]]
607; CHECK-NEXT:    [[F:%.*]] = fsub reassoc float 0.000000e+00, [[E]]
608; CHECK-NEXT:    ret float [[F]]
609;
610  %d = fmul reassoc float %z, 4.000000e+01
611  %c = fsub reassoc float 0.000000e+00, %d
612  %e = fmul reassoc float %a, %c
613  %f = fsub reassoc float 0.000000e+00, %e
614  ret float %f
615}
616
617; fneg of fneg is an identity operation, so no FMF are needed to remove those instructions.
618
619define float @test18_unary_fneg_no_FMF(float %a, float %b, float %z) {
620; CHECK-LABEL: @test18_unary_fneg_no_FMF(
621; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[Z:%.*]], 4.000000e+01
622; CHECK-NEXT:    [[F:%.*]] = fmul float [[TMP1]], [[A:%.*]]
623; CHECK-NEXT:    ret float [[F]]
624;
625  %d = fmul float %z, 4.000000e+01
626  %c = fneg float %d
627  %e = fmul float %a, %c
628  %f = fneg float %e
629  ret float %f
630}
631
632define float @test18_reassoc_unary_fneg(float %a, float %b, float %z) {
633; CHECK-LABEL: @test18_reassoc_unary_fneg(
634; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[Z:%.*]], 4.000000e+01
635; CHECK-NEXT:    [[F:%.*]] = fmul reassoc float [[TMP1]], [[A:%.*]]
636; CHECK-NEXT:    ret float [[F]]
637;
638  %d = fmul reassoc float %z, 4.000000e+01
639  %c = fneg reassoc float %d
640  %e = fmul reassoc float %a, %c
641  %f = fneg reassoc float %e
642  ret float %f
643}
644
645; With sub reassociation, constant folding can eliminate the 12 and -12 constants.
646define float @test19(float %A, float %B) {
647; CHECK-LABEL: @test19(
648; CHECK-NEXT:    [[Z:%.*]] = fsub fast float [[A:%.*]], [[B:%.*]]
649; CHECK-NEXT:    ret float [[Z]]
650;
651  %X = fadd fast float -1.200000e+01, %A
652  %Y = fsub fast float %X, %B
653  %Z = fadd fast float %Y, 1.200000e+01
654  ret float %Z
655}
656
657define float @test19_reassoc(float %A, float %B) {
658; CHECK-LABEL: @test19_reassoc(
659; CHECK-NEXT:    [[X:%.*]] = fadd reassoc float [[A:%.*]], -1.200000e+01
660; CHECK-NEXT:    [[Y:%.*]] = fsub reassoc float [[X]], [[B:%.*]]
661; CHECK-NEXT:    [[Z:%.*]] = fadd reassoc float [[Y]], 1.200000e+01
662; CHECK-NEXT:    ret float [[Z]]
663;
664  %X = fadd reassoc float -1.200000e+01, %A
665  %Y = fsub reassoc float %X, %B
666  %Z = fadd reassoc float %Y, 1.200000e+01
667  ret float %Z
668}
669
670; With sub reassociation, constant folding can eliminate the uses of %a.
671define float @test20(float %a, float %b, float %c) nounwind  {
672; CHECK-LABEL: @test20(
673; CHECK-NEXT:    [[TMP1:%.*]] = fadd fast float [[B:%.*]], [[C:%.*]]
674; CHECK-NEXT:    [[T7:%.*]] = fneg fast float [[TMP1]]
675; CHECK-NEXT:    ret float [[T7]]
676;
677  %t3 = fsub fast float %a, %b
678  %t5 = fsub fast float %t3, %c
679  %t7 = fsub fast float %t5, %a
680  ret float %t7
681}
682
683define float @test20_reassoc(float %a, float %b, float %c) nounwind  {
684; CHECK-LABEL: @test20_reassoc(
685; CHECK-NEXT:    [[T3:%.*]] = fsub reassoc float [[A:%.*]], [[B:%.*]]
686; CHECK-NEXT:    [[T5:%.*]] = fsub reassoc float [[T3]], [[C:%.*]]
687; CHECK-NEXT:    [[T7:%.*]] = fsub reassoc float [[T5]], [[A]]
688; CHECK-NEXT:    ret float [[T7]]
689;
690  %t3 = fsub reassoc float %a, %b
691  %t5 = fsub reassoc float %t3, %c
692  %t7 = fsub reassoc float %t5, %a
693  ret float %t7
694}
695
696