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 <2 x float> @neg_constant_vec(<2 x float> %x) {
16; CHECK-LABEL: @neg_constant_vec(
17; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf <2 x float> [[X:%.*]], <float -2.000000e+00, float -3.000000e+00>
18; CHECK-NEXT:    ret <2 x float> [[MUL]]
19;
20  %sub = fsub <2 x float> <float -0.0, float -0.0>, %x
21  %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0>
22  ret <2 x float> %mul
23}
24
25define <2 x float> @neg_constant_vec_undef(<2 x float> %x) {
26; CHECK-LABEL: @neg_constant_vec_undef(
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 undef, 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
35; (0.0 - X) * C => X * -C
36define float @neg_nsz_constant(float %x) {
37; CHECK-LABEL: @neg_nsz_constant(
38; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[X:%.*]], -2.000000e+01
39; CHECK-NEXT:    ret float [[MUL]]
40;
41  %sub = fsub nsz float 0.0, %x
42  %mul = fmul nnan float %sub, 2.0e+1
43  ret float %mul
44}
45
46; (-0.0 - X) * (-0.0 - Y) => X * Y
47define float @neg_neg(float %x, float %y) {
48; CHECK-LABEL: @neg_neg(
49; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]]
50; CHECK-NEXT:    ret float [[MUL]]
51;
52  %sub1 = fsub float -0.0, %x
53  %sub2 = fsub float -0.0, %y
54  %mul = fmul arcp float %sub1, %sub2
55  ret float %mul
56}
57
58define <2 x float> @neg_neg_vec(<2 x float> %x, <2 x float> %y) {
59; CHECK-LABEL: @neg_neg_vec(
60; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
61; CHECK-NEXT:    ret <2 x float> [[MUL]]
62;
63  %sub1 = fsub <2 x float> <float -0.0, float -0.0>, %x
64  %sub2 = fsub <2 x float> <float -0.0, float -0.0>, %y
65  %mul = fmul arcp <2 x float> %sub1, %sub2
66  ret <2 x float> %mul
67}
68
69define <2 x float> @neg_neg_vec_undef(<2 x float> %x, <2 x float> %y) {
70; CHECK-LABEL: @neg_neg_vec_undef(
71; CHECK-NEXT:    [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]]
72; CHECK-NEXT:    ret <2 x float> [[MUL]]
73;
74  %sub1 = fsub <2 x float> <float -0.0, float undef>, %x
75  %sub2 = fsub <2 x float> <float undef, float -0.0>, %y
76  %mul = fmul arcp <2 x float> %sub1, %sub2
77  ret <2 x float> %mul
78}
79
80; (0.0 - X) * (0.0 - Y) => X * Y
81define float @neg_neg_nsz(float %x, float %y) {
82; CHECK-LABEL: @neg_neg_nsz(
83; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X:%.*]], [[Y:%.*]]
84; CHECK-NEXT:    ret float [[MUL]]
85;
86  %sub1 = fsub nsz float 0.0, %x
87  %sub2 = fsub nsz float 0.0, %y
88  %mul = fmul afn float %sub1, %sub2
89  ret float %mul
90}
91
92declare void @use_f32(float)
93
94define float @neg_neg_multi_use(float %x, float %y) {
95; CHECK-LABEL: @neg_neg_multi_use(
96; CHECK-NEXT:    [[NX:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
97; CHECK-NEXT:    [[NY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]]
98; CHECK-NEXT:    [[MUL:%.*]] = fmul afn float [[X]], [[Y]]
99; CHECK-NEXT:    call void @use_f32(float [[NX]])
100; CHECK-NEXT:    call void @use_f32(float [[NY]])
101; CHECK-NEXT:    ret float [[MUL]]
102;
103  %nx = fsub float -0.0, %x
104  %ny = fsub float -0.0, %y
105  %mul = fmul afn float %nx, %ny
106  call void @use_f32(float %nx)
107  call void @use_f32(float %ny)
108  ret float %mul
109}
110
111; (-0.0 - X) * Y => -0.0 - (X * Y)
112define float @neg_sink(float %x, float %y) {
113; CHECK-LABEL: @neg_sink(
114; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
115; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
116; CHECK-NEXT:    ret float [[MUL]]
117;
118  %sub = fsub float -0.0, %x
119  %mul = fmul float %sub, %y
120  ret float %mul
121}
122
123define <2 x float> @neg_sink_vec(<2 x float> %x, <2 x float> %y) {
124; CHECK-LABEL: @neg_sink_vec(
125; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
126; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
127; CHECK-NEXT:    ret <2 x float> [[MUL]]
128;
129  %sub = fsub <2 x float> <float -0.0, float -0.0>, %x
130  %mul = fmul <2 x float> %sub, %y
131  ret <2 x float> %mul
132}
133
134define <2 x float> @neg_sink_vec_undef(<2 x float> %x, <2 x float> %y) {
135; CHECK-LABEL: @neg_sink_vec_undef(
136; CHECK-NEXT:    [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]]
137; CHECK-NEXT:    [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
138; CHECK-NEXT:    ret <2 x float> [[MUL]]
139;
140  %sub = fsub <2 x float> <float undef, float -0.0>, %x
141  %mul = fmul <2 x float> %sub, %y
142  ret <2 x float> %mul
143}
144
145; (0.0 - X) * Y => 0.0 - (X * Y)
146define float @neg_sink_nsz(float %x, float %y) {
147; CHECK-LABEL: @neg_sink_nsz(
148; CHECK-NEXT:    [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
149; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]]
150; CHECK-NEXT:    ret float [[MUL]]
151;
152  %sub1 = fsub nsz float 0.0, %x
153  %mul = fmul float %sub1, %y
154  ret float %mul
155}
156
157; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X"
158; has multiple uses.
159define float @neg_sink_multi_use(float %x, float %y) {
160; CHECK-LABEL: @neg_sink_multi_use(
161; CHECK-NEXT:    [[SUB1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
162; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB1]], [[Y:%.*]]
163; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]]
164; CHECK-NEXT:    ret float [[MUL2]]
165;
166  %sub1 = fsub float -0.0, %x
167  %mul = fmul float %sub1, %y
168  %mul2 = fmul float %mul, %sub1
169  ret float %mul2
170}
171
172; Don't crash when attempting to cast a constant FMul to an instruction.
173define void @test8(i32* %inout) {
174; CHECK-LABEL: @test8(
175; CHECK-NEXT:  entry:
176; CHECK-NEXT:    br label [[FOR_COND:%.*]]
177; CHECK:       for.cond:
178; 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:%.*]] ]
179; CHECK-NEXT:    br i1 undef, label [[FOR_BODY]], label [[FOR_END:%.*]]
180; CHECK:       for.body:
181; CHECK-NEXT:    [[TMP0]] = insertelement <4 x float> [[LOCAL_VAR_7_0]], float 0.000000e+00, i32 2
182; CHECK-NEXT:    br label [[FOR_COND]]
183; CHECK:       for.end:
184; CHECK-NEXT:    ret void
185;
186entry:
187  %0 = load i32, i32* %inout, align 4
188  %conv = uitofp i32 %0 to float
189  %vecinit = insertelement <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float undef>, float %conv, i32 3
190  %sub = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %vecinit
191  %1 = shufflevector <4 x float> %sub, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
192  %mul = fmul <4 x float> zeroinitializer, %1
193  br label %for.cond
194
195for.cond:                                         ; preds = %for.body, %entry
196  %local_var_7.0 = phi <4 x float> [ %mul, %entry ], [ %2, %for.body ]
197  br i1 undef, label %for.body, label %for.end
198
199for.body:                                         ; preds = %for.cond
200  %2 = insertelement <4 x float> %local_var_7.0, float 0.000000e+00, i32 2
201  br label %for.cond
202
203for.end:                                          ; preds = %for.cond
204  ret void
205}
206
207; X * -1.0 => -0.0 - X
208define float @test9(float %x) {
209; CHECK-LABEL: @test9(
210; CHECK-NEXT:    [[MUL:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
211; CHECK-NEXT:    ret float [[MUL]]
212;
213  %mul = fmul float %x, -1.0
214  ret float %mul
215}
216
217; PR18532
218define <4 x float> @test10(<4 x float> %x) {
219; CHECK-LABEL: @test10(
220; CHECK-NEXT:    [[MUL:%.*]] = fsub arcp afn <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
221; CHECK-NEXT:    ret <4 x float> [[MUL]]
222;
223  %mul = fmul arcp afn <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
224  ret <4 x float> %mul
225}
226
227define float @test11(float %x, float %y) {
228; CHECK-LABEL: @test11(
229; CHECK-NEXT:    [[B:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]]
230; CHECK-NEXT:    [[C:%.*]] = fadd fast float [[B]], 3.000000e+00
231; CHECK-NEXT:    ret float [[C]]
232;
233  %a = fadd fast float %x, 1.0
234  %b = fadd fast float %y, 2.0
235  %c = fadd fast float %a, %b
236  ret float %c
237}
238
239declare double @llvm.sqrt.f64(double)
240
241; With unsafe/fast math, sqrt(X) * sqrt(X) is just X,
242; but make sure another use of the sqrt is intact.
243; Note that the remaining fmul is altered but is not 'fast'
244; itself because it was not marked 'fast' originally.
245; Thus, we have an overall fast result, but no more indication of
246; 'fast'ness in the code.
247define double @sqrt_squared2(double %f) {
248; CHECK-LABEL: @sqrt_squared2(
249; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]])
250; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[SQRT]], [[F]]
251; CHECK-NEXT:    ret double [[MUL2]]
252;
253  %sqrt = call double @llvm.sqrt.f64(double %f)
254  %mul1 = fmul fast double %sqrt, %sqrt
255  %mul2 = fmul double %mul1, %sqrt
256  ret double %mul2
257}
258
259declare float @llvm.fabs.f32(float) nounwind readnone
260
261define float @fabs_squared(float %x) {
262; CHECK-LABEL: @fabs_squared(
263; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
264; CHECK-NEXT:    ret float [[MUL]]
265;
266  %x.fabs = call float @llvm.fabs.f32(float %x)
267  %mul = fmul float %x.fabs, %x.fabs
268  ret float %mul
269}
270
271define float @fabs_squared_fast(float %x) {
272; CHECK-LABEL: @fabs_squared_fast(
273; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[X]]
274; CHECK-NEXT:    ret float [[MUL]]
275;
276  %x.fabs = call float @llvm.fabs.f32(float %x)
277  %mul = fmul fast float %x.fabs, %x.fabs
278  ret float %mul
279}
280
281define float @fabs_x_fabs(float %x, float %y) {
282; CHECK-LABEL: @fabs_x_fabs(
283; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
284; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
285; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_FABS]]
286; CHECK-NEXT:    ret float [[MUL]]
287;
288  %x.fabs = call float @llvm.fabs.f32(float %x)
289  %y.fabs = call float @llvm.fabs.f32(float %y)
290  %mul = fmul float %x.fabs, %y.fabs
291  ret float %mul
292}
293
294; (X*Y) * X => (X*X) * Y
295; The transform only requires 'reassoc', but test other FMF in
296; the commuted variants to make sure FMF propagates as expected.
297
298define float @reassoc_common_operand1(float %x, float %y) {
299; CHECK-LABEL: @reassoc_common_operand1(
300; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], [[X]]
301; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc float [[TMP1]], [[Y:%.*]]
302; CHECK-NEXT:    ret float [[MUL2]]
303;
304  %mul1 = fmul float %x, %y
305  %mul2 = fmul reassoc float %mul1, %x
306  ret float %mul2
307}
308
309; (Y*X) * X => (X*X) * Y
310
311define float @reassoc_common_operand2(float %x, float %y) {
312; CHECK-LABEL: @reassoc_common_operand2(
313; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[X]]
314; CHECK-NEXT:    [[MUL2:%.*]] = fmul fast float [[TMP1]], [[Y:%.*]]
315; CHECK-NEXT:    ret float [[MUL2]]
316;
317  %mul1 = fmul float %y, %x
318  %mul2 = fmul fast float %mul1, %x
319  ret float %mul2
320}
321
322; X * (X*Y) => (X*X) * Y
323
324define float @reassoc_common_operand3(float %x1, float %y) {
325; CHECK-LABEL: @reassoc_common_operand3(
326; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 3.000000e+00
327; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc nnan float [[X]], [[X]]
328; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc nnan float [[TMP1]], [[Y:%.*]]
329; CHECK-NEXT:    ret float [[MUL2]]
330;
331  %x = fdiv float %x1, 3.0 ; thwart complexity-based canonicalization
332  %mul1 = fmul float %x, %y
333  %mul2 = fmul reassoc nnan float %x, %mul1
334  ret float %mul2
335}
336
337; X * (Y*X) => (X*X) * Y
338
339define float @reassoc_common_operand4(float %x1, float %y) {
340; CHECK-LABEL: @reassoc_common_operand4(
341; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 3.000000e+00
342; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc ninf float [[X]], [[X]]
343; CHECK-NEXT:    [[MUL2:%.*]] = fmul reassoc ninf float [[TMP1]], [[Y:%.*]]
344; CHECK-NEXT:    ret float [[MUL2]]
345;
346  %x = fdiv float %x1, 3.0 ; thwart complexity-based canonicalization
347  %mul1 = fmul float %y, %x
348  %mul2 = fmul reassoc ninf float %x, %mul1
349  ret float %mul2
350}
351
352; No change if the first fmul has another use.
353
354define float @reassoc_common_operand_multi_use(float %x, float %y) {
355; CHECK-LABEL: @reassoc_common_operand_multi_use(
356; CHECK-NEXT:    [[MUL1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
357; CHECK-NEXT:    [[MUL2:%.*]] = fmul fast float [[MUL1]], [[X]]
358; CHECK-NEXT:    call void @use_f32(float [[MUL1]])
359; CHECK-NEXT:    ret float [[MUL2]]
360;
361  %mul1 = fmul float %x, %y
362  %mul2 = fmul fast float %mul1, %x
363  call void @use_f32(float %mul1)
364  ret float %mul2
365}
366
367declare float @llvm.log2.f32(float)
368
369; log2(Y * 0.5) * X = log2(Y) * X - X
370
371define float @log2half(float %x, float %y) {
372; CHECK-LABEL: @log2half(
373; CHECK-NEXT:    [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
374; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X:%.*]]
375; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
376; CHECK-NEXT:    ret float [[MUL]]
377;
378  %halfy = fmul float %y, 0.5
379  %log2 = call float @llvm.log2.f32(float %halfy)
380  %mul = fmul fast float %log2, %x
381  ret float %mul
382}
383
384define float @log2half_commute(float %x1, float %y) {
385; CHECK-LABEL: @log2half_commute(
386; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 7.000000e+00
387; CHECK-NEXT:    [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
388; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]]
389; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
390; CHECK-NEXT:    ret float [[MUL]]
391;
392  %x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization
393  %halfy = fmul float %y, 0.5
394  %log2 = call float @llvm.log2.f32(float %halfy)
395  %mul = fmul fast float %x, %log2
396  ret float %mul
397}
398
399; C1/X * C2 => (C1*C2) / X
400
401define float @fdiv_constant_numerator_fmul(float %x) {
402; CHECK-LABEL: @fdiv_constant_numerator_fmul(
403; CHECK-NEXT:    [[T3:%.*]] = fdiv reassoc float 1.200000e+07, [[X:%.*]]
404; CHECK-NEXT:    ret float [[T3]]
405;
406  %t1 = fdiv float 2.0e+3, %x
407  %t3 = fmul reassoc float %t1, 6.0e+3
408  ret float %t3
409}
410
411; C1/X * C2 => (C1*C2) / X is disabled if C1/X has multiple uses
412
413@fmul2_external = external global float
414
415define float @fdiv_constant_numerator_fmul_extra_use(float %x) {
416; CHECK-LABEL: @fdiv_constant_numerator_fmul_extra_use(
417; CHECK-NEXT:    [[DIV:%.*]] = fdiv fast float 1.000000e+00, [[X:%.*]]
418; CHECK-NEXT:    store float [[DIV]], float* @fmul2_external, align 4
419; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[DIV]], 2.000000e+00
420; CHECK-NEXT:    ret float [[MUL]]
421;
422  %div = fdiv fast float 1.0, %x
423  store float %div, float* @fmul2_external
424  %mul = fmul fast float %div, 2.0
425  ret float %mul
426}
427
428; X/C1 * C2 => X * (C2/C1) (if C2/C1 is normal FP)
429
430define float @fdiv_constant_denominator_fmul(float %x) {
431; CHECK-LABEL: @fdiv_constant_denominator_fmul(
432; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
433; CHECK-NEXT:    ret float [[T3]]
434;
435  %t1 = fdiv float %x, 2.0e+3
436  %t3 = fmul reassoc float %t1, 6.0e+3
437  ret float %t3
438}
439
440define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
441; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec(
442; 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>
443; CHECK-NEXT:    ret <4 x float> [[T3]]
444;
445  %t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
446  %t3 = fmul reassoc <4 x float> %t1, <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3>
447  ret <4 x float> %t3
448}
449
450; Make sure fmul with constant expression doesn't assert.
451
452define <4 x float> @fdiv_constant_denominator_fmul_vec_constexpr(<4 x float> %x) {
453; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec_constexpr(
454; 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>
455; CHECK-NEXT:    ret <4 x float> [[T3]]
456;
457  %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>
458  %t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
459  %t3 = fmul reassoc <4 x float> %t1, %constExprMul
460  ret <4 x float> %t3
461}
462
463; Rule "X/C1 * C2 => X * (C2/C1) is not applicable if C2/C1 is abnormal
464; 0x3810000000000000 == FLT_MIN
465
466define float @fdiv_constant_denominator_fmul_denorm(float %x) {
467; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm(
468; CHECK-NEXT:    [[T1:%.*]] = fdiv float [[X:%.*]], 2.000000e+03
469; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
470; CHECK-NEXT:    ret float [[T3]]
471;
472  %t1 = fdiv float %x, 2.0e+3
473  %t3 = fmul fast float %t1, 0x3810000000000000
474  ret float %t3
475}
476
477; X / C1 * C2 => X / (C2/C1) if C1/C2 is abnormal, but C2/C1 is a normal value.
478; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
479; by a denormal, but we could do better when we know that denormals are not a problem.
480
481define float @fdiv_constant_denominator_fmul_denorm_try_harder(float %x) {
482; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder(
483; CHECK-NEXT:    [[T3:%.*]] = fdiv reassoc float [[X:%.*]], 0x47E8000000000000
484; CHECK-NEXT:    ret float [[T3]]
485;
486  %t1 = fdiv float %x, 3.0
487  %t3 = fmul reassoc float %t1, 0x3810000000000000
488  ret float %t3
489}
490
491; Negative test: we should not have 2 divisions instead of the 1 we started with.
492
493define float @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(float %x) {
494; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(
495; CHECK-NEXT:    [[T1:%.*]] = fdiv float [[X:%.*]], 3.000000e+00
496; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
497; CHECK-NEXT:    [[R:%.*]] = fadd float [[T1]], [[T3]]
498; CHECK-NEXT:    ret float [[R]]
499;
500  %t1 = fdiv float %x, 3.0e+0
501  %t3 = fmul fast float %t1, 0x3810000000000000
502  %r = fadd float %t1, %t3
503  ret float %r
504}
505
506; (X + C1) * C2 --> (X * C2) + C1*C2
507
508define float @fmul_fadd_distribute(float %x) {
509; CHECK-LABEL: @fmul_fadd_distribute(
510; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
511; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc float [[TMP1]], 6.000000e+00
512; CHECK-NEXT:    ret float [[T3]]
513;
514  %t2 = fadd float %x, 2.0
515  %t3 = fmul reassoc float %t2, 3.0
516  ret float %t3
517}
518
519; (X - C1) * C2 --> (X * C2) - C1*C2
520
521define float @fmul_fsub_distribute1(float %x) {
522; CHECK-LABEL: @fmul_fsub_distribute1(
523; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
524; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc float [[TMP1]], -6.000000e+00
525; CHECK-NEXT:    ret float [[T3]]
526;
527  %t2 = fsub float %x, 2.0
528  %t3 = fmul reassoc float %t2, 3.0
529  ret float %t3
530}
531
532; (C1 - X) * C2 --> C1*C2 - (X * C2)
533
534define float @fmul_fsub_distribute2(float %x) {
535; CHECK-LABEL: @fmul_fsub_distribute2(
536; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 3.000000e+00
537; CHECK-NEXT:    [[T3:%.*]] = fsub reassoc float 6.000000e+00, [[TMP1]]
538; CHECK-NEXT:    ret float [[T3]]
539;
540  %t2 = fsub float 2.0, %x
541  %t3 = fmul reassoc float %t2, 3.0
542  ret float %t3
543}
544
545; FIXME: This should only need 'reassoc'.
546; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3)
547
548define float @fmul_fadd_fmul_distribute(float %x) {
549; CHECK-LABEL: @fmul_fadd_fmul_distribute(
550; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
551; CHECK-NEXT:    [[T3:%.*]] = fadd fast float [[TMP1]], 1.000000e+01
552; CHECK-NEXT:    ret float [[T3]]
553;
554  %t1 = fmul float %x, 6.0
555  %t2 = fadd float %t1, 2.0
556  %t3 = fmul fast float %t2, 5.0
557  ret float %t3
558}
559
560define float @fmul_fadd_distribute_extra_use(float %x) {
561; CHECK-LABEL: @fmul_fadd_distribute_extra_use(
562; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
563; CHECK-NEXT:    [[T2:%.*]] = fadd float [[T1]], 2.000000e+00
564; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
565; CHECK-NEXT:    call void @use_f32(float [[T2]])
566; CHECK-NEXT:    ret float [[T3]]
567;
568  %t1 = fmul float %x, 6.0
569  %t2 = fadd float %t1, 2.0
570  %t3 = fmul fast float %t2, 5.0
571  call void @use_f32(float %t2)
572  ret float %t3
573}
574
575; (X/C1 + C2) * C3 => X/(C1/C3) + C2*C3
576; 0x10000000000000 = DBL_MIN
577; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
578; by a denormal, but we could do better when we know that denormals are not a problem.
579
580define double @fmul_fadd_fdiv_distribute2(double %x) {
581; CHECK-LABEL: @fmul_fadd_fdiv_distribute2(
582; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc double [[X:%.*]], 0x7FE8000000000000
583; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc double [[TMP1]], 0x34000000000000
584; CHECK-NEXT:    ret double [[T3]]
585;
586  %t1 = fdiv double %x, 3.0
587  %t2 = fadd double %t1, 5.0
588  %t3 = fmul reassoc double %t2, 0x10000000000000
589  ret double %t3
590}
591
592; 5.0e-1 * DBL_MIN yields denormal, so "(f1*3.0 + 5.0e-1) * DBL_MIN" cannot
593; be simplified into f1 * (3.0*DBL_MIN) + (5.0e-1*DBL_MIN)
594
595define double @fmul_fadd_fdiv_distribute3(double %x) {
596; CHECK-LABEL: @fmul_fadd_fdiv_distribute3(
597; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc double [[X:%.*]], 0x7FE8000000000000
598; CHECK-NEXT:    [[T3:%.*]] = fadd reassoc double [[TMP1]], 0x34000000000000
599; CHECK-NEXT:    ret double [[T3]]
600;
601  %t1 = fdiv double %x, 3.0
602  %t2 = fadd double %t1, 5.0
603  %t3 = fmul reassoc double %t2, 0x10000000000000
604  ret double %t3
605}
606
607; FIXME: This should only need 'reassoc'.
608; (C2 - (X*C1)) * C3 => (C2*C3) - (X * (C1*C3))
609
610define float @fmul_fsub_fmul_distribute(float %x) {
611; CHECK-LABEL: @fmul_fsub_fmul_distribute(
612; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
613; CHECK-NEXT:    [[T3:%.*]] = fsub fast float 1.000000e+01, [[TMP1]]
614; CHECK-NEXT:    ret float [[T3]]
615;
616  %t1 = fmul float %x, 6.0
617  %t2 = fsub float 2.0, %t1
618  %t3 = fmul fast float %t2, 5.0
619  ret float %t3
620}
621
622define float @fmul_fsub_fmul_distribute_extra_use(float %x) {
623; CHECK-LABEL: @fmul_fsub_fmul_distribute_extra_use(
624; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
625; CHECK-NEXT:    [[T2:%.*]] = fsub float 2.000000e+00, [[T1]]
626; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
627; CHECK-NEXT:    call void @use_f32(float [[T2]])
628; CHECK-NEXT:    ret float [[T3]]
629;
630  %t1 = fmul float %x, 6.0
631  %t2 = fsub float 2.0, %t1
632  %t3 = fmul fast float %t2, 5.0
633  call void @use_f32(float %t2)
634  ret float %t3
635}
636
637; FIXME: This should only need 'reassoc'.
638; ((X*C1) - C2) * C3 => (X * (C1*C3)) - C2*C3
639
640define float @fmul_fsub_fmul_distribute2(float %x) {
641; CHECK-LABEL: @fmul_fsub_fmul_distribute2(
642; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+01
643; CHECK-NEXT:    [[T3:%.*]] = fadd fast float [[TMP1]], -1.000000e+01
644; CHECK-NEXT:    ret float [[T3]]
645;
646  %t1 = fmul float %x, 6.0
647  %t2 = fsub float %t1, 2.0
648  %t3 = fmul fast float %t2, 5.0
649  ret float %t3
650}
651
652define float @fmul_fsub_fmul_distribute2_extra_use(float %x) {
653; CHECK-LABEL: @fmul_fsub_fmul_distribute2_extra_use(
654; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], 6.000000e+00
655; CHECK-NEXT:    [[T2:%.*]] = fsub float 2.000000e+00, [[T1]]
656; CHECK-NEXT:    [[T3:%.*]] = fmul fast float [[T2]], 5.000000e+00
657; CHECK-NEXT:    call void @use_f32(float [[T2]])
658; CHECK-NEXT:    ret float [[T3]]
659;
660  %t1 = fmul float %x, 6.0
661  %t2 = fsub float 2.0, %t1
662  %t3 = fmul fast float %t2, 5.0
663  call void @use_f32(float %t2)
664  ret float %t3
665}
666
667; "(X*Y) * X => (X*X) * Y" is disabled if "X*Y" has multiple uses
668
669define float @common_factor(float %x, float %y) {
670; CHECK-LABEL: @common_factor(
671; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
672; CHECK-NEXT:    [[MUL1:%.*]] = fmul fast float [[MUL]], [[X]]
673; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[MUL1]], [[MUL]]
674; CHECK-NEXT:    ret float [[ADD]]
675;
676  %mul = fmul float %x, %y
677  %mul1 = fmul fast float %mul, %x
678  %add = fadd float %mul1, %mul
679  ret float %add
680}
681
682