xref: /llvm-project/llvm/test/Transforms/InstCombine/fmul.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
5; (-0.0 - X) * C => X * -C
6define float @neg_constant(float %x) {
7; CHECK-LABEL: @neg_constant(
8; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[X:%.*]], -2.000000e+01
9; CHECK-NEXT:    ret float [[MUL]]
10;
11  %sub = fsub float -0.0, %x
12  %mul = fmul ninf float %sub, 2.0e+1
13  ret float %mul
14}
15
16define float @unary_neg_constant(float %x) {
17; CHECK-LABEL: @unary_neg_constant(
18; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[X:%.*]], -2.000000e+01
19; CHECK-NEXT:    ret float [[MUL]]
20;
21  %sub = fneg float %x
22  %mul = fmul ninf float %sub, 2.0e+1
23  ret float %mul
24}
25
26define <2 x float> @neg_constant_vec(<2 x float> %x) {
27; CHECK-LABEL: @neg_constant_vec(
28; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf <2 x float> [[X:%.*]], <float -2.000000e+00, float -3.000000e+00>
29; CHECK-NEXT:    ret <2 x float> [[MUL]]
30;
31  %sub = fsub <2 x float> <float -0.0, float -0.0>, %x
32  %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0>
33  ret <2 x float> %mul
34}
35
36define <2 x float> @unary_neg_constant_vec(<2 x float> %x) {
37; CHECK-LABEL: @unary_neg_constant_vec(
38; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf <2 x float> [[X:%.*]], <float -2.000000e+00, float -3.000000e+00>
39; CHECK-NEXT:    ret <2 x float> [[MUL]]
40;
41  %sub = fneg <2 x float> %x
42  %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0>
43  ret <2 x float> %mul
44}
45
46define <2 x float> @neg_constant_vec_poison(<2 x float> %x) {
47; CHECK-LABEL: @neg_constant_vec_poison(
48; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf <2 x float> [[X:%.*]], <float -2.000000e+00, float -3.000000e+00>
49; CHECK-NEXT:    ret <2 x float> [[MUL]]
50;
51  %sub = fsub <2 x float> <float poison, float -0.0>, %x
52  %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0>
53  ret <2 x float> %mul
54}
55
56; (0.0 - X) * C => X * -C
57define float @neg_nsz_constant(float %x) {
58; CHECK-LABEL: @neg_nsz_constant(
59; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[X:%.*]], -2.000000e+01
60; CHECK-NEXT:    ret float [[MUL]]
61;
62  %sub = fsub nsz float 0.0, %x
63  %mul = fmul nnan float %sub, 2.0e+1
64  ret float %mul
65}
66
67define float @unary_neg_nsz_constant(float %x) {
68; CHECK-LABEL: @unary_neg_nsz_constant(
69; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[X:%.*]], -2.000000e+01
70; CHECK-NEXT:    ret float [[MUL]]
71;
72  %sub = fneg nsz float %x
73  %mul = fmul nnan float %sub, 2.0e+1
74  ret float %mul
75}
76
77; (-0.0 - X) * (-0.0 - Y) => X * Y
78define float @neg_neg(float %x, float %y) {
79; CHECK-LABEL: @neg_neg(
80; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]]
81; CHECK-NEXT:    ret float [[MUL]]
82;
83  %sub1 = fsub float -0.0, %x
84  %sub2 = fsub float -0.0, %y
85  %mul = fmul arcp float %sub1, %sub2
86  ret float %mul
87}
88
89define float @unary_neg_unary_neg(float %x, float %y) {
90; CHECK-LABEL: @unary_neg_unary_neg(
91; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]]
92; CHECK-NEXT:    ret float [[MUL]]
93;
94  %sub1 = fneg float %x
95  %sub2 = fneg float %y
96  %mul = fmul arcp float %sub1, %sub2
97  ret float %mul
98}
99
100define float @unary_neg_neg(float %x, float %y) {
101; CHECK-LABEL: @unary_neg_neg(
102; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]]
103; CHECK-NEXT:    ret float [[MUL]]
104;
105  %sub1 = fneg float %x
106  %sub2 = fsub float -0.0, %y
107  %mul = fmul arcp float %sub1, %sub2
108  ret float %mul
109}
110
111define float @neg_unary_neg(float %x, float %y) {
112; CHECK-LABEL: @neg_unary_neg(
113; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]]
114; CHECK-NEXT:    ret float [[MUL]]
115;
116  %sub1 = fsub float -0.0, %x
117  %sub2 = fneg float %y
118  %mul = fmul arcp float %sub1, %sub2
119  ret float %mul
120}
121
122define <2 x float> @neg_neg_vec(<2 x float> %x, <2 x float> %y) {
123; CHECK-LABEL: @neg_neg_vec(
124; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
125; CHECK-NEXT:    ret <2 x float> [[MUL]]
126;
127  %sub1 = fsub <2 x float> <float -0.0, float -0.0>, %x
128  %sub2 = fsub <2 x float> <float -0.0, float -0.0>, %y
129  %mul = fmul arcp <2 x float> %sub1, %sub2
130  ret <2 x float> %mul
131}
132
133define <2 x float> @unary_neg_unary_neg_vec(<2 x float> %x, <2 x float> %y) {
134; CHECK-LABEL: @unary_neg_unary_neg_vec(
135; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
136; CHECK-NEXT:    ret <2 x float> [[MUL]]
137;
138  %sub1 = fneg <2 x float> %x
139  %sub2 = fneg <2 x float> %y
140  %mul = fmul arcp <2 x float> %sub1, %sub2
141  ret <2 x float> %mul
142}
143
144define <2 x float> @unary_neg_neg_vec(<2 x float> %x, <2 x float> %y) {
145; CHECK-LABEL: @unary_neg_neg_vec(
146; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
147; CHECK-NEXT:    ret <2 x float> [[MUL]]
148;
149  %sub1 = fneg <2 x float> %x
150  %sub2 = fsub <2 x float> <float -0.0, float -0.0>, %y
151  %mul = fmul arcp <2 x float> %sub1, %sub2
152  ret <2 x float> %mul
153}
154
155define <2 x float> @neg_unary_neg_vec(<2 x float> %x, <2 x float> %y) {
156; CHECK-LABEL: @neg_unary_neg_vec(
157; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
158; CHECK-NEXT:    ret <2 x float> [[MUL]]
159;
160  %sub1 = fsub <2 x float> <float -0.0, float -0.0>, %x
161  %sub2 = fneg <2 x float> %y
162  %mul = fmul arcp <2 x float> %sub1, %sub2
163  ret <2 x float> %mul
164}
165
166define <2 x float> @neg_neg_vec_poison(<2 x float> %x, <2 x float> %y) {
167; CHECK-LABEL: @neg_neg_vec_poison(
168; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
169; CHECK-NEXT:    ret <2 x float> [[MUL]]
170;
171  %sub1 = fsub <2 x float> <float -0.0, float poison>, %x
172  %sub2 = fsub <2 x float> <float poison, float -0.0>, %y
173  %mul = fmul arcp <2 x float> %sub1, %sub2
174  ret <2 x float> %mul
175}
176
177define <2 x float> @unary_neg_neg_vec_poison(<2 x float> %x, <2 x float> %y) {
178; CHECK-LABEL: @unary_neg_neg_vec_poison(
179; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
180; CHECK-NEXT:    ret <2 x float> [[MUL]]
181;
182  %neg = fneg <2 x float> %x
183  %sub = fsub <2 x float> <float poison, float -0.0>, %y
184  %mul = fmul arcp <2 x float> %neg, %sub
185  ret <2 x float> %mul
186}
187
188define <2 x float> @neg_unary_neg_vec_poison(<2 x float> %x, <2 x float> %y) {
189; CHECK-LABEL: @neg_unary_neg_vec_poison(
190; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
191; CHECK-NEXT:    ret <2 x float> [[MUL]]
192;
193  %sub = fsub <2 x float> <float -0.0, float poison>, %x
194  %neg = fneg <2 x float> %y
195  %mul = fmul arcp <2 x float> %sub, %neg
196  ret <2 x float> %mul
197}
198
199; (0.0 - X) * (0.0 - Y) => X * Y
200define float @neg_neg_nsz(float %x, float %y) {
201; CHECK-LABEL: @neg_neg_nsz(
202; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X:%.*]], [[Y:%.*]]
203; CHECK-NEXT:    ret float [[MUL]]
204;
205  %sub1 = fsub nsz float 0.0, %x
206  %sub2 = fsub nsz float 0.0, %y
207  %mul = fmul afn float %sub1, %sub2
208  ret float %mul
209}
210
211declare void @use_f32(float)
212
213define float @neg_neg_multi_use(float %x, float %y) {
214; CHECK-LABEL: @neg_neg_multi_use(
215; CHECK-NEXT:    [[NX:%.*]] = fneg float [[X:%.*]]
216; CHECK-NEXT:    [[NY:%.*]] = fneg float [[Y:%.*]]
217; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X]], [[Y]]
218; CHECK-NEXT:    call void @use_f32(float [[NX]])
219; CHECK-NEXT:    call void @use_f32(float [[NY]])
220; CHECK-NEXT:    ret float [[MUL]]
221;
222  %nx = fsub float -0.0, %x
223  %ny = fsub float -0.0, %y
224  %mul = fmul afn float %nx, %ny
225  call void @use_f32(float %nx)
226  call void @use_f32(float %ny)
227  ret float %mul
228}
229
230define float @unary_neg_unary_neg_multi_use(float %x, float %y) {
231; CHECK-LABEL: @unary_neg_unary_neg_multi_use(
232; CHECK-NEXT:    [[NX:%.*]] = fneg float [[X:%.*]]
233; CHECK-NEXT:    [[NY:%.*]] = fneg float [[Y:%.*]]
234; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X]], [[Y]]
235; CHECK-NEXT:    call void @use_f32(float [[NX]])
236; CHECK-NEXT:    call void @use_f32(float [[NY]])
237; CHECK-NEXT:    ret float [[MUL]]
238;
239  %nx = fneg float %x
240  %ny = fneg float %y
241  %mul = fmul afn float %nx, %ny
242  call void @use_f32(float %nx)
243  call void @use_f32(float %ny)
244  ret float %mul
245}
246
247define float @unary_neg_neg_multi_use(float %x, float %y) {
248; CHECK-LABEL: @unary_neg_neg_multi_use(
249; CHECK-NEXT:    [[NX:%.*]] = fneg float [[X:%.*]]
250; CHECK-NEXT:    [[NY:%.*]] = fneg float [[Y:%.*]]
251; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X]], [[Y]]
252; CHECK-NEXT:    call void @use_f32(float [[NX]])
253; CHECK-NEXT:    call void @use_f32(float [[NY]])
254; CHECK-NEXT:    ret float [[MUL]]
255;
256  %nx = fneg float %x
257  %ny = fsub float -0.0, %y
258  %mul = fmul afn float %nx, %ny
259  call void @use_f32(float %nx)
260  call void @use_f32(float %ny)
261  ret float %mul
262}
263
264define float @neg_unary_neg_multi_use(float %x, float %y) {
265; CHECK-LABEL: @neg_unary_neg_multi_use(
266; CHECK-NEXT:    [[NX:%.*]] = fneg float [[X:%.*]]
267; CHECK-NEXT:    [[NY:%.*]] = fneg float [[Y:%.*]]
268; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X]], [[Y]]
269; CHECK-NEXT:    call void @use_f32(float [[NX]])
270; CHECK-NEXT:    call void @use_f32(float [[NY]])
271; CHECK-NEXT:    ret float [[MUL]]
272;
273  %nx = fsub float -0.0, %x
274  %ny = fneg float %y
275  %mul = fmul afn float %nx, %ny
276  call void @use_f32(float %nx)
277  call void @use_f32(float %ny)
278  ret float %mul
279}
280
281; (-0.0 - X) * Y
282define float @neg_mul(float %x, float %y) {
283; CHECK-LABEL: @neg_mul(
284; CHECK-NEXT:    [[SUB:%.*]] = fneg float [[X:%.*]]
285; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y:%.*]], [[SUB]]
286; CHECK-NEXT:    ret float [[MUL]]
287;
288  %sub = fsub float -0.0, %x
289  %mul = fmul float %sub, %y
290  ret float %mul
291}
292
293define float @unary_neg_mul(float %x, float %y) {
294; CHECK-LABEL: @unary_neg_mul(
295; CHECK-NEXT:    [[NEG:%.*]] = fneg float [[X:%.*]]
296; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y:%.*]], [[NEG]]
297; CHECK-NEXT:    ret float [[MUL]]
298;
299  %neg = fneg float %x
300  %mul = fmul float %neg, %y
301  ret float %mul
302}
303
304define <2 x float> @neg_mul_vec(<2 x float> %x, <2 x float> %y) {
305; CHECK-LABEL: @neg_mul_vec(
306; CHECK-NEXT:    [[SUB:%.*]] = fneg <2 x float> [[X:%.*]]
307; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[SUB]]
308; CHECK-NEXT:    ret <2 x float> [[MUL]]
309;
310  %sub = fsub <2 x float> <float -0.0, float -0.0>, %x
311  %mul = fmul <2 x float> %sub, %y
312  ret <2 x float> %mul
313}
314
315define <2 x float> @unary_neg_mul_vec(<2 x float> %x, <2 x float> %y) {
316; CHECK-LABEL: @unary_neg_mul_vec(
317; CHECK-NEXT:    [[SUB:%.*]] = fneg <2 x float> [[X:%.*]]
318; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[SUB]]
319; CHECK-NEXT:    ret <2 x float> [[MUL]]
320;
321  %sub = fneg <2 x float> %x
322  %mul = fmul <2 x float> %sub, %y
323  ret <2 x float> %mul
324}
325
326define <2 x float> @neg_mul_vec_poison(<2 x float> %x, <2 x float> %y) {
327; CHECK-LABEL: @neg_mul_vec_poison(
328; CHECK-NEXT:    [[SUB:%.*]] = fneg <2 x float> [[X:%.*]]
329; CHECK-NEXT:    [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[SUB]]
330; CHECK-NEXT:    ret <2 x float> [[MUL]]
331;
332  %sub = fsub <2 x float> <float poison, float -0.0>, %x
333  %mul = fmul <2 x float> %sub, %y
334  ret <2 x float> %mul
335}
336
337; (0.0 - X) * Y
338define float @neg_sink_nsz(float %x, float %y) {
339; CHECK-LABEL: @neg_sink_nsz(
340; CHECK-NEXT:    [[SUB1:%.*]] = fneg nsz float [[X:%.*]]
341; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y:%.*]], [[SUB1]]
342; CHECK-NEXT:    ret float [[MUL]]
343;
344  %sub1 = fsub nsz float 0.0, %x
345  %mul = fmul float %sub1, %y
346  ret float %mul
347}
348
349define float @neg_sink_multi_use(float %x, float %y) {
350; CHECK-LABEL: @neg_sink_multi_use(
351; CHECK-NEXT:    [[SUB1:%.*]] = fneg float [[X:%.*]]
352; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y:%.*]], [[SUB1]]
353; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]
354; CHECK-NEXT:    ret float [[MUL2]]
355;
356  %sub1 = fsub float -0.0, %x
357  %mul = fmul float %sub1, %y
358  %mul2 = fmul float %mul, %sub1
359  ret float %mul2
360}
361
362define float @unary_neg_mul_multi_use(float %x, float %y) {
363; CHECK-LABEL: @unary_neg_mul_multi_use(
364; CHECK-NEXT:    [[SUB1:%.*]] = fneg float [[X:%.*]]
365; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[Y:%.*]], [[SUB1]]
366; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]
367; CHECK-NEXT:    ret float [[MUL2]]
368;
369  %sub1 = fneg float %x
370  %mul = fmul float %sub1, %y
371  %mul2 = fmul float %mul, %sub1
372  ret float %mul2
373}
374
375; Don't crash when attempting to cast a constant FMul to an instruction.
376define void @test8(ptr %inout, i1 %c1) {
377; CHECK-LABEL: @test8(
378; CHECK-NEXT:  entry:
379; CHECK-NEXT:    br label [[FOR_COND:%.*]]
380; CHECK:       for.cond:
381; CHECK-NEXT:    [[LOCAL_VAR_7_0:%.*]] = phi <4 x float> [ splat (float -0.000000e+00), [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[FOR_BODY:%.*]] ]
382; CHECK-NEXT:    br i1 [[C1:%.*]], label [[FOR_BODY]], label [[FOR_END:%.*]]
383; CHECK:       for.body:
384; CHECK-NEXT:    [[TMP0]] = insertelement <4 x float> [[LOCAL_VAR_7_0]], float 0.000000e+00, i64 2
385; CHECK-NEXT:    br label [[FOR_COND]]
386; CHECK:       for.end:
387; CHECK-NEXT:    ret void
388;
389entry:
390  %0 = load i32, ptr %inout, align 4
391  %conv = uitofp i32 %0 to float
392  %vecinit = insertelement <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float poison>, float %conv, i32 3
393  %sub = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vecinit
394  %1 = shufflevector <4 x float> %sub, <4 x float> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
395  %mul = fmul <4 x float> zeroinitializer, %1
396  br label %for.cond
397
398for.cond:                                         ; preds = %for.body, %entry
399  %local_var_7.0 = phi <4 x float> [ %mul, %entry ], [ %2, %for.body ]
400  br i1 %c1, label %for.body, label %for.end
401
402for.body:                                         ; preds = %for.cond
403  %2 = insertelement <4 x float> %local_var_7.0, float 0.000000e+00, i32 2
404  br label %for.cond
405
406for.end:                                          ; preds = %for.cond
407  ret void
408}
409
410; X * -1.0 => -0.0 - X
411define float @test9(float %x) {
412; CHECK-LABEL: @test9(
413; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[X:%.*]]
414; CHECK-NEXT:    ret float [[MUL]]
415;
416  %mul = fmul float %x, -1.0
417  ret float %mul
418}
419
420; PR18532
421define <4 x float> @test10(<4 x float> %x) {
422; CHECK-LABEL: @test10(
423; CHECK-NEXT:    [[MUL:%.*]] = fneg arcp afn <4 x float> [[X:%.*]]
424; CHECK-NEXT:    ret <4 x float> [[MUL]]
425;
426  %mul = fmul arcp afn <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
427  ret <4 x float> %mul
428}
429
430define float @test11(float %x, float %y) {
431; CHECK-LABEL: @test11(
432; CHECK-NEXT:    [[B:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]]
433; CHECK-NEXT:    [[C:%.*]] = fadd fast float [[B]], 3.000000e+00
434; CHECK-NEXT:    ret float [[C]]
435;
436  %a = fadd fast float %x, 1.0
437  %b = fadd fast float %y, 2.0
438  %c = fadd fast float %a, %b
439  ret float %c
440}
441
442declare double @llvm.sqrt.f64(double)
443
444; With unsafe/fast math, sqrt(X) * sqrt(X) is just X,
445; but make sure another use of the sqrt is intact.
446; Note that the remaining fmul is altered but is not 'fast'
447; itself because it was not marked 'fast' originally.
448; Thus, we have an overall fast result, but no more indication of
449; 'fast'ness in the code.
450define double @sqrt_squared2(double %f) {
451; CHECK-LABEL: @sqrt_squared2(
452; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]])
453; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[F]], [[SQRT]]
454; CHECK-NEXT:    ret double [[MUL2]]
455;
456  %sqrt = call double @llvm.sqrt.f64(double %f)
457  %mul1 = fmul fast double %sqrt, %sqrt
458  %mul2 = fmul double %mul1, %sqrt
459  ret double %mul2
460}
461
462declare float @llvm.fabs.f32(float) nounwind readnone
463
464define float @fabs_squared(float %x) {
465; CHECK-LABEL: @fabs_squared(
466; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
467; CHECK-NEXT:    ret float [[MUL]]
468;
469  %x.fabs = call float @llvm.fabs.f32(float %x)
470  %mul = fmul float %x.fabs, %x.fabs
471  ret float %mul
472}
473
474define float @fabs_squared_fast(float %x) {
475; CHECK-LABEL: @fabs_squared_fast(
476; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[X]]
477; CHECK-NEXT:    ret float [[MUL]]
478;
479  %x.fabs = call float @llvm.fabs.f32(float %x)
480  %mul = fmul fast float %x.fabs, %x.fabs
481  ret float %mul
482}
483
484define float @fabs_fabs(float %x, float %y) {
485; CHECK-LABEL: @fabs_fabs(
486; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
487; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.fabs.f32(float [[TMP1]])
488; CHECK-NEXT:    ret float [[MUL]]
489;
490  %x.fabs = call float @llvm.fabs.f32(float %x)
491  %y.fabs = call float @llvm.fabs.f32(float %y)
492  %mul = fmul float %x.fabs, %y.fabs
493  ret float %mul
494}
495
496define float @fabs_fabs_extra_use1(float %x, float %y) {
497; CHECK-LABEL: @fabs_fabs_extra_use1(
498; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
499; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
500; CHECK-NEXT:    [[TMP1:%.*]] = fmul ninf float [[X]], [[Y:%.*]]
501; CHECK-NEXT:    [[MUL:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]])
502; CHECK-NEXT:    ret float [[MUL]]
503;
504  %x.fabs = call float @llvm.fabs.f32(float %x)
505  call void @use_f32(float %x.fabs)
506  %y.fabs = call float @llvm.fabs.f32(float %y)
507  %mul = fmul ninf float %x.fabs, %y.fabs
508  ret float %mul
509}
510
511define float @fabs_fabs_extra_use2(float %x, float %y) {
512; CHECK-LABEL: @fabs_fabs_extra_use2(
513; CHECK-NEXT:    [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]])
514; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
515; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc ninf float [[X:%.*]], [[Y]]
516; CHECK-NEXT:    [[MUL:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]])
517; CHECK-NEXT:    ret float [[MUL]]
518;
519  %x.fabs = call fast float @llvm.fabs.f32(float %x)
520  %y.fabs = call fast float @llvm.fabs.f32(float %y)
521  call void @use_f32(float %y.fabs)
522  %mul = fmul reassoc ninf float %x.fabs, %y.fabs
523  ret float %mul
524}
525
526; negative test - don't create an extra instruction
527
528define float @fabs_fabs_extra_use3(float %x, float %y) {
529; CHECK-LABEL: @fabs_fabs_extra_use3(
530; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
531; CHECK-NEXT:    call void @use_f32(float [[X_FABS]])
532; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
533; CHECK-NEXT:    call void @use_f32(float [[Y_FABS]])
534; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_FABS]]
535; CHECK-NEXT:    ret float [[MUL]]
536;
537  %x.fabs = call float @llvm.fabs.f32(float %x)
538  call void @use_f32(float %x.fabs)
539  %y.fabs = call float @llvm.fabs.f32(float %y)
540  call void @use_f32(float %y.fabs)
541  %mul = fmul float %x.fabs, %y.fabs
542  ret float %mul
543}
544
545; (X*Y) * X => (X*X) * Y
546; The transform only requires 'reassoc', but test other FMF in
547; the commuted variants to make sure FMF propagates as expected.
548
549define float @reassoc_common_operand1(float %x, float %y) {
550; CHECK-LABEL: @reassoc_common_operand1(
551; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], [[X]]
552; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc float [[TMP1]], [[Y:%.*]]
553; CHECK-NEXT:    ret float [[MUL2]]
554;
555  %mul1 = fmul float %x, %y
556  %mul2 = fmul reassoc float %mul1, %x
557  ret float %mul2
558}
559
560; (Y*X) * X => (X*X) * Y
561
562define float @reassoc_common_operand2(float %x, float %y) {
563; CHECK-LABEL: @reassoc_common_operand2(
564; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[X]]
565; CHECK-NEXT:    [[MUL2:%.*]] = fmul fast float [[TMP1]], [[Y:%.*]]
566; CHECK-NEXT:    ret float [[MUL2]]
567;
568  %mul1 = fmul float %y, %x
569  %mul2 = fmul fast float %mul1, %x
570  ret float %mul2
571}
572
573; X * (X*Y) => (X*X) * Y
574
575define float @reassoc_common_operand3(float %x1, float %y) {
576; CHECK-LABEL: @reassoc_common_operand3(
577; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 3.000000e+00
578; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nnan float [[X]], [[X]]
579; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc nnan float [[TMP1]], [[Y:%.*]]
580; CHECK-NEXT:    ret float [[MUL2]]
581;
582  %x = fdiv float %x1, 3.0 ; thwart complexity-based canonicalization
583  %mul1 = fmul float %x, %y
584  %mul2 = fmul reassoc nnan float %x, %mul1
585  ret float %mul2
586}
587
588; X * (Y*X) => (X*X) * Y
589
590define float @reassoc_common_operand4(float %x1, float %y) {
591; CHECK-LABEL: @reassoc_common_operand4(
592; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 3.000000e+00
593; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc ninf float [[X]], [[X]]
594; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc ninf float [[TMP1]], [[Y:%.*]]
595; CHECK-NEXT:    ret float [[MUL2]]
596;
597  %x = fdiv float %x1, 3.0 ; thwart complexity-based canonicalization
598  %mul1 = fmul float %y, %x
599  %mul2 = fmul reassoc ninf float %x, %mul1
600  ret float %mul2
601}
602
603; No change if the first fmul has another use.
604
605define float @reassoc_common_operand_multi_use(float %x, float %y) {
606; CHECK-LABEL: @reassoc_common_operand_multi_use(
607; CHECK-NEXT:    [[MUL1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
608; CHECK-NEXT:    [[MUL2:%.*]] = fmul fast float [[MUL1]], [[X]]
609; CHECK-NEXT:    call void @use_f32(float [[MUL1]])
610; CHECK-NEXT:    ret float [[MUL2]]
611;
612  %mul1 = fmul float %x, %y
613  %mul2 = fmul fast float %mul1, %x
614  call void @use_f32(float %mul1)
615  ret float %mul2
616}
617
618declare float @llvm.log2.f32(float)
619
620; log2(Y * 0.5) * X = log2(Y) * X - X
621
622define float @log2half(float %x, float %y) {
623; CHECK-LABEL: @log2half(
624; CHECK-NEXT:    [[TMP1:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
625; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast float [[TMP1]], [[X:%.*]]
626; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP2]], [[X]]
627; CHECK-NEXT:    ret float [[MUL]]
628;
629  %halfy = fmul float %y, 0.5
630  %log2 = call float @llvm.log2.f32(float %halfy)
631  %mul = fmul fast float %log2, %x
632  ret float %mul
633}
634
635define float @log2half_commute(float %x1, float %y) {
636; CHECK-LABEL: @log2half_commute(
637; CHECK-NEXT:    [[X:%.*]] = fmul fast float [[X1:%.*]], 0x3FC24924A0000000
638; CHECK-NEXT:    [[TMP1:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
639; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast float [[TMP1]], [[X]]
640; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP2]], [[X]]
641; CHECK-NEXT:    ret float [[MUL]]
642;
643  %x = fdiv fast float %x1, 7.0 ; thwart complexity-based canonicalization
644  %halfy = fmul fast float %y, 0.5
645  %log2 = call fast float @llvm.log2.f32(float %halfy)
646  %mul = fmul fast float %x, %log2
647  ret float %mul
648}
649
650; C1/X * C2 => (C1*C2) / X
651
652define float @fdiv_constant_numerator_fmul(float %x) {
653; CHECK-LABEL: @fdiv_constant_numerator_fmul(
654; CHECK-NEXT:    [[T3:%.*]] = fdiv reassoc float 1.200000e+07, [[X:%.*]]
655; CHECK-NEXT:    ret float [[T3]]
656;
657  %t1 = fdiv reassoc float 2.0e+3, %x
658  %t3 = fmul reassoc float %t1, 6.0e+3
659  ret float %t3
660}
661
662; C1/X * C2 => (C1*C2) / X with mixed fast-math flags
663
664define float @fdiv_constant_numerator_fmul_mixed(float %x) {
665; CHECK-LABEL: @fdiv_constant_numerator_fmul_mixed(
666; CHECK-NEXT:    [[T3:%.*]] = fdiv reassoc float 1.200000e+07, [[X:%.*]]
667; CHECK-NEXT:    ret float [[T3]]
668;
669  %t1 = fdiv reassoc float 2.0e+3, %x
670  %t3 = fmul fast float %t1, 6.0e+3
671  ret float %t3
672}
673
674; C1/X * C2 => (C1*C2) / X with full fast-math flags
675
676define float @fdiv_constant_numerator_fmul_fast(float %x) {
677; CHECK-LABEL: @fdiv_constant_numerator_fmul_fast(
678; CHECK-NEXT:    [[T3:%.*]] = fdiv fast float 1.200000e+07, [[X:%.*]]
679; CHECK-NEXT:    ret float [[T3]]
680;
681  %t1 = fdiv fast float 2.0e+3, %x
682  %t3 = fmul fast float %t1, 6.0e+3
683  ret float %t3
684}
685
686; C1/X * C2 => (C1*C2) / X with no fast-math flags on the fdiv
687
688define float @fdiv_constant_numerator_fmul_precdiv(float %x) {
689; CHECK-LABEL: @fdiv_constant_numerator_fmul_precdiv(
690; CHECK-NEXT:    [[T1:%.*]] = fdiv float 2.000000e+03, [[X:%.*]]
691; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc float [[T1]], 6.000000e+03
692; CHECK-NEXT:    ret float [[T3]]
693;
694  %t1 = fdiv float 2.0e+3, %x
695  %t3 = fmul reassoc float %t1, 6.0e+3
696  ret float %t3
697}
698
699
700; C1/X * C2 => (C1*C2) / X is disabled if C1/X has multiple uses
701
702@fmul2_external = external global float
703
704define float @fdiv_constant_numerator_fmul_extra_use(float %x) {
705; CHECK-LABEL: @fdiv_constant_numerator_fmul_extra_use(
706; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float 1.000000e+00, [[X:%.*]]
707; CHECK-NEXT:    store float [[DIV]], ptr @fmul2_external, align 4
708; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[DIV]], 2.000000e+00
709; CHECK-NEXT:    ret float [[MUL]]
710;
711  %div = fdiv fast float 1.0, %x
712  store float %div, ptr @fmul2_external
713  %mul = fmul fast float %div, 2.0
714  ret float %mul
715}
716
717; X/C1 * C2 => X * (C2/C1) (if C2/C1 is normal FP)
718
719define float @fdiv_constant_denominator_fmul(float %x) {
720; CHECK-LABEL: @fdiv_constant_denominator_fmul(
721; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
722; CHECK-NEXT:    ret float [[T3]]
723;
724  %t1 = fdiv reassoc float %x, 2.0e+3
725  %t3 = fmul reassoc float %t1, 6.0e+3
726  ret float %t3
727}
728
729define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
730; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec(
731; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
732; CHECK-NEXT:    ret <4 x float> [[T3]]
733;
734  %t1 = fdiv reassoc <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
735  %t3 = fmul reassoc <4 x float> %t1, <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3>
736  ret <4 x float> %t3
737}
738
739; Make sure fmul with constant expression doesn't assert.
740
741define <4 x float> @fdiv_constant_denominator_fmul_vec_constexpr(<4 x float> %x) {
742; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec_constexpr(
743; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
744; CHECK-NEXT:    ret <4 x float> [[T3]]
745;
746  %constExprMul = bitcast i128 trunc (i160 bitcast (<5 x float> <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3, float poison> to i160) to i128) to <4 x float>
747  %t1 = fdiv reassoc <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
748  %t3 = fmul reassoc <4 x float> %t1, %constExprMul
749  ret <4 x float> %t3
750}
751
752; This shows that at least part of instcombine does not check constant
753; values to see if it is creating denorms (0x3800000000000000 is a denorm
754; for 32-bit float), so protecting against denorms in other parts is
755; probably not doing the intended job.
756
757define float @fmul_constant_reassociation(float %x) {
758; CHECK-LABEL: @fmul_constant_reassociation(
759; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], 0x3800000000000000
760; CHECK-NEXT:    ret float [[R]]
761;
762  %mul_flt_min = fmul reassoc nsz float %x, 0x3810000000000000
763  %r = fmul reassoc nsz float  %mul_flt_min, 0.5
764  ret float %r
765}
766
767; Canonicalization "X/C1 * C2 => X * (C2/C1)" still applies if C2/C1 is denormal
768; (otherwise, we should not have allowed the reassociation in the previous test).
769; 0x3810000000000000 == FLT_MIN
770
771define float @fdiv_constant_denominator_fmul_denorm(float %x) {
772; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm(
773; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[X:%.*]], 0x3760620000000000
774; CHECK-NEXT:    ret float [[T3]]
775;
776  %t1 = fdiv fast float %x, 2.0e+3
777  %t3 = fmul fast float %t1, 0x3810000000000000
778  ret float %t3
779}
780
781; X / C1 * C2 => X / (C2/C1) if C1/C2 is abnormal, but C2/C1 is a normal value.
782; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
783; by a denormal, but we could do better when we know that denormals are not a problem.
784
785define float @fdiv_constant_denominator_fmul_denorm_try_harder(float %x) {
786; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder(
787; CHECK-NEXT:    [[T3:%.*]] = fdiv reassoc float [[X:%.*]], 0x47E8000000000000
788; CHECK-NEXT:    ret float [[T3]]
789;
790  %t1 = fdiv reassoc float %x, 3.0
791  %t3 = fmul reassoc float %t1, 0x3810000000000000
792  ret float %t3
793}
794
795; Negative test: we should not have 2 divisions instead of the 1 we started with.
796
797define float @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(float %x) {
798; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(
799; CHECK-NEXT:    [[T1:%.*]] = fdiv float [[X:%.*]], 3.000000e+00
800; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
801; CHECK-NEXT:    [[R:%.*]] = fadd float [[T1]], [[T3]]
802; CHECK-NEXT:    ret float [[R]]
803;
804  %t1 = fdiv float %x, 3.0e+0
805  %t3 = fmul fast float %t1, 0x3810000000000000
806  %r = fadd float %t1, %t3
807  ret float %r
808}
809
810; (X + C1) * C2 --> (X * C2) + C1*C2
811
812define float @fmul_fadd_distribute(float %x) {
813; CHECK-LABEL: @fmul_fadd_distribute(
814; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
815; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc float [[TMP1]], 6.000000e+00
816; CHECK-NEXT:    ret float [[T3]]
817;
818  %t2 = fadd reassoc float %x, 2.0
819  %t3 = fmul reassoc float %t2, 3.0
820  ret float %t3
821}
822
823define <2 x float> @fmul_fadd_distribute_vec(<2 x float> %x) {
824; CHECK-LABEL: @fmul_fadd_distribute_vec(
825; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc <2 x float> [[X:%.*]], splat (float 6.000000e+03)
826; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc <2 x float> [[TMP1]], splat (float 1.200000e+07)
827; CHECK-NEXT:    ret <2 x float> [[T3]]
828;
829  %t1 = fadd reassoc <2 x float> <float 2.0e+3, float 2.0e+3>, %x
830  %t3 = fmul reassoc <2 x float> %t1, <float 6.0e+3, float 6.0e+3>
831  ret <2 x float> %t3
832}
833
834define <vscale x 2 x float> @fmul_fadd_distribute_scalablevec(<vscale x 2 x float> %x) {
835; CHECK-LABEL: @fmul_fadd_distribute_scalablevec(
836; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc <vscale x 2 x float> [[X:%.*]], splat (float 6.000000e+03)
837; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc <vscale x 2 x float> [[TMP1]], splat (float 1.200000e+07)
838; CHECK-NEXT:    ret <vscale x 2 x float> [[T3]]
839;
840  %t1 = fadd reassoc <vscale x 2 x float> splat (float 2.0e+3), %x
841  %t3 = fmul reassoc <vscale x 2 x float> %t1, splat (float 6.0e+3)
842
843
844  ret <vscale x 2 x float> %t3
845}
846
847; (X - C1) * C2 --> (X * C2) - C1*C2
848
849define float @fmul_fsub_distribute1(float %x) {
850; CHECK-LABEL: @fmul_fsub_distribute1(
851; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
852; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc float [[TMP1]], -6.000000e+00
853; CHECK-NEXT:    ret float [[T3]]
854;
855  %t2 = fsub reassoc float %x, 2.0
856  %t3 = fmul reassoc float %t2, 3.0
857  ret float %t3
858}
859
860; (C1 - X) * C2 --> C1*C2 - (X * C2)
861
862define float @fmul_fsub_distribute2(float %x) {
863; CHECK-LABEL: @fmul_fsub_distribute2(
864; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
865; CHECK-NEXT:    [[T3:%.*]] = fsub reassoc float 6.000000e+00, [[TMP1]]
866; CHECK-NEXT:    ret float [[T3]]
867;
868  %t2 = fsub reassoc float 2.0, %x
869  %t3 = fmul reassoc float %t2, 3.0
870  ret float %t3
871}
872
873; FIXME: This should only need 'reassoc'.
874; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3)
875
876define float @fmul_fadd_fmul_distribute(float %x) {
877; CHECK-LABEL: @fmul_fadd_fmul_distribute(
878; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
879; CHECK-NEXT:    [[T3:%.*]] = fadd fast float [[TMP1]], 1.000000e+01
880; CHECK-NEXT:    ret float [[T3]]
881;
882  %t1 = fmul fast float %x, 6.0
883  %t2 = fadd fast float %t1, 2.0
884  %t3 = fmul fast float %t2, 5.0
885  ret float %t3
886}
887
888define float @fmul_fadd_distribute_extra_use(float %x) {
889; CHECK-LABEL: @fmul_fadd_distribute_extra_use(
890; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
891; CHECK-NEXT:    [[T2:%.*]] = fadd float [[T1]], 2.000000e+00
892; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
893; CHECK-NEXT:    call void @use_f32(float [[T2]])
894; CHECK-NEXT:    ret float [[T3]]
895;
896  %t1 = fmul float %x, 6.0
897  %t2 = fadd float %t1, 2.0
898  %t3 = fmul fast float %t2, 5.0
899  call void @use_f32(float %t2)
900  ret float %t3
901}
902
903; (X/C1 + C2) * C3 => X/(C1/C3) + C2*C3
904; 0x10000000000000 = DBL_MIN
905; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
906; by a denormal, but we could do better when we know that denormals are not a problem.
907
908define double @fmul_fadd_fdiv_distribute2(double %x) {
909; CHECK-LABEL: @fmul_fadd_fdiv_distribute2(
910; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc double [[X:%.*]], 0x7FE8000000000000
911; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc double [[TMP1]], 0x34000000000000
912; CHECK-NEXT:    ret double [[T3]]
913;
914  %t1 = fdiv reassoc double %x, 3.0
915  %t2 = fadd reassoc double %t1, 5.0
916  %t3 = fmul reassoc double %t2, 0x10000000000000
917  ret double %t3
918}
919
920; 5.0e-1 * DBL_MIN yields denormal, so "(f1*3.0 + 5.0e-1) * DBL_MIN" cannot
921; be simplified into f1 * (3.0*DBL_MIN) + (5.0e-1*DBL_MIN)
922
923define double @fmul_fadd_fdiv_distribute3(double %x) {
924; CHECK-LABEL: @fmul_fadd_fdiv_distribute3(
925; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc double [[X:%.*]], 0x7FE8000000000000
926; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc double [[TMP1]], 0x34000000000000
927; CHECK-NEXT:    ret double [[T3]]
928;
929  %t1 = fdiv reassoc double %x, 3.0
930  %t2 = fadd reassoc double %t1, 5.0
931  %t3 = fmul reassoc double %t2, 0x10000000000000
932  ret double %t3
933}
934
935; FIXME: This should only need 'reassoc'.
936; (C2 - (X*C1)) * C3 => (C2*C3) - (X * (C1*C3))
937
938define float @fmul_fsub_fmul_distribute(float %x) {
939; CHECK-LABEL: @fmul_fsub_fmul_distribute(
940; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
941; CHECK-NEXT:    [[T3:%.*]] = fsub fast float 1.000000e+01, [[TMP1]]
942; CHECK-NEXT:    ret float [[T3]]
943;
944  %t1 = fmul fast float %x, 6.0
945  %t2 = fsub fast float 2.0, %t1
946  %t3 = fmul fast float %t2, 5.0
947  ret float %t3
948}
949
950define float @fmul_fsub_fmul_distribute_extra_use(float %x) {
951; CHECK-LABEL: @fmul_fsub_fmul_distribute_extra_use(
952; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
953; CHECK-NEXT:    [[T2:%.*]] = fsub float 2.000000e+00, [[T1]]
954; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
955; CHECK-NEXT:    call void @use_f32(float [[T2]])
956; CHECK-NEXT:    ret float [[T3]]
957;
958  %t1 = fmul float %x, 6.0
959  %t2 = fsub float 2.0, %t1
960  %t3 = fmul fast float %t2, 5.0
961  call void @use_f32(float %t2)
962  ret float %t3
963}
964
965; FIXME: This should only need 'reassoc'.
966; ((X*C1) - C2) * C3 => (X * (C1*C3)) - C2*C3
967
968define float @fmul_fsub_fmul_distribute2(float %x) {
969; CHECK-LABEL: @fmul_fsub_fmul_distribute2(
970; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
971; CHECK-NEXT:    [[T3:%.*]] = fadd fast float [[TMP1]], -1.000000e+01
972; CHECK-NEXT:    ret float [[T3]]
973;
974  %t1 = fmul fast float %x, 6.0
975  %t2 = fsub fast float %t1, 2.0
976  %t3 = fmul fast float %t2, 5.0
977  ret float %t3
978}
979
980define float @fmul_fsub_fmul_distribute2_extra_use(float %x) {
981; CHECK-LABEL: @fmul_fsub_fmul_distribute2_extra_use(
982; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
983; CHECK-NEXT:    [[T2:%.*]] = fsub float 2.000000e+00, [[T1]]
984; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
985; CHECK-NEXT:    call void @use_f32(float [[T2]])
986; CHECK-NEXT:    ret float [[T3]]
987;
988  %t1 = fmul float %x, 6.0
989  %t2 = fsub float 2.0, %t1
990  %t3 = fmul fast float %t2, 5.0
991  call void @use_f32(float %t2)
992  ret float %t3
993}
994
995; "(X*Y) * X => (X*X) * Y" is disabled if "X*Y" has multiple uses
996
997define float @common_factor(float %x, float %y) {
998; CHECK-LABEL: @common_factor(
999; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
1000; CHECK-NEXT:    [[MUL1:%.*]] = fmul fast float [[MUL]], [[X]]
1001; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[MUL1]], [[MUL]]
1002; CHECK-NEXT:    ret float [[ADD]]
1003;
1004  %mul = fmul float %x, %y
1005  %mul1 = fmul fast float %mul, %x
1006  %add = fadd float %mul1, %mul
1007  ret float %add
1008}
1009
1010define double @fmul_fdiv_factor_squared(double %x, double %y) {
1011; CHECK-LABEL: @fmul_fdiv_factor_squared(
1012; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast double [[X:%.*]], [[Y:%.*]]
1013; CHECK-NEXT:    [[SQUARED:%.*]] = fmul fast double [[DIV]], [[DIV]]
1014; CHECK-NEXT:    ret double [[SQUARED]]
1015;
1016  %div = fdiv fast double %x, %y
1017  %squared = fmul fast double %div, %div
1018  ret double %squared
1019}
1020
1021define double @fmul_fdivs_factor_common_denominator(double %x, double %y, double %z) {
1022; CHECK-LABEL: @fmul_fdivs_factor_common_denominator(
1023; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast double [[Y:%.*]], [[X:%.*]]
1024; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast double [[Z:%.*]], [[Z]]
1025; CHECK-NEXT:    [[MUL:%.*]] = fdiv fast double [[TMP1]], [[TMP2]]
1026; CHECK-NEXT:    ret double [[MUL]]
1027;
1028  %div1 = fdiv fast double %x, %z
1029  %div2 = fdiv fast double %y, %z
1030  %mul = fmul fast double %div1, %div2
1031  ret double %mul
1032}
1033
1034define double @fmul_fdivs_factor(double %x, double %y, double %z, double %w) {
1035; CHECK-LABEL: @fmul_fdivs_factor(
1036; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc double [[Z:%.*]], [[X:%.*]]
1037; CHECK-NEXT:    [[TMP2:%.*]] = fdiv reassoc double [[TMP1]], [[W:%.*]]
1038; CHECK-NEXT:    [[MUL:%.*]] = fdiv reassoc double [[TMP2]], [[Y:%.*]]
1039; CHECK-NEXT:    ret double [[MUL]]
1040;
1041  %div1 = fdiv reassoc double %x, %y
1042  %div2 = fdiv reassoc double %z, %w
1043  %mul = fmul reassoc double %div1, %div2
1044  ret double %mul
1045}
1046
1047define double @fmul_fdiv_factor(double %x, double %y, double %z) {
1048; CHECK-LABEL: @fmul_fdiv_factor(
1049; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], [[Z:%.*]]
1050; CHECK-NEXT:    [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]]
1051; CHECK-NEXT:    ret double [[MUL]]
1052;
1053  %div = fdiv reassoc double %x, %y
1054  %mul = fmul reassoc double %div, %z
1055  ret double %mul
1056}
1057
1058define double @fmul_fdiv_factor_constant1(double %x, double %y) {
1059; CHECK-LABEL: @fmul_fdiv_factor_constant1(
1060; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], 4.200000e+01
1061; CHECK-NEXT:    [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]]
1062; CHECK-NEXT:    ret double [[MUL]]
1063;
1064  %div = fdiv reassoc double %x, %y
1065  %mul = fmul reassoc double %div, 42.0
1066  ret double %mul
1067}
1068
1069define <2 x float> @fmul_fdiv_factor_constant2(<2 x float> %x, <2 x float> %y) {
1070; CHECK-LABEL: @fmul_fdiv_factor_constant2(
1071; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc <2 x float> [[X:%.*]], [[Y:%.*]]
1072; CHECK-NEXT:    [[MUL:%.*]] = fdiv reassoc <2 x float> [[TMP1]], <float 4.200000e+01, float 1.200000e+01>
1073; CHECK-NEXT:    ret <2 x float> [[MUL]]
1074;
1075  %div = fdiv reassoc <2 x float> %x, <float 42.0, float 12.0>
1076  %mul = fmul reassoc <2 x float> %div, %y
1077  ret <2 x float> %mul
1078}
1079
1080define float @fmul_fdiv_factor_extra_use(float %x, float %y) {
1081; CHECK-LABEL: @fmul_fdiv_factor_extra_use(
1082; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X:%.*]], 4.200000e+01
1083; CHECK-NEXT:    call void @use_f32(float [[DIV]])
1084; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc float [[DIV]], [[Y:%.*]]
1085; CHECK-NEXT:    ret float [[MUL]]
1086;
1087  %div = fdiv float %x, 42.0
1088  call void @use_f32(float %div)
1089  %mul = fmul reassoc float %div, %y
1090  ret float %mul
1091}
1092
1093define void @fmul_loop_invariant_fdiv(ptr %a, float %x) {
1094; CHECK-LABEL: @fmul_loop_invariant_fdiv(
1095; CHECK-NEXT:  entry:
1096; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1097; CHECK:       for.cond.cleanup:
1098; CHECK-NEXT:    ret void
1099; CHECK:       for.body:
1100; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
1101; CHECK-NEXT:    [[IDXPROM:%.*]] = zext nneg i32 [[I_08]] to i64
1102; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw float, ptr [[A:%.*]], i64 [[IDXPROM]]
1103; CHECK-NEXT:    [[F:%.*]] = load float, ptr [[ARRAYIDX]], align 4
1104; CHECK-NEXT:    [[M:%.*]] = fdiv fast float [[F]], [[X:%.*]]
1105; CHECK-NEXT:    store float [[M]], ptr [[ARRAYIDX]], align 4
1106; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1107; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[INC]], 1024
1108; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
1109;
1110entry:
1111  %d = fdiv fast float 1.0, %x
1112  br label %for.body
1113
1114for.cond.cleanup:
1115  ret void
1116
1117for.body:
1118  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1119  %idxprom = zext i32 %i.08 to i64
1120  %arrayidx = getelementptr inbounds float, ptr %a, i64 %idxprom
1121  %f = load float, ptr %arrayidx, align 4
1122  %m = fmul fast float %f, %d
1123  store float %m, ptr %arrayidx, align 4
1124  %inc = add nuw nsw i32 %i.08, 1
1125  %cmp.not = icmp eq i32 %inc, 1024
1126  br i1 %cmp.not, label %for.cond.cleanup, label %for.body
1127}
1128
1129; Avoid infinite looping by moving negation out of a constant expression.
1130
1131@g = external global {[2 x ptr]}, align 1
1132
1133define double @fmul_negated_constant_expression(double %x) {
1134; CHECK-LABEL: @fmul_negated_constant_expression(
1135; CHECK-NEXT:    [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @g, i64 16) to i64) to double)
1136; CHECK-NEXT:    [[R:%.*]] = fmul double [[X:%.*]], [[FSUB]]
1137; CHECK-NEXT:    ret double [[R]]
1138;
1139  %fsub = fsub double -0.000000e+00, bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, i32 0, i64 2) to i64) to double)
1140  %r = fmul double %x, %fsub
1141  ret double %r
1142}
1143
1144define float @negate_if_true(float %x, i1 %cond) {
1145; CHECK-LABEL: @negate_if_true(
1146; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[X:%.*]]
1147; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND:%.*]], float [[TMP1]], float [[X]]
1148; CHECK-NEXT:    ret float [[R]]
1149;
1150  %sel = select i1 %cond, float -1.0, float 1.0
1151  %r = fmul float %sel, %x
1152  ret float %r
1153}
1154
1155define float @negate_if_false(float %x, i1 %cond) {
1156; CHECK-LABEL: @negate_if_false(
1157; CHECK-NEXT:    [[TMP1:%.*]] = fneg arcp float [[X:%.*]]
1158; CHECK-NEXT:    [[R:%.*]] = select arcp i1 [[COND:%.*]], float [[X]], float [[TMP1]]
1159; CHECK-NEXT:    ret float [[R]]
1160;
1161  %sel = select i1 %cond, float 1.0, float -1.0
1162  %r = fmul arcp float %sel, %x
1163  ret float %r
1164}
1165
1166define <2 x double> @negate_if_true_commute(<2 x double> %px, i1 %cond) {
1167; CHECK-LABEL: @negate_if_true_commute(
1168; CHECK-NEXT:    [[X:%.*]] = fdiv <2 x double> splat (double 4.200000e+01), [[PX:%.*]]
1169; CHECK-NEXT:    [[TMP1:%.*]] = fneg ninf <2 x double> [[X]]
1170; CHECK-NEXT:    [[R:%.*]] = select ninf i1 [[COND:%.*]], <2 x double> [[TMP1]], <2 x double> [[X]]
1171; CHECK-NEXT:    ret <2 x double> [[R]]
1172;
1173  %x = fdiv <2 x double> <double 42.0, double 42.0>, %px  ; thwart complexity-based canonicalization
1174  %sel = select i1 %cond, <2 x double> <double -1.0, double -1.0>, <2 x double> <double 1.0, double 1.0>
1175  %r = fmul ninf <2 x double> %x, %sel
1176  ret <2 x double> %r
1177}
1178
1179define <2 x double> @negate_if_false_commute(<2 x double> %px, <2 x i1> %cond) {
1180; CHECK-LABEL: @negate_if_false_commute(
1181; CHECK-NEXT:    [[X:%.*]] = fdiv <2 x double> <double 4.200000e+01, double 5.100000e+00>, [[PX:%.*]]
1182; CHECK-NEXT:    [[TMP1:%.*]] = fneg <2 x double> [[X]]
1183; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[COND:%.*]], <2 x double> [[X]], <2 x double> [[TMP1]]
1184; CHECK-NEXT:    ret <2 x double> [[R]]
1185;
1186  %x = fdiv <2 x double> <double 42.0, double 5.1>, %px  ; thwart complexity-based canonicalization
1187  %sel = select <2 x i1> %cond, <2 x double> <double 1.0, double 1.0>, <2 x double> <double -1.0, double -1.0>
1188  %r = fmul <2 x double> %x, %sel
1189  ret <2 x double> %r
1190}
1191
1192; Negative test
1193
1194define float @negate_if_true_extra_use(float %x, i1 %cond) {
1195; CHECK-LABEL: @negate_if_true_extra_use(
1196; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float 1.000000e+00
1197; CHECK-NEXT:    call void @use_f32(float [[SEL]])
1198; CHECK-NEXT:    [[R:%.*]] = fmul float [[SEL]], [[X:%.*]]
1199; CHECK-NEXT:    ret float [[R]]
1200;
1201  %sel = select i1 %cond, float -1.0, float 1.0
1202  call void @use_f32(float %sel)
1203  %r = fmul float %sel, %x
1204  ret float %r
1205}
1206
1207; Negative test
1208
1209define <2 x double> @negate_if_true_wrong_constant(<2 x double> %px, i1 %cond) {
1210; CHECK-LABEL: @negate_if_true_wrong_constant(
1211; CHECK-NEXT:    [[X:%.*]] = fdiv <2 x double> splat (double 4.200000e+01), [[PX:%.*]]
1212; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x double> <double -1.000000e+00, double 0.000000e+00>, <2 x double> splat (double 1.000000e+00)
1213; CHECK-NEXT:    [[R:%.*]] = fmul <2 x double> [[X]], [[SEL]]
1214; CHECK-NEXT:    ret <2 x double> [[R]]
1215;
1216  %x = fdiv <2 x double> <double 42.0, double 42.0>, %px  ; thwart complexity-based canonicalization
1217  %sel = select i1 %cond, <2 x double> <double -1.0, double 0.0>, <2 x double> <double 1.0, double 1.0>
1218  %r = fmul <2 x double> %x, %sel
1219  ret <2 x double> %r
1220}
1221
1222; X *fast (C ? 1.0 : 0.0) -> C ? X : 0.0
1223define float @fmul_select(float %x, i1 %c) {
1224; CHECK-LABEL: @fmul_select(
1225; CHECK-NEXT:    [[MUL:%.*]] = select fast i1 [[C:%.*]], float [[X:%.*]], float 0.000000e+00
1226; CHECK-NEXT:    ret float [[MUL]]
1227;
1228  %sel = select i1 %c, float 1.0, float 0.0
1229  %mul = fmul fast float %sel, %x
1230  ret float %mul
1231}
1232
1233; X *fast (C ? 1.0 : 0.0) -> C ? X : 0.0
1234define <2 x float> @fmul_select_vec(<2 x float> %x, i1 %c) {
1235; CHECK-LABEL: @fmul_select_vec(
1236; CHECK-NEXT:    [[MUL:%.*]] = select fast i1 [[C:%.*]], <2 x float> [[X:%.*]], <2 x float> zeroinitializer
1237; CHECK-NEXT:    ret <2 x float> [[MUL]]
1238;
1239  %sel = select i1 %c, <2 x float> <float 1.0, float 1.0>, <2 x float> zeroinitializer
1240  %mul = fmul fast <2 x float> %sel, %x
1241  ret <2 x float> %mul
1242}
1243
1244; Without fast math flags we can't optimize X * (C ? 1.0 : 0.0) -> C ? X : 0.0
1245define float @fmul_select_strict(float %x, i1 %c) {
1246; CHECK-LABEL: @fmul_select_strict(
1247; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C:%.*]], float 1.000000e+00, float 0.000000e+00
1248; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SEL]], [[X:%.*]]
1249; CHECK-NEXT:    ret float [[MUL]]
1250;
1251  %sel = select i1 %c, float 1.0, float 0.0
1252  %mul = fmul float %sel, %x
1253  ret float %mul
1254}
1255
1256; sqrt(X) *fast (C ? sqrt(X) : 1.0) -> C ? X : sqrt(X)
1257define double @fmul_sqrt_select(double %x, i1 %c) {
1258; CHECK-LABEL: @fmul_sqrt_select(
1259; CHECK-NEXT:    [[SQR:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]])
1260; CHECK-NEXT:    [[MUL:%.*]] = select fast i1 [[C:%.*]], double [[X]], double [[SQR]]
1261; CHECK-NEXT:    ret double [[MUL]]
1262;
1263  %sqr = call double @llvm.sqrt.f64(double %x)
1264  %sel = select i1 %c, double %sqr, double 1.0
1265  %mul = fmul fast double %sqr, %sel
1266  ret double %mul
1267}
1268
1269; fastmath => z * splat(0) = splat(0), even for scalable vectors
1270define <vscale x 2 x float> @mul_scalable_splat_zero(<vscale x 2 x float> %z) {
1271; CHECK-LABEL: @mul_scalable_splat_zero(
1272; CHECK-NEXT:    ret <vscale x 2 x float> zeroinitializer
1273;
1274  %shuf = shufflevector <vscale x 2 x float> insertelement (<vscale x 2 x float> poison, float 0.0, i32 0), <vscale x 2 x float> poison, <vscale x 2 x i32> zeroinitializer
1275  %t3 = fmul fast <vscale x 2 x float> %shuf, %z
1276  ret <vscale x 2 x float> %t3
1277}
1278
1279define half @mul_zero_nnan(half %x) {
1280; CHECK-LABEL: @mul_zero_nnan(
1281; CHECK-NEXT:    [[R:%.*]] = call nnan half @llvm.copysign.f16(half 0xH0000, half [[X:%.*]])
1282; CHECK-NEXT:    ret half [[R]]
1283;
1284  %r = fmul nnan half %x, 0.0
1285  ret half %r
1286}
1287
1288; poison propagates through vector elements
1289
1290define <2 x float> @mul_zero_nnan_vec_poison(<2 x float> %x) {
1291; CHECK-LABEL: @mul_zero_nnan_vec_poison(
1292; CHECK-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0.000000e+00, float poison>, <2 x float> [[X:%.*]])
1293; CHECK-NEXT:    ret <2 x float> [[R]]
1294;
1295  %r = fmul nnan <2 x float> %x, <float 0.0, float poison>
1296  ret <2 x float> %r
1297}
1298
1299; negative test - must have nnan
1300
1301define half @mul_zero(half %x) {
1302; CHECK-LABEL: @mul_zero(
1303; CHECK-NEXT:    [[R:%.*]] = fmul ninf nsz half [[X:%.*]], 0xH0000
1304; CHECK-NEXT:    ret half [[R]]
1305;
1306  %r = fmul ninf nsz half %x, 0.0
1307  ret half %r
1308}
1309
1310define half @mul_negzero_nnan(half %x) {
1311; CHECK-LABEL: @mul_negzero_nnan(
1312; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan half [[X:%.*]]
1313; CHECK-NEXT:    [[R:%.*]] = call nnan half @llvm.copysign.f16(half 0xH0000, half [[TMP1]])
1314; CHECK-NEXT:    ret half [[R]]
1315;
1316  %r = fmul nnan half %x, -0.0
1317  ret half %r
1318}
1319
1320define float @mul_pos_zero_nnan_ninf(float nofpclass(inf nan) %a) {
1321; CHECK-LABEL: @mul_pos_zero_nnan_ninf(
1322; CHECK-NEXT:  entry:
1323; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[A:%.*]])
1324; CHECK-NEXT:    ret float [[RET]]
1325;
1326entry:
1327  %ret = fmul float %a, 0.000000e+00
1328  ret float %ret
1329}
1330
1331define float @mul_pos_zero_nnan(float nofpclass(nan) %a) {
1332; CHECK-LABEL: @mul_pos_zero_nnan(
1333; CHECK-NEXT:  entry:
1334; CHECK-NEXT:    [[RET:%.*]] = fmul float [[A:%.*]], 0.000000e+00
1335; CHECK-NEXT:    ret float [[RET]]
1336;
1337entry:
1338  %ret = fmul float %a, 0.000000e+00
1339  ret float %ret
1340}
1341
1342define float @mul_pos_zero_nnan_ninf_fmf(float nofpclass(nan) %a) {
1343; CHECK-LABEL: @mul_pos_zero_nnan_ninf_fmf(
1344; CHECK-NEXT:  entry:
1345; CHECK-NEXT:    [[RET:%.*]] = call ninf float @llvm.copysign.f32(float 0.000000e+00, float [[A:%.*]])
1346; CHECK-NEXT:    ret float [[RET]]
1347;
1348entry:
1349  %ret = fmul ninf float %a, 0.000000e+00
1350  ret float %ret
1351}
1352
1353define float @mul_neg_zero_nnan_ninf(float nofpclass(inf nan) %a) {
1354; CHECK-LABEL: @mul_neg_zero_nnan_ninf(
1355; CHECK-NEXT:  entry:
1356; CHECK-NEXT:    [[TMP0:%.*]] = fneg float [[A:%.*]]
1357; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]])
1358; CHECK-NEXT:    ret float [[RET]]
1359;
1360entry:
1361  %ret = fmul float %a, -0.000000e+00
1362  ret float %ret
1363}
1364
1365define float @mul_neg_zero_nnan_fmf(float %a) {
1366; CHECK-LABEL: @mul_neg_zero_nnan_fmf(
1367; CHECK-NEXT:  entry:
1368; CHECK-NEXT:    [[TMP0:%.*]] = fneg nnan float [[A:%.*]]
1369; CHECK-NEXT:    [[RET:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]])
1370; CHECK-NEXT:    ret float [[RET]]
1371;
1372entry:
1373  %ret = fmul nnan float %a, -0.000000e+00
1374  ret float %ret
1375}
1376
1377define float @mul_neg_zero_nnan_ninf_fmf(float nofpclass(inf nan) %a) {
1378; CHECK-LABEL: @mul_neg_zero_nnan_ninf_fmf(
1379; CHECK-NEXT:  entry:
1380; CHECK-NEXT:    [[TMP0:%.*]] = fneg nnan ninf float [[A:%.*]]
1381; CHECK-NEXT:    [[RET:%.*]] = call nnan ninf float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]])
1382; CHECK-NEXT:    ret float [[RET]]
1383;
1384entry:
1385  %ret = fmul nnan ninf float %a, -0.000000e+00
1386  ret float %ret
1387}
1388
1389define <3 x float> @mul_neg_zero_nnan_ninf_vec(<3 x float> nofpclass(inf nan) %a) {
1390; CHECK-LABEL: @mul_neg_zero_nnan_ninf_vec(
1391; CHECK-NEXT:  entry:
1392; CHECK-NEXT:    [[TMP0:%.*]] = fneg <3 x float> [[A:%.*]]
1393; CHECK-NEXT:    [[RET:%.*]] = call <3 x float> @llvm.copysign.v3f32(<3 x float> <float -0.000000e+00, float poison, float poison>, <3 x float> [[TMP0]])
1394; CHECK-NEXT:    ret <3 x float> [[RET]]
1395;
1396entry:
1397  %ret = fmul <3 x float> %a, <float -0.0, float poison, float poison>
1398  ret <3 x float> %ret
1399}
1400
1401define <3 x float> @mul_mixed_zero_nnan_ninf_vec(<3 x float> nofpclass(inf nan) %a) {
1402; CHECK-LABEL: @mul_mixed_zero_nnan_ninf_vec(
1403; CHECK-NEXT:  entry:
1404; CHECK-NEXT:    [[RET:%.*]] = fmul <3 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00, float poison>
1405; CHECK-NEXT:    ret <3 x float> [[RET]]
1406;
1407entry:
1408  %ret = fmul <3 x float> %a, <float -0.0, float 0.0, float poison>
1409  ret <3 x float> %ret
1410}
1411