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