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