xref: /llvm-project/llvm/test/Transforms/InstCombine/fadd.ll (revision 02328e0465c256293950542f1a85eb55bcbc9d45)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3; RUN: opt < %s -passes=instcombine -use-constant-fp-for-fixed-length-splat -S | FileCheck %s
4
5declare void @use(float)
6declare void @use_vec(<2 x float>)
7declare float @llvm.vector.reduce.fadd.v4f32(float, <4 x float>)
8
9; -x + y => y - x
10
11define float @fneg_op0(float %x, float %y) {
12; CHECK-LABEL: @fneg_op0(
13; CHECK-NEXT:    [[ADD:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
14; CHECK-NEXT:    ret float [[ADD]]
15;
16  %neg = fsub float -0.0, %x
17  %add = fadd float %neg, %y
18  ret float %add
19}
20
21; x + -y => x - y
22
23define float @fneg_op1(float %x, float %y) {
24; CHECK-LABEL: @fneg_op1(
25; CHECK-NEXT:    [[ADD:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
26; CHECK-NEXT:    ret float [[ADD]]
27;
28  %neg = fsub float -0.0, %y
29  %add = fadd float %x, %neg
30  ret float %add
31}
32
33; Z + (-X / Y) --> Z - (X / Y)
34
35define double @fdiv_fneg1(double %x, double %y, double %pz) {
36; CHECK-LABEL: @fdiv_fneg1(
37; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
38; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
39; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
40; CHECK-NEXT:    ret double [[R]]
41;
42  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
43  %neg = fsub double -0.000000e+00, %x
44  %div = fdiv double %neg, %y
45  %r = fadd double %z, %div
46  ret double %r
47}
48
49; Z + (Y / -X) --> Z - (Y / X)
50
51define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
52; CHECK-LABEL: @fdiv_fneg2(
53; CHECK-NEXT:    [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
54; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
55; CHECK-NEXT:    [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
56; CHECK-NEXT:    ret <2 x double> [[R]]
57;
58  %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
59  %neg = fsub <2 x double> <double -0.0, double -0.0>, %x
60  %div = fdiv <2 x double> %y, %neg
61  %r = fadd <2 x double> %z, %div
62  ret <2 x double> %r
63}
64
65; Z + (-X * Y) --> Z - (X * Y)
66
67define double @fmul_fneg1(double %x, double %y, double %pz) {
68; CHECK-LABEL: @fmul_fneg1(
69; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
70; CHECK-NEXT:    [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
71; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
72; CHECK-NEXT:    ret double [[R]]
73;
74  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
75  %neg = fsub double -0.000000e+00, %x
76  %mul = fmul double %neg, %y
77  %r = fadd double %z, %mul
78  ret double %r
79}
80
81; Z + (Y * -X) --> Z - (Y * X)
82
83define double @fmul_fneg2(double %x, double %py, double %pz) {
84; CHECK-LABEL: @fmul_fneg2(
85; CHECK-NEXT:    [[Y:%.*]] = frem double -4.200000e+01, [[PY:%.*]]
86; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
87; CHECK-NEXT:    [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]]
88; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
89; CHECK-NEXT:    ret double [[R]]
90;
91  %y = frem double -42.0, %py ; thwart complexity-based canonicalization
92  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
93  %neg = fsub double -0.000000e+00, %x
94  %mul = fmul double %y, %neg
95  %r = fadd double %z, %mul
96  ret double %r
97}
98
99; (-X / Y) + Z --> Z - (X / Y)
100
101define double @fdiv_fneg1_commute(double %x, double %y, double %pz) {
102; CHECK-LABEL: @fdiv_fneg1_commute(
103; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
104; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
105; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
106; CHECK-NEXT:    ret double [[R]]
107;
108  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
109  %neg = fsub double -0.000000e+00, %x
110  %div = fdiv double %neg, %y
111  %r = fadd double %div, %z
112  ret double %r
113}
114
115; (Y / -X) + Z --> Z - (Y / X)
116
117define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
118; CHECK-LABEL: @fdiv_fneg2_commute(
119; CHECK-NEXT:    [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
120; CHECK-NEXT:    [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
121; CHECK-NEXT:    [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
122; CHECK-NEXT:    ret <2 x double> [[R]]
123;
124  %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
125  %neg = fsub <2 x double> <double -0.0, double -0.0>, %x
126  %div = fdiv <2 x double> %y, %neg
127  %r = fadd <2 x double> %div, %z
128  ret <2 x double> %r
129}
130
131; (-X * Y) + Z --> Z - (X * Y)
132
133define double @fmul_fneg1_commute(double %x, double %y, double %pz) {
134; CHECK-LABEL: @fmul_fneg1_commute(
135; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
136; CHECK-NEXT:    [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
137; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
138; CHECK-NEXT:    ret double [[R]]
139;
140  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
141  %neg = fsub double -0.000000e+00, %x
142  %mul = fmul double %neg, %y
143  %r = fadd double %mul, %z
144  ret double %r
145}
146
147; (Y * -X) + Z --> Z - (Y * X)
148
149define double @fmul_fneg2_commute(double %x, double %py, double %pz) {
150; CHECK-LABEL: @fmul_fneg2_commute(
151; CHECK-NEXT:    [[Y:%.*]] = frem double 4.100000e+01, [[PY:%.*]]
152; CHECK-NEXT:    [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
153; CHECK-NEXT:    [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]]
154; CHECK-NEXT:    [[R:%.*]] = fsub double [[Z]], [[TMP1]]
155; CHECK-NEXT:    ret double [[R]]
156;
157  %y = frem double 41.0, %py ; thwart complexity-based canonicalization
158  %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
159  %neg = fsub double -0.000000e+00, %x
160  %mul = fmul double %y, %neg
161  %r = fadd double %mul, %z
162  ret double %r
163}
164
165; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction
166
167define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) {
168; CHECK-LABEL: @fdiv_fneg1_extra_use(
169; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
170; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
171; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
172; CHECK-NEXT:    call void @use(float [[DIV]])
173; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[DIV]]
174; CHECK-NEXT:    ret float [[R]]
175;
176  %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
177  %neg = fsub float -0.000000e+00, %x
178  %div = fdiv float %neg, %y
179  call void @use(float %div)
180  %r = fadd float %z, %div
181  ret float %r
182}
183
184; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction
185
186define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) {
187; CHECK-LABEL: @fdiv_fneg2_extra_use(
188; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
189; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
190; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
191; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[Y]], [[NEG]]
192; CHECK-NEXT:    call void @use(float [[DIV]])
193; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[DIV]]
194; CHECK-NEXT:    ret float [[R]]
195;
196  %y = frem float -42.0, %py ; thwart complexity-based canonicalization
197  %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
198  %neg = fsub float -0.000000e+00, %x
199  %div = fdiv float %y, %neg
200  call void @use(float %div)
201  %r = fadd float %z, %div
202  ret float %r
203}
204
205; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction
206
207define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) {
208; CHECK-LABEL: @fmul_fneg1_extra_use(
209; CHECK-NEXT:    [[Z:%.*]] = frem <2 x float> <float 4.200000e+01, float -1.000000e+00>, [[PZ:%.*]]
210; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
211; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]
212; CHECK-NEXT:    call void @use_vec(<2 x float> [[MUL]])
213; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]]
214; CHECK-NEXT:    ret <2 x float> [[R]]
215;
216  %z = frem <2 x float> <float 42.0, float -1.0>, %pz ; thwart complexity-based canonicalization
217  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
218  %mul = fmul <2 x float> %neg, %y
219  call void @use_vec(<2 x float> %mul)
220  %r = fadd <2 x float> %z, %mul
221  ret <2 x float> %r
222}
223
224; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction
225
226define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) {
227; CHECK-LABEL: @fmul_fneg2_extra_use(
228; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
229; CHECK-NEXT:    [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
230; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
231; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
232; CHECK-NEXT:    call void @use(float [[MUL]])
233; CHECK-NEXT:    [[R:%.*]] = fadd float [[Z]], [[MUL]]
234; CHECK-NEXT:    ret float [[R]]
235;
236  %y = frem float -42.0, %py ; thwart complexity-based canonicalization
237  %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
238  %neg = fsub float -0.000000e+00, %x
239  %mul = fmul float %y, %neg
240  call void @use(float %mul)
241  %r = fadd float %z, %mul
242  ret float %r
243}
244
245; (-X / Y) + Z --> Z - (X / Y)
246
247define float @fdiv_fneg1_extra_use2(float %x, float %y, float %z) {
248; CHECK-LABEL: @fdiv_fneg1_extra_use2(
249; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
250; CHECK-NEXT:    call void @use(float [[NEG]])
251; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]
252; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
253; CHECK-NEXT:    ret float [[R]]
254;
255  %neg = fsub float -0.000000e+00, %x
256  call void @use(float %neg)
257  %div = fdiv float %neg, %y
258  %r = fadd float %div, %z
259  ret float %r
260}
261
262; (Y / -X) + Z --> Z - (Y / X)
263
264define float @fdiv_fneg2_extra_use2(float %x, float %y, float %z) {
265; CHECK-LABEL: @fdiv_fneg2_extra_use2(
266; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
267; CHECK-NEXT:    call void @use(float [[NEG]])
268; CHECK-NEXT:    [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]
269; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
270; CHECK-NEXT:    ret float [[R]]
271;
272  %neg = fsub float -0.000000e+00, %x
273  call void @use(float %neg)
274  %div = fdiv float %y, %neg
275  %r = fadd float %div, %z
276  ret float %r
277}
278
279; (-X * Y) + Z --> Z - (X * Y)
280
281define <2 x float> @fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
282; CHECK-LABEL: @fmul_fneg1_extra_use2(
283; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
284; CHECK-NEXT:    call void @use_vec(<2 x float> [[NEG]])
285; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]
286; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[TMP1]]
287; CHECK-NEXT:    ret <2 x float> [[R]]
288;
289  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
290  call void @use_vec(<2 x float> %neg)
291  %mul = fmul <2 x float> %neg, %y
292  %r = fadd <2 x float> %mul, %z
293  ret <2 x float> %r
294}
295
296; (Y * -X) + Z --> Z - (Y * X)
297
298define float @fmul_fneg2_extra_use2(float %x, float %py, float %z) {
299; CHECK-LABEL: @fmul_fneg2_extra_use2(
300; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
301; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
302; CHECK-NEXT:    call void @use(float [[NEG]])
303; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X]], [[Y]]
304; CHECK-NEXT:    [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
305; CHECK-NEXT:    ret float [[R]]
306;
307  %y = frem float -42.0, %py ; thwart complexity-based canonicalization
308  %neg = fsub float -0.000000e+00, %x
309  call void @use(float %neg)
310  %mul = fmul float %y, %neg
311  %r = fadd float %mul, %z
312  ret float %r
313}
314
315; (-X / Y) + Z --> Z - (X / Y)
316
317define float @fdiv_fneg1_extra_use3(float %x, float %y, float %z) {
318; CHECK-LABEL: @fdiv_fneg1_extra_use3(
319; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
320; CHECK-NEXT:    call void @use(float [[NEG]])
321; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
322; CHECK-NEXT:    call void @use(float [[DIV]])
323; CHECK-NEXT:    [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
324; CHECK-NEXT:    ret float [[R]]
325;
326  %neg = fsub float -0.000000e+00, %x
327  call void @use(float %neg)
328  %div = fdiv float %neg, %y
329  call void @use(float %div)
330  %r = fadd float %div, %z
331  ret float %r
332}
333
334; (Y / -X) + Z --> Z - (Y / X)
335
336define float @fdiv_fneg2_extra_use3(float %x, float %y, float %z) {
337; CHECK-LABEL: @fdiv_fneg2_extra_use3(
338; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
339; CHECK-NEXT:    call void @use(float [[NEG]])
340; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
341; CHECK-NEXT:    call void @use(float [[DIV]])
342; CHECK-NEXT:    [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
343; CHECK-NEXT:    ret float [[R]]
344;
345  %neg = fsub float -0.000000e+00, %x
346  call void @use(float %neg)
347  %div = fdiv float %y, %neg
348  call void @use(float %div)
349  %r = fadd float %div, %z
350  ret float %r
351}
352
353; (-X * Y) + Z --> Z - (X * Y)
354
355define <2 x float> @fmul_fneg1_extra_use3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
356; CHECK-LABEL: @fmul_fneg1_extra_use3(
357; CHECK-NEXT:    [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
358; CHECK-NEXT:    call void @use_vec(<2 x float> [[NEG]])
359; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]
360; CHECK-NEXT:    call void @use_vec(<2 x float> [[MUL]])
361; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[MUL]], [[Z:%.*]]
362; CHECK-NEXT:    ret <2 x float> [[R]]
363;
364  %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
365  call void @use_vec(<2 x float> %neg)
366  %mul = fmul <2 x float> %neg, %y
367  call void @use_vec(<2 x float> %mul)
368  %r = fadd <2 x float> %mul, %z
369  ret <2 x float> %r
370}
371
372; (Y * -X) + Z --> Z - (Y * X)
373
374define float @fmul_fneg2_extra_use3(float %x, float %py, float %z) {
375; CHECK-LABEL: @fmul_fneg2_extra_use3(
376; CHECK-NEXT:    [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
377; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
378; CHECK-NEXT:    call void @use(float [[NEG]])
379; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
380; CHECK-NEXT:    call void @use(float [[MUL]])
381; CHECK-NEXT:    [[R:%.*]] = fadd float [[MUL]], [[Z:%.*]]
382; CHECK-NEXT:    ret float [[R]]
383;
384  %y = frem float -42.0, %py ; thwart complexity-based canonicalization
385  %neg = fsub float -0.000000e+00, %x
386  call void @use(float %neg)
387  %mul = fmul float %y, %neg
388  call void @use(float %mul)
389  %r = fadd float %mul, %z
390  ret float %r
391}
392
393define float @fadd_rdx(float %x, <4 x float> %v) {
394; CHECK-LABEL: @fadd_rdx(
395; CHECK-NEXT:    [[ADD:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float [[X:%.*]], <4 x float> [[V:%.*]])
396; CHECK-NEXT:    ret float [[ADD]]
397;
398  %rdx = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
399  %add = fadd fast float %rdx, %x
400  ret float %add
401}
402
403define float @fadd_rdx_commute(float %x, <4 x float> %v) {
404; CHECK-LABEL: @fadd_rdx_commute(
405; CHECK-NEXT:    [[D:%.*]] = fdiv float 4.200000e+01, [[X:%.*]]
406; CHECK-NEXT:    [[ADD:%.*]] = call reassoc nsz float @llvm.vector.reduce.fadd.v4f32(float [[D]], <4 x float> [[V:%.*]])
407; CHECK-NEXT:    ret float [[ADD]]
408;
409  %d = fdiv float 42.0, %x
410  %rdx = call float @llvm.vector.reduce.fadd.v4f32(float -0.0, <4 x float> %v)
411  %add = fadd reassoc nsz float %d, %rdx
412  ret float %add
413}
414
415; Negative test - require nsz to be safer (and reassoc obviously).
416
417define float @fadd_rdx_fmf(float %x, <4 x float> %v) {
418; CHECK-LABEL: @fadd_rdx_fmf(
419; CHECK-NEXT:    [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]])
420; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc float [[RDX]], [[X:%.*]]
421; CHECK-NEXT:    ret float [[ADD]]
422;
423  %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
424  %add = fadd reassoc float %rdx, %x
425  ret float %add
426}
427
428; Negative test - don't replace a single add with another reduction.
429
430define float @fadd_rdx_extra_use(float %x, <4 x float> %v) {
431; CHECK-LABEL: @fadd_rdx_extra_use(
432; CHECK-NEXT:    [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]])
433; CHECK-NEXT:    call void @use(float [[RDX]])
434; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]]
435; CHECK-NEXT:    ret float [[ADD]]
436;
437  %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
438  call void @use(float %rdx)
439  %add = fadd fast float %rdx, %x
440  ret float %add
441}
442
443define float @fadd_rdx_nonzero_start_const_op(<4 x float> %v) {
444; CHECK-LABEL: @fadd_rdx_nonzero_start_const_op(
445; CHECK-NEXT:    [[ADD:%.*]] = call reassoc ninf nsz float @llvm.vector.reduce.fadd.v4f32(float 3.300000e+01, <4 x float> [[V:%.*]])
446; CHECK-NEXT:    ret float [[ADD]]
447;
448  %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v)
449  %add = fadd reassoc nsz ninf float %rdx, -9.0
450  ret float %add
451}
452
453; Negative test - we don't change the order of ops unless it saves an instruction.
454
455define float @fadd_rdx_nonzero_start_variable_op(float %x, <4 x float> %v) {
456; CHECK-LABEL: @fadd_rdx_nonzero_start_variable_op(
457; CHECK-NEXT:    [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 4.200000e+01, <4 x float> [[V:%.*]])
458; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]]
459; CHECK-NEXT:    ret float [[ADD]]
460;
461  %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v)
462  %add = fadd fast float %rdx, %x
463  ret float %add
464}
465
466; (X * C) + X --> X * (C + 1)
467
468define float @fadd_fmul_common_op(float %x) {
469; CHECK-LABEL: @fadd_fmul_common_op(
470; CHECK-NEXT:    [[A:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.300000e+01
471; CHECK-NEXT:    ret float [[A]]
472;
473  %m = fmul reassoc nsz float %x, 42.0
474  %a = fadd reassoc nsz float %m, %x
475  ret float %a
476}
477
478; Splat constant is ok.
479
480define <2 x float> @fadd_fmul_common_op_vec(<2 x float> %x) {
481; CHECK-LABEL: @fadd_fmul_common_op_vec(
482; CHECK-NEXT:    [[A:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], splat (float 4.300000e+01)
483; CHECK-NEXT:    ret <2 x float> [[A]]
484;
485  %m = fmul reassoc nsz <2 x float> %x, <float 42.0, float 42.0>
486  %a = fadd reassoc nsz <2 x float> %m, %x
487  ret <2 x float> %a
488}
489
490; Non-splat constant is ok.
491
492define <2 x float> @fadd_fmul_common_op_commute_vec(<2 x float> %px) {
493; CHECK-LABEL: @fadd_fmul_common_op_commute_vec(
494; CHECK-NEXT:    [[X:%.*]] = fmul <2 x float> [[PX:%.*]], [[PX]]
495; CHECK-NEXT:    [[A:%.*]] = fmul reassoc nsz <2 x float> [[X]], <float 4.300000e+01, float -4.200000e+01>
496; CHECK-NEXT:    ret <2 x float> [[A]]
497;
498  %x = fmul <2 x float> %px, %px ; thwart complexity-based canonicalization
499  %m = fmul reassoc nsz <2 x float> %x, <float 42.0, float -43.0>
500  %a = fadd reassoc nsz <2 x float> %x, %m
501  ret <2 x float> %a
502}
503
504; Extra use is ok.
505
506define float @fadd_fmul_common_op_use(float %x) {
507; CHECK-LABEL: @fadd_fmul_common_op_use(
508; CHECK-NEXT:    [[M:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.200000e+01
509; CHECK-NEXT:    call void @use(float [[M]])
510; CHECK-NEXT:    [[A:%.*]] = fmul reassoc nsz float [[X]], 4.300000e+01
511; CHECK-NEXT:    ret float [[A]]
512;
513  %m = fmul reassoc nsz float %x, 42.0
514  call void @use(float %m)
515  %a = fadd reassoc nsz float %m, %x
516  ret float %a
517}
518
519; Negative test - must have 'reassoc' FMF
520
521define float @fadd_fmul_common_op_wrong_fmf(float %x) {
522; CHECK-LABEL: @fadd_fmul_common_op_wrong_fmf(
523; CHECK-NEXT:    [[M:%.*]] = fmul ninf nsz float [[X:%.*]], 4.200000e+01
524; CHECK-NEXT:    [[A:%.*]] = fadd ninf nsz float [[M]], [[X]]
525; CHECK-NEXT:    ret float [[A]]
526;
527  %m = fmul ninf nsz float %x, 42.0
528  %a = fadd ninf nsz float %m, %x
529  ret float %a
530}
531
532; (-x - y) + (x + z) --> z - y
533
534define float @fadd_fneg_reass_commute0(float %x, float %y, float %z) {
535; CHECK-LABEL: @fadd_fneg_reass_commute0(
536; CHECK-NEXT:    [[N:%.*]] = fneg reassoc nsz float [[X:%.*]]
537; CHECK-NEXT:    call void @use(float [[N]])
538; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y:%.*]]
539; CHECK-NEXT:    ret float [[R]]
540;
541  %n = fneg reassoc nsz float %x
542  call void @use(float %n)
543  %s = fsub reassoc nsz float %n, %y
544  %a = fadd reassoc nsz float %x, %z
545  %r = fadd reassoc nsz float %s, %a
546  ret float %r
547}
548
549define float @fadd_fneg_reass_commute1(float %x, float %y, float %z) {
550; CHECK-LABEL: @fadd_fneg_reass_commute1(
551; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]
552; CHECK-NEXT:    call void @use(float [[N]])
553; CHECK-NEXT:    [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
554; CHECK-NEXT:    call void @use(float [[S]])
555; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y]]
556; CHECK-NEXT:    ret float [[R]]
557;
558  %n = fneg float %x
559  call void @use(float %n)
560  %s = fsub float %n, %y
561  call void @use(float %s)
562  %a = fadd float %x, %z
563  %r = fadd reassoc nsz float %a, %s
564  ret float %r
565}
566
567define float @fadd_fneg_reass_commute2(float %x, float %y, float %z) {
568; CHECK-LABEL: @fadd_fneg_reass_commute2(
569; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]
570; CHECK-NEXT:    call void @use(float [[N]])
571; CHECK-NEXT:    [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
572; CHECK-NEXT:    call void @use(float [[S]])
573; CHECK-NEXT:    [[A:%.*]] = fadd float [[Z:%.*]], [[X]]
574; CHECK-NEXT:    call void @use(float [[A]])
575; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[Z]], [[Y]]
576; CHECK-NEXT:    ret float [[R]]
577;
578  %n = fneg float %x
579  call void @use(float %n)
580  %s = fsub float %n, %y
581  call void @use(float %s)
582  %a = fadd float %z, %x
583  call void @use(float %a)
584  %r = fadd fast float %s, %a
585  ret float %r
586}
587
588define <2 x float> @fadd_fneg_reass_commute3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
589; CHECK-LABEL: @fadd_fneg_reass_commute3(
590; CHECK-NEXT:    [[N:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]]
591; CHECK-NEXT:    call void @use_vec(<2 x float> [[N]])
592; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz <2 x float> [[Z:%.*]], [[Y:%.*]]
593; CHECK-NEXT:    ret <2 x float> [[R]]
594;
595  %n = fneg reassoc nsz <2 x float> %x
596  call void @use_vec(<2 x float> %n)
597  %s = fsub reassoc nsz <2 x float> %n, %y
598  %a = fadd reassoc nsz <2 x float> %z, %x
599  %r = fadd reassoc nsz <2 x float> %a, %s
600  ret <2 x float> %r
601}
602
603; negative test - need reassoc (+ nsz)
604
605define float @fadd_fneg_commute0(float %x, float %y, float %z) {
606; CHECK-LABEL: @fadd_fneg_commute0(
607; CHECK-NEXT:    [[N:%.*]] = fneg float [[X:%.*]]
608; CHECK-NEXT:    call void @use(float [[N]])
609; CHECK-NEXT:    [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
610; CHECK-NEXT:    [[A:%.*]] = fadd float [[X]], [[Z:%.*]]
611; CHECK-NEXT:    [[R:%.*]] = fadd nsz float [[S]], [[A]]
612; CHECK-NEXT:    ret float [[R]]
613;
614  %n = fneg float %x
615  call void @use(float %n)
616  %s = fsub float %n, %y
617  %a = fadd float %x, %z
618  %r = fadd nsz float %s, %a
619  ret float %r
620}
621
622define float @fadd_reduce_sqr_sum_varA(float %a, float %b) {
623; CHECK-LABEL: @fadd_reduce_sqr_sum_varA(
624; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
625; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
626; CHECK-NEXT:    ret float [[ADD]]
627;
628  %a_sq = fmul float %a, %a
629  %two_a = fmul float %a, 2.0
630  %two_a_plus_b = fadd float %two_a, %b
631  %mul = fmul float %two_a_plus_b, %b
632  %add = fadd reassoc nsz float %mul, %a_sq
633  ret float %add
634}
635
636define float @fadd_reduce_sqr_sum_varA_order2(float %a, float %b) {
637; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order2(
638; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
639; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
640; CHECK-NEXT:    ret float [[ADD]]
641;
642  %a_sq = fmul float %a, %a
643  %two_a = fmul float %a, 2.0
644  %two_a_plus_b = fadd float %two_a, %b
645  %mul = fmul float %two_a_plus_b, %b
646  %add = fadd reassoc nsz float %a_sq, %mul
647  ret float %add
648}
649
650define float @fadd_reduce_sqr_sum_varA_order3(float %a, float %b) {
651; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order3(
652; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
653; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
654; CHECK-NEXT:    ret float [[ADD]]
655;
656  %a_sq = fmul float %a, %a
657  %two_a = fmul float %a, 2.0
658  %two_a_plus_b = fadd float %two_a, %b
659  %mul = fmul float %b, %two_a_plus_b
660  %add = fadd reassoc nsz float %mul, %a_sq
661  ret float %add
662}
663
664define float @fadd_reduce_sqr_sum_varA_order4(float %a, float %b) {
665; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order4(
666; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
667; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
668; CHECK-NEXT:    ret float [[ADD]]
669;
670  %a_sq = fmul float %a, %a
671  %two_a = fmul float %a, 2.0
672  %two_a_plus_b = fadd float %b, %two_a
673  %mul = fmul float %two_a_plus_b, %b
674  %add = fadd reassoc nsz float %mul, %a_sq
675  ret float %add
676}
677
678define float @fadd_reduce_sqr_sum_varA_order5(float %a, float %b) {
679; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order5(
680; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
681; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
682; CHECK-NEXT:    ret float [[ADD]]
683;
684  %a_sq = fmul float %a, %a
685  %two_a = fmul float 2.0, %a
686  %two_a_plus_b = fadd float %two_a, %b
687  %mul = fmul float %two_a_plus_b, %b
688  %add = fadd reassoc nsz float %mul, %a_sq
689  ret float %add
690}
691
692define float @fadd_reduce_sqr_sum_varB(float %a, float %b) {
693; CHECK-LABEL: @fadd_reduce_sqr_sum_varB(
694; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
695; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
696; CHECK-NEXT:    ret float [[ADD]]
697;
698  %a_b = fmul float %a, %b
699  %a_b_2 = fmul float %a_b, 2.0
700  %a_sq = fmul float %a, %a
701  %b_sq = fmul float %b, %b
702  %a_sq_b_sq = fadd float %a_sq, %b_sq
703  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
704  ret float %add
705}
706
707define float @fadd_reduce_sqr_sum_varB_order1(float %a, float %b) {
708; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order1(
709; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
710; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
711; CHECK-NEXT:    ret float [[ADD]]
712;
713  %a_b = fmul float %a, %b
714  %a_b_2 = fmul float %a_b, 2.0
715  %a_sq = fmul float %a, %a
716  %b_sq = fmul float %b, %b
717  %a_sq_b_sq = fadd float %a_sq, %b_sq
718  %add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2
719  ret float %add
720}
721
722define float @fadd_reduce_sqr_sum_varB_order2(float %a, float %b) {
723; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order2(
724; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
725; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
726; CHECK-NEXT:    ret float [[ADD]]
727;
728  %a_b = fmul float %a, %b
729  %a_b_2 = fmul float %a_b, 2.0
730  %a_sq = fmul float %a, %a
731  %b_sq = fmul float %b, %b
732  %a_sq_b_sq = fadd float %b_sq, %a_sq
733  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
734  ret float %add
735}
736
737define float @fadd_reduce_sqr_sum_varB_order3(float %a, float %b) {
738; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order3(
739; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[B:%.*]], [[A:%.*]]
740; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
741; CHECK-NEXT:    ret float [[ADD]]
742;
743  %a_b = fmul float %b, %a
744  %a_b_2 = fmul float 2.0, %a_b
745  %a_sq = fmul float %a, %a
746  %b_sq = fmul float %b, %b
747  %a_sq_b_sq = fadd float %a_sq, %b_sq
748  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
749  ret float %add
750}
751
752define float @fadd_reduce_sqr_sum_varB2(float %a, float %b) {
753; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2(
754; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
755; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
756; CHECK-NEXT:    ret float [[ADD]]
757;
758  %a_2 = fmul float %a, 2.0
759  %a_b_2 = fmul float %a_2, %b
760  %a_sq = fmul float %a, %a
761  %b_sq = fmul float %b, %b
762  %a_sq_b_sq = fadd float %a_sq, %b_sq
763  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
764  ret float %add
765}
766
767define float @fadd_reduce_sqr_sum_varB2_order1(float %a, float %b) {
768; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order1(
769; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
770; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
771; CHECK-NEXT:    ret float [[ADD]]
772;
773  %a_2 = fmul float %a, 2.0
774  %a_b_2 = fmul float %a_2, %b
775  %a_sq = fmul float %a, %a
776  %b_sq = fmul float %b, %b
777  %a_sq_b_sq = fadd float %a_sq, %b_sq
778  %add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2
779  ret float %add
780}
781
782define float @fadd_reduce_sqr_sum_varB2_order2(float %a, float %b) {
783; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order2(
784; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
785; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
786; CHECK-NEXT:    ret float [[ADD]]
787;
788  %a_2 = fmul float %a, 2.0
789  %a_b_2 = fmul float %b, %a_2
790  %a_sq = fmul float %a, %a
791  %b_sq = fmul float %b, %b
792  %a_sq_b_sq = fadd float %a_sq, %b_sq
793  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
794  ret float %add
795}
796
797define float @fadd_reduce_sqr_sum_varB2_order3(float %a, float %b) {
798; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order3(
799; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
800; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
801; CHECK-NEXT:    ret float [[ADD]]
802;
803  %a_2 = fmul float 2.0, %a
804  %a_b_2 = fmul float %a_2, %b
805  %a_sq = fmul float %a, %a
806  %b_sq = fmul float %b, %b
807  %a_sq_b_sq = fadd float %a_sq, %b_sq
808  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
809  ret float %add
810}
811
812define float @fadd_reduce_sqr_sum_varA_not_one_use1(float %a, float %b) {
813; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use1(
814; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
815; CHECK-NEXT:    [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
816; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
817; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
818; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
819; CHECK-NEXT:    tail call void @fake_func(float [[MUL]])
820; CHECK-NEXT:    ret float [[ADD]]
821;
822  %a_sq = fmul float %a, %a
823  %two_a = fmul float %a, 2.0
824  %two_a_plus_b = fadd float %two_a, %b
825  %mul = fmul float %two_a_plus_b, %b
826  %add = fadd reassoc nsz float %mul, %a_sq
827  tail call void @fake_func (float %mul)
828  ret float %add
829}
830
831define float @fadd_reduce_sqr_sum_varA_not_one_use2(float %a, float %b) {
832; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use2(
833; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
834; CHECK-NEXT:    [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
835; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
836; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
837; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
838; CHECK-NEXT:    tail call void @fake_func(float [[A_SQ]])
839; CHECK-NEXT:    ret float [[ADD]]
840;
841  %a_sq = fmul float %a, %a
842  %two_a = fmul float %a, 2.0
843  %two_a_plus_b = fadd float %two_a, %b
844  %mul = fmul float %two_a_plus_b, %b
845  %add = fadd reassoc nsz float %mul, %a_sq
846  tail call void @fake_func (float %a_sq)
847  ret float %add
848}
849
850define float @fadd_reduce_sqr_sum_varB_not_one_use1(float %a, float %b) {
851; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use1(
852; CHECK-NEXT:    [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
853; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
854; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
855; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
856; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
857; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
858; CHECK-NEXT:    tail call void @fake_func(float [[A_B_2]])
859; CHECK-NEXT:    ret float [[ADD]]
860;
861  %a_b = fmul float %a, %b
862  %a_b_2 = fmul float %a_b, 2.0
863  %a_sq = fmul float %a, %a
864  %b_sq = fmul float %b, %b
865  %a_sq_b_sq = fadd float %a_sq, %b_sq
866  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
867  tail call void @fake_func (float %a_b_2)
868  ret float %add
869}
870
871define float @fadd_reduce_sqr_sum_varB_not_one_use2(float %a, float %b) {
872; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use2(
873; CHECK-NEXT:    [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
874; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
875; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
876; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
877; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
878; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
879; CHECK-NEXT:    tail call void @fake_func(float [[A_SQ_B_SQ]])
880; CHECK-NEXT:    ret float [[ADD]]
881;
882  %a_b = fmul float %a, %b
883  %a_b_2 = fmul float %a_b, 2.0
884  %a_sq = fmul float %a, %a
885  %b_sq = fmul float %b, %b
886  %a_sq_b_sq = fadd float %a_sq, %b_sq
887  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
888  tail call void @fake_func (float %a_sq_b_sq)
889  ret float %add
890}
891
892define float @fadd_reduce_sqr_sum_varB2_not_one_use(float %a, float %b) {
893; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_not_one_use(
894; CHECK-NEXT:    [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00
895; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[A_2]], [[B:%.*]]
896; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
897; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
898; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
899; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
900; CHECK-NEXT:    tail call void @fake_func(float [[A_B_2]])
901; CHECK-NEXT:    ret float [[ADD]]
902;
903  %a_2 = fmul float %a, 2.0
904  %a_b_2 = fmul float %a_2, %b
905  %a_sq = fmul float %a, %a
906  %b_sq = fmul float %b, %b
907  %a_sq_b_sq = fadd float %a_sq, %b_sq
908  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
909  tail call void @fake_func (float %a_b_2)
910  ret float %add
911}
912
913define float @fadd_reduce_sqr_sum_varA_invalid1(float %a, float %b) {
914; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid1(
915; CHECK-NEXT:    [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00
916; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
917; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]]
918; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[A]]
919; CHECK-NEXT:    ret float [[ADD]]
920;
921  %a_sq = fmul float %a, %a
922  %two_a = fmul float %a, 2.0
923  %two_a_plus_b = fadd float %two_a, %b
924  %mul = fmul float %two_a_plus_b, %a
925  %add = fadd reassoc nsz float %mul, %a_sq
926  ret float %add
927}
928
929define float @fadd_reduce_sqr_sum_varA_invalid2(float %a, float %b) {
930; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid2(
931; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
932; CHECK-NEXT:    [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
933; CHECK-NEXT:    [[NOT_TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[A]]
934; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_TWO_A_PLUS_B]], [[B:%.*]]
935; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
936; CHECK-NEXT:    ret float [[ADD]]
937;
938  %a_sq = fmul float %a, %a
939  %two_a = fmul float %a, 2.0
940  %not_two_a_plus_b = fadd float %two_a, %a
941  %mul = fmul float %not_two_a_plus_b, %b
942  %add = fadd reassoc nsz float %mul, %a_sq
943  ret float %add
944}
945
946define float @fadd_reduce_sqr_sum_varA_invalid3(float %a, float %b) {
947; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid3(
948; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
949; CHECK-NEXT:    [[NOT_TWO_A:%.*]] = fmul float [[A]], 0x4000CCCCC0000000
950; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B:%.*]]
951; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
952; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
953; CHECK-NEXT:    ret float [[ADD]]
954;
955  %a_sq = fmul float %a, %a
956  %not_two_a = fmul float %a, 0x4000CCCCC0000000 ; 2.1
957  %two_a_plus_b = fadd float %not_two_a, %b
958  %mul = fmul float %two_a_plus_b, %b
959  %add = fadd reassoc nsz float %mul, %a_sq
960  ret float %add
961}
962
963define float @fadd_reduce_sqr_sum_varA_invalid4(float %a, float %b) {
964; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid4(
965; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
966; CHECK-NEXT:    [[NOT_TWO_A:%.*]] = fmul float [[B:%.*]], 2.000000e+00
967; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B]]
968; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
969; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
970; CHECK-NEXT:    ret float [[ADD]]
971;
972  %a_sq = fmul float %a, %a
973  %not_two_a = fmul float %b, 2.0
974  %two_a_plus_b = fadd float %not_two_a, %b
975  %mul = fmul float %two_a_plus_b, %b
976  %add = fadd reassoc nsz float %mul, %a_sq
977  ret float %add
978}
979
980define float @fadd_reduce_sqr_sum_varA_invalid5(float %a, float %b) {
981; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid5(
982; CHECK-NEXT:    [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00
983; CHECK-NEXT:    [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
984; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]]
985; CHECK-NEXT:    [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[B]]
986; CHECK-NEXT:    ret float [[ADD]]
987;
988  %not_a_sq = fmul float %a, %b
989  %two_a = fmul float %a, 2.0
990  %two_a_plus_b = fadd float %two_a, %b
991  %mul = fmul float %two_a_plus_b, %b
992  %add = fadd reassoc nsz float %mul, %not_a_sq
993  ret float %add
994}
995
996define float @fadd_reduce_sqr_sum_varB_invalid1(float %a, float %b) {
997; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid1(
998; CHECK-NEXT:    [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
999; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
1000; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
1001; CHECK-NEXT:    [[NOT_B_SQ:%.*]] = fmul float [[B]], [[A]]
1002; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[NOT_B_SQ]]
1003; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1004; CHECK-NEXT:    ret float [[ADD]]
1005;
1006  %a_b = fmul float %a, %b
1007  %a_b_2 = fmul float %a_b, 2.0
1008  %a_sq = fmul float %a, %a
1009  %not_b_sq = fmul float %b, %a
1010  %a_sq_b_sq = fadd float %a_sq, %not_b_sq
1011  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1012  ret float %add
1013}
1014
1015define float @fadd_reduce_sqr_sum_varB_invalid2(float %a, float %b) {
1016; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid2(
1017; CHECK-NEXT:    [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
1018; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
1019; CHECK-NEXT:    [[NOT_A_SQ:%.*]] = fmul float [[A]], [[B]]
1020; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
1021; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[NOT_A_SQ]], [[B_SQ]]
1022; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1023; CHECK-NEXT:    ret float [[ADD]]
1024;
1025  %a_b = fmul float %a, %b
1026  %a_b_2 = fmul float %a_b, 2.0
1027  %not_a_sq = fmul float %a, %b
1028  %b_sq = fmul float %b, %b
1029  %a_sq_b_sq = fadd float %not_a_sq, %b_sq
1030  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1031  ret float %add
1032}
1033
1034define float @fadd_reduce_sqr_sum_varB_invalid3(float %a, float %b) {
1035; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid3(
1036; CHECK-NEXT:    [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
1037; CHECK-NEXT:    [[NOT_A_B_2:%.*]] = fmul float [[A_B]], 0x4000CCCCC0000000
1038; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
1039; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
1040; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1041; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]]
1042; CHECK-NEXT:    ret float [[ADD]]
1043;
1044  %a_b = fmul float %a, %b
1045  %not_a_b_2 = fmul float %a_b, 0x4000CCCCC0000000 ; 2.1
1046  %a_sq = fmul float %a, %a
1047  %b_sq = fmul float %b, %b
1048  %a_sq_b_sq = fadd float %a_sq, %b_sq
1049  %add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq
1050  ret float %add
1051}
1052
1053define float @fadd_reduce_sqr_sum_varB_invalid4(float %a, float %b) {
1054; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid4(
1055; CHECK-NEXT:    [[NOT_A_B:%.*]] = fmul float [[A:%.*]], [[A]]
1056; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00
1057; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
1058; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]]
1059; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1060; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1061; CHECK-NEXT:    ret float [[ADD]]
1062;
1063  %not_a_b = fmul float %a, %a
1064  %a_b_2 = fmul float %not_a_b, 2.0
1065  %a_sq = fmul float %a, %a
1066  %b_sq = fmul float %b, %b
1067  %a_sq_b_sq = fadd float %a_sq, %b_sq
1068  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1069  ret float %add
1070}
1071
1072define float @fadd_reduce_sqr_sum_varB_invalid5(float %a, float %b) {
1073; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid5(
1074; CHECK-NEXT:    [[NOT_A_B:%.*]] = fmul float [[B:%.*]], [[B]]
1075; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00
1076; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
1077; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
1078; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1079; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1080; CHECK-NEXT:    ret float [[ADD]]
1081;
1082  %not_a_b = fmul float %b, %b
1083  %a_b_2 = fmul float %not_a_b, 2.0
1084  %a_sq = fmul float %a, %a
1085  %b_sq = fmul float %b, %b
1086  %a_sq_b_sq = fadd float %a_sq, %b_sq
1087  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1088  ret float %add
1089}
1090
1091define float @fadd_reduce_sqr_sum_varB2_invalid1(float %a, float %b) {
1092; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid1(
1093; CHECK-NEXT:    [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00
1094; CHECK-NEXT:    [[NOT_A_B_2:%.*]] = fmul float [[A_2]], [[A]]
1095; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
1096; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]]
1097; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1098; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]]
1099; CHECK-NEXT:    ret float [[ADD]]
1100;
1101  %a_2 = fmul float %a, 2.0
1102  %not_a_b_2 = fmul float %a_2, %a
1103  %a_sq = fmul float %a, %a
1104  %b_sq = fmul float %b, %b
1105  %a_sq_b_sq = fadd float %a_sq, %b_sq
1106  %add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq
1107  ret float %add
1108}
1109
1110define float @fadd_reduce_sqr_sum_varB2_invalid2(float %a, float %b) {
1111; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid2(
1112; CHECK-NEXT:    [[NOT_A_2:%.*]] = fmul float [[A:%.*]], 0x4000CCCCC0000000
1113; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B:%.*]]
1114; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A]], [[A]]
1115; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
1116; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1117; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1118; CHECK-NEXT:    ret float [[ADD]]
1119;
1120  %not_a_2 = fmul float %a, 0x4000CCCCC0000000 ; 2.1
1121  %a_b_2 = fmul float %not_a_2, %b
1122  %a_sq = fmul float %a, %a
1123  %b_sq = fmul float %b, %b
1124  %a_sq_b_sq = fadd float %a_sq, %b_sq
1125  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1126  ret float %add
1127}
1128
1129define float @fadd_reduce_sqr_sum_varB2_invalid3(float %a, float %b) {
1130; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid3(
1131; CHECK-NEXT:    [[NOT_A_2:%.*]] = fmul float [[B:%.*]], 2.000000e+00
1132; CHECK-NEXT:    [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B]]
1133; CHECK-NEXT:    [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
1134; CHECK-NEXT:    [[B_SQ:%.*]] = fmul float [[B]], [[B]]
1135; CHECK-NEXT:    [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
1136; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
1137; CHECK-NEXT:    ret float [[ADD]]
1138;
1139  %not_a_2 = fmul float %b, 2.0
1140  %a_b_2 = fmul float %not_a_2, %b
1141  %a_sq = fmul float %a, %a
1142  %b_sq = fmul float %b, %b
1143  %a_sq_b_sq = fadd float %a_sq, %b_sq
1144  %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
1145  ret float %add
1146}
1147
1148declare void @fake_func(float)
1149