[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / fadd-fsub-factor.ll
blobb5e1e84529e08b8998b846697b3c7c0ae6534b4a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; =========================================================================
6 ;   Test FP factorization with patterns:
7 ;   X * Z + Y * Z --> (X + Y) * Z (including all 4 commuted variants)
8 ;   X * Z - Y * Z --> (X - Y) * Z (including all 4 commuted variants)
9 ;   X / Z + Y / Z --> (X + Y) / Z
10 ;   X / Z - Y / Z --> (X - Y) / Z
12 ; =========================================================================
14 ; Minimum FMF - the final result requires/propagates FMF.
16 define float @fmul_fadd(float %x, float %y, float %z) {
17 ; CHECK-LABEL: @fmul_fadd(
18 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]]
19 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]]
20 ; CHECK-NEXT:    ret float [[R]]
22   %t1 = fmul float %x, %z
23   %t2 = fmul float %y, %z
24   %r = fadd reassoc nsz float %t1, %t2
25   ret float %r
28 ; Verify vector types and commuted operands.
30 define <2 x float> @fmul_fadd_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
31 ; CHECK-LABEL: @fmul_fadd_commute1_vec(
32 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
33 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
34 ; CHECK-NEXT:    ret <2 x float> [[R]]
36   %t1 = fmul <2 x float> %z, %x
37   %t2 = fmul <2 x float> %z, %y
38   %r = fadd reassoc nsz <2 x float> %t1, %t2
39   ret <2 x float> %r
42 ; Verify vector types, commuted operands, FMF propagation.
44 define <2 x float> @fmul_fadd_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
45 ; CHECK-LABEL: @fmul_fadd_commute2_vec(
46 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]]
47 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]]
48 ; CHECK-NEXT:    ret <2 x float> [[R]]
50   %t1 = fmul fast <2 x float> %x, %z
51   %t2 = fmul nnan <2 x float> %z, %y
52   %r = fadd reassoc nsz ninf <2 x float> %t1, %t2
53   ret <2 x float> %r
56 ; Verify different scalar type, commuted operands, FMF propagation.
58 define double @fmul_fadd_commute3(double %x, double %y, double %z) {
59 ; CHECK-LABEL: @fmul_fadd_commute3(
60 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nnan nsz double [[X:%.*]], [[Y:%.*]]
61 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
62 ; CHECK-NEXT:    ret double [[R]]
64   %t1 = fmul double %z, %x
65   %t2 = fmul fast double %y, %z
66   %r = fadd reassoc nsz nnan double %t1, %t2
67   ret double %r
70 ; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required).
72 define float @fmul_fadd_not_enough_FMF(float %x, float %y, float %z) {
73 ; CHECK-LABEL: @fmul_fadd_not_enough_FMF(
74 ; CHECK-NEXT:    [[T1:%.*]] = fmul fast float [[X:%.*]], [[Z:%.*]]
75 ; CHECK-NEXT:    [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]]
76 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc float [[T1]], [[T2]]
77 ; CHECK-NEXT:    ret float [[R]]
79   %t1 = fmul fast float %x, %z
80   %t2 = fmul fast float %y, %z
81   %r = fadd reassoc float %t1, %t2
82   ret float %r
85 declare void @use(float)
87 ; Negative test - extra uses should disable the fold.
89 define float @fmul_fadd_uses1(float %x, float %y, float %z) {
90 ; CHECK-LABEL: @fmul_fadd_uses1(
91 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
92 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
93 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
94 ; CHECK-NEXT:    call void @use(float [[T1]])
95 ; CHECK-NEXT:    ret float [[R]]
97   %t1 = fmul float %z, %x
98   %t2 = fmul float %y, %z
99   %r = fadd reassoc nsz float %t1, %t2
100   call void @use(float %t1)
101   ret float %r
104 ; Negative test - extra uses should disable the fold.
106 define float @fmul_fadd_uses2(float %x, float %y, float %z) {
107 ; CHECK-LABEL: @fmul_fadd_uses2(
108 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
109 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
110 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
111 ; CHECK-NEXT:    call void @use(float [[T2]])
112 ; CHECK-NEXT:    ret float [[R]]
114   %t1 = fmul float %z, %x
115   %t2 = fmul float %z, %y
116   %r = fadd reassoc nsz float %t1, %t2
117   call void @use(float %t2)
118   ret float %r
121 ; Negative test - extra uses should disable the fold.
123 define float @fmul_fadd_uses3(float %x, float %y, float %z) {
124 ; CHECK-LABEL: @fmul_fadd_uses3(
125 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
126 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
127 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
128 ; CHECK-NEXT:    call void @use(float [[T1]])
129 ; CHECK-NEXT:    call void @use(float [[T2]])
130 ; CHECK-NEXT:    ret float [[R]]
132   %t1 = fmul float %x, %z
133   %t2 = fmul float %z, %y
134   %r = fadd reassoc nsz float %t1, %t2
135   call void @use(float %t1)
136   call void @use(float %t2)
137   ret float %r
140 ; Minimum FMF - the final result requires/propagates FMF.
142 define half @fmul_fsub(half %x, half %y, half %z) {
143 ; CHECK-LABEL: @fmul_fsub(
144 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz half [[X:%.*]], [[Y:%.*]]
145 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz half [[TMP1]], [[Z:%.*]]
146 ; CHECK-NEXT:    ret half [[R]]
148   %t1 = fmul half %x, %z
149   %t2 = fmul half %y, %z
150   %r = fsub reassoc nsz half %t1, %t2
151   ret half %r
154 ; Verify vector types and commuted operands.
156 define <2 x float> @fmul_fsub_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
157 ; CHECK-LABEL: @fmul_fsub_commute1_vec(
158 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
159 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
160 ; CHECK-NEXT:    ret <2 x float> [[R]]
162   %t1 = fmul <2 x float> %z, %x
163   %t2 = fmul <2 x float> %y, %z
164   %r = fsub reassoc nsz <2 x float> %t1, %t2
165   ret <2 x float> %r
168 ; Verify vector types, commuted operands, FMF propagation.
170 define <2 x float> @fmul_fsub_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
171 ; CHECK-LABEL: @fmul_fsub_commute2_vec(
172 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]]
173 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]]
174 ; CHECK-NEXT:    ret <2 x float> [[R]]
176   %t1 = fmul fast <2 x float> %x, %z
177   %t2 = fmul nnan <2 x float> %z, %y
178   %r = fsub reassoc nsz ninf <2 x float> %t1, %t2
179   ret <2 x float> %r
182 ; Verify different scalar type, commuted operands, FMF propagation.
184 define double @fmul_fsub_commute3(double %x, double %y, double %z) {
185 ; CHECK-LABEL: @fmul_fsub_commute3(
186 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nnan nsz double [[X:%.*]], [[Y:%.*]]
187 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
188 ; CHECK-NEXT:    ret double [[R]]
190   %t1 = fmul double %z, %x
191   %t2 = fmul fast double %z, %y
192   %r = fsub reassoc nsz nnan double %t1, %t2
193   ret double %r
196 ; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required).
198 define float @fmul_fsub_not_enough_FMF(float %x, float %y, float %z) {
199 ; CHECK-LABEL: @fmul_fsub_not_enough_FMF(
200 ; CHECK-NEXT:    [[T1:%.*]] = fmul fast float [[Z:%.*]], [[X:%.*]]
201 ; CHECK-NEXT:    [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]]
202 ; CHECK-NEXT:    [[R:%.*]] = fsub nsz float [[T1]], [[T2]]
203 ; CHECK-NEXT:    ret float [[R]]
205   %t1 = fmul fast float %z, %x
206   %t2 = fmul fast float %y, %z
207   %r = fsub nsz float %t1, %t2
208   ret float %r
211 ; Negative test - extra uses should disable the fold.
213 define float @fmul_fsub_uses1(float %x, float %y, float %z) {
214 ; CHECK-LABEL: @fmul_fsub_uses1(
215 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
216 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
217 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
218 ; CHECK-NEXT:    call void @use(float [[T1]])
219 ; CHECK-NEXT:    ret float [[R]]
221   %t1 = fmul float %x, %z
222   %t2 = fmul float %y, %z
223   %r = fsub reassoc nsz float %t1, %t2
224   call void @use(float %t1)
225   ret float %r
228 ; Negative test - extra uses should disable the fold.
230 define float @fmul_fsub_uses2(float %x, float %y, float %z) {
231 ; CHECK-LABEL: @fmul_fsub_uses2(
232 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
233 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
234 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
235 ; CHECK-NEXT:    call void @use(float [[T2]])
236 ; CHECK-NEXT:    ret float [[R]]
238   %t1 = fmul float %z, %x
239   %t2 = fmul float %z, %y
240   %r = fsub reassoc nsz float %t1, %t2
241   call void @use(float %t2)
242   ret float %r
245 ; Negative test - extra uses should disable the fold.
247 define float @fmul_fsub_uses3(float %x, float %y, float %z) {
248 ; CHECK-LABEL: @fmul_fsub_uses3(
249 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
250 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
251 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
252 ; CHECK-NEXT:    call void @use(float [[T1]])
253 ; CHECK-NEXT:    call void @use(float [[T2]])
254 ; CHECK-NEXT:    ret float [[R]]
256   %t1 = fmul float %x, %z
257   %t2 = fmul float %y, %z
258   %r = fsub reassoc nsz float %t1, %t2
259   call void @use(float %t1)
260   call void @use(float %t2)
261   ret float %r
264 ; Common divisor
266 define double @fdiv_fadd(double %x, double %y, double %z) {
267 ; CHECK-LABEL: @fdiv_fadd(
268 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz double [[X:%.*]], [[Y:%.*]]
269 ; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz double [[TMP1]], [[Z:%.*]]
270 ; CHECK-NEXT:    ret double [[R]]
272   %t1 = fdiv double %x, %z
273   %t2 = fdiv double %y, %z
274   %r = fadd reassoc nsz double %t1, %t2
275   ret double %r
278 define float @fdiv_fsub(float %x, float %y, float %z) {
279 ; CHECK-LABEL: @fdiv_fsub(
280 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]]
281 ; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz float [[TMP1]], [[Z:%.*]]
282 ; CHECK-NEXT:    ret float [[R]]
284   %t1 = fdiv fast float %x, %z
285   %t2 = fdiv nnan float %y, %z
286   %r = fsub reassoc nsz float %t1, %t2
287   ret float %r
290 ; Verify vector types.
292 define <2 x double> @fdiv_fadd_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z) {
293 ; CHECK-LABEL: @fdiv_fadd_vec(
294 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz <2 x double> [[X:%.*]], [[Y:%.*]]
295 ; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz <2 x double> [[TMP1]], [[Z:%.*]]
296 ; CHECK-NEXT:    ret <2 x double> [[R]]
298   %t1 = fdiv fast <2 x double> %x, %z
299   %t2 = fdiv <2 x double> %y, %z
300   %r = fadd reassoc nsz <2 x double> %t1, %t2
301   ret <2 x double> %r
304 ; Verify vector types.
306 define <2 x float> @fdiv_fsub_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
307 ; CHECK-LABEL: @fdiv_fsub_vec(
308 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
309 ; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
310 ; CHECK-NEXT:    ret <2 x float> [[R]]
312   %t1 = fdiv <2 x float> %x, %z
313   %t2 = fdiv nnan <2 x float> %y, %z
314   %r = fsub reassoc nsz <2 x float> %t1, %t2
315   ret <2 x float> %r
318 ; Negative test - common operand is not divisor.
320 define float @fdiv_fadd_commute1(float %x, float %y, float %z) {
321 ; CHECK-LABEL: @fdiv_fadd_commute1(
322 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]]
323 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Z]], [[X:%.*]]
324 ; CHECK-NEXT:    [[R:%.*]] = fadd fast float [[T1]], [[T2]]
325 ; CHECK-NEXT:    ret float [[R]]
327   %t1 = fdiv fast float %z, %y
328   %t2 = fdiv fast float %z, %x
329   %r = fadd fast float %t1, %t2
330   ret float %r
333 ; Negative test - common operand is not divisor.
335 define float @fdiv_fsub_commute2(float %x, float %y, float %z) {
336 ; CHECK-LABEL: @fdiv_fsub_commute2(
337 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]]
338 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[X:%.*]], [[Z]]
339 ; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
340 ; CHECK-NEXT:    ret float [[R]]
342   %t1 = fdiv fast float %z, %y
343   %t2 = fdiv fast float %x, %z
344   %r = fsub fast float %t1, %t2
345   ret float %r
348 ; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required).
350 define float @fdiv_fadd_not_enough_FMF(float %x, float %y, float %z) {
351 ; CHECK-LABEL: @fdiv_fadd_not_enough_FMF(
352 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]]
353 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]]
354 ; CHECK-NEXT:    [[T3:%.*]] = fadd nsz float [[T1]], [[T2]]
355 ; CHECK-NEXT:    ret float [[T3]]
357   %t1 = fdiv fast float %y, %x
358   %t2 = fdiv fast float %z, %x
359   %t3 = fadd nsz float %t1, %t2
360   ret float %t3
363 ; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required).
365 define float @fdiv_fsub_not_enough_FMF(float %x, float %y, float %z) {
366 ; CHECK-LABEL: @fdiv_fsub_not_enough_FMF(
367 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]]
368 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]]
369 ; CHECK-NEXT:    [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]]
370 ; CHECK-NEXT:    ret float [[T3]]
372   %t1 = fdiv fast float %y, %x
373   %t2 = fdiv fast float %z, %x
374   %t3 = fsub reassoc float %t1, %t2
375   ret float %t3
378 ; Negative test - extra uses should disable the fold.
380 define float @fdiv_fadd_uses1(float %x, float %y, float %z) {
381 ; CHECK-LABEL: @fdiv_fadd_uses1(
382 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
383 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
384 ; CHECK-NEXT:    [[R:%.*]] = fadd fast float [[T1]], [[T2]]
385 ; CHECK-NEXT:    call void @use(float [[T1]])
386 ; CHECK-NEXT:    ret float [[R]]
388   %t1 = fdiv fast float %x, %z
389   %t2 = fdiv fast float %y, %z
390   %r = fadd fast float %t1, %t2
391   call void @use(float %t1)
392   ret float %r
395 ; Negative test - extra uses should disable the fold.
397 define float @fdiv_fsub_uses2(float %x, float %y, float %z) {
398 ; CHECK-LABEL: @fdiv_fsub_uses2(
399 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
400 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
401 ; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
402 ; CHECK-NEXT:    call void @use(float [[T2]])
403 ; CHECK-NEXT:    ret float [[R]]
405   %t1 = fdiv fast float %x, %z
406   %t2 = fdiv fast float %y, %z
407   %r = fsub fast float %t1, %t2
408   call void @use(float %t2)
409   ret float %r
412 ; Negative test - extra uses should disable the fold.
414 define float @fdiv_fsub_uses3(float %x, float %y, float %z) {
415 ; CHECK-LABEL: @fdiv_fsub_uses3(
416 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
417 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
418 ; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
419 ; CHECK-NEXT:    call void @use(float [[T1]])
420 ; CHECK-NEXT:    call void @use(float [[T2]])
421 ; CHECK-NEXT:    ret float [[R]]
423   %t1 = fdiv fast float %x, %z
424   %t2 = fdiv fast float %y, %z
425   %r = fsub fast float %t1, %t2
426   call void @use(float %t1)
427   call void @use(float %t2)
428   ret float %r
431 ; Constants are fine to combine if they are not denorms.
433 define float @fdiv_fadd_not_denorm(float %x) {
434 ; CHECK-LABEL: @fdiv_fadd_not_denorm(
435 ; CHECK-NEXT:    [[R:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]]
436 ; CHECK-NEXT:    ret float [[R]]
438   %t1 = fdiv fast float 0x3810000000000000, %x
439   %t2 = fdiv fast float 0x3800000000000000, %x
440   %r = fadd fast float %t1, %t2
441   ret float %r
444 ; Negative test - disabled if x+y is denormal.
446 define float @fdiv_fadd_denorm(float %x) {
447 ; CHECK-LABEL: @fdiv_fadd_denorm(
448 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float 0xB810000000000000, [[X:%.*]]
449 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]]
450 ; CHECK-NEXT:    [[R:%.*]] = fadd fast float [[T1]], [[T2]]
451 ; CHECK-NEXT:    ret float [[R]]
453   %t1 = fdiv fast float 0xB810000000000000, %x
454   %t2 = fdiv fast float 0x3800000000000000, %x
455   %r = fadd fast float %t1, %t2
456   ret float %r
459 ; Negative test - disabled if x-y is denormal.
461 define float @fdiv_fsub_denorm(float %x) {
462 ; CHECK-LABEL: @fdiv_fsub_denorm(
463 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float 0x3810000000000000, [[X:%.*]]
464 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]]
465 ; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
466 ; CHECK-NEXT:    ret float [[R]]
468   %t1 = fdiv fast float 0x3810000000000000, %x
469   %t2 = fdiv fast float 0x3800000000000000, %x
470   %r = fsub fast float %t1, %t2
471   ret float %r
474 define float @lerp_commute0(float %a, float %b, float %c) {
475 ; CHECK-LABEL: @lerp_commute0(
476 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast float [[B:%.*]], [[A:%.*]]
477 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast float [[TMP1]], [[C:%.*]]
478 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[TMP2]], [[A]]
479 ; CHECK-NEXT:    ret float [[ADD]]
481   %sub = fsub fast float 1.0, %c
482   %mul = fmul fast float %sub, %a
483   %bc = fmul fast float %c, %b
484   %add = fadd fast float %mul, %bc
485   ret float %add
488 define <2 x float> @lerp_commute1(<2 x float> %a, <2 x float> %b, <2 x float> %c) {
489 ; CHECK-LABEL: @lerp_commute1(
490 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <2 x float> [[B:%.*]], [[A:%.*]]
491 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast <2 x float> [[TMP1]], [[C:%.*]]
492 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast <2 x float> [[TMP2]], [[A]]
493 ; CHECK-NEXT:    ret <2 x float> [[ADD]]
495   %sub = fsub <2 x float> <float 1.0, float 1.0>, %c
496   %mul = fmul <2 x float> %sub, %a
497   %bc = fmul <2 x float> %c, %b
498   %add = fadd fast <2 x float> %bc, %mul
499   ret <2 x float> %add
502 define float @lerp_commute2(float %a, float %b, float %c) {
503 ; CHECK-LABEL: @lerp_commute2(
504 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[B:%.*]], [[A:%.*]]
505 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[C:%.*]]
506 ; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nsz float [[TMP2]], [[A]]
507 ; CHECK-NEXT:    ret float [[ADD]]
509   %sub = fsub float 1.0, %c
510   %mul = fmul float %sub, %a
511   %bc = fmul float %b, %c
512   %add = fadd reassoc nsz float %mul, %bc
513   ret float %add
516 define float @lerp_commute3(float %a, float %b, float %c) {
517 ; CHECK-LABEL: @lerp_commute3(
518 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc ninf nsz float [[B:%.*]], [[A:%.*]]
519 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc ninf nsz float [[TMP1]], [[C:%.*]]
520 ; CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc ninf nsz float [[TMP2]], [[A]]
521 ; CHECK-NEXT:    ret float [[ADD]]
523   %sub = fsub fast float 1.0, %c
524   %mul = fmul float %sub, %a
525   %bc = fmul float %b, %c
526   %add = fadd reassoc nsz ninf float %bc, %mul
527   ret float %add
530 define double @lerp_commute4(double %a, double %b, double %c) {
531 ; CHECK-LABEL: @lerp_commute4(
532 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast double [[B:%.*]], [[A:%.*]]
533 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast double [[TMP1]], [[C:%.*]]
534 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast double [[TMP2]], [[A]]
535 ; CHECK-NEXT:    ret double [[ADD]]
537   %sub = fsub fast double 1.0, %c
538   %mul = fmul fast double %a, %sub
539   %bc = fmul fast double %c, %b
540   %add = fadd fast double %mul, %bc
541   ret double %add
544 define double @lerp_commute5(double %a, double %b, double %c) {
545 ; CHECK-LABEL: @lerp_commute5(
546 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast double [[B:%.*]], [[A:%.*]]
547 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast double [[TMP1]], [[C:%.*]]
548 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast double [[TMP2]], [[A]]
549 ; CHECK-NEXT:    ret double [[ADD]]
551   %sub = fsub fast double 1.0, %c
552   %mul = fmul fast double %a, %sub
553   %bc = fmul fast double %c, %b
554   %add = fadd fast double %bc, %mul
555   ret double %add
558 define half @lerp_commute6(half %a, half %b, half %c) {
559 ; CHECK-LABEL: @lerp_commute6(
560 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast half [[B:%.*]], [[A:%.*]]
561 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast half [[TMP1]], [[C:%.*]]
562 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast half [[TMP2]], [[A]]
563 ; CHECK-NEXT:    ret half [[ADD]]
565   %sub = fsub fast half 1.0, %c
566   %mul = fmul fast half %a, %sub
567   %bc = fmul fast half %b, %c
568   %add = fadd fast half %mul, %bc
569   ret half %add
572 define half @lerp_commute7(half %a, half %b, half %c) {
573 ; CHECK-LABEL: @lerp_commute7(
574 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast half [[B:%.*]], [[A:%.*]]
575 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast half [[TMP1]], [[C:%.*]]
576 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast half [[TMP2]], [[A]]
577 ; CHECK-NEXT:    ret half [[ADD]]
579   %sub = fsub fast half 1.0, %c
580   %mul = fmul fast half %a, %sub
581   %bc = fmul fast half %b, %c
582   %add = fadd fast half %bc, %mul
583   ret half %add
586 define float @lerp_extra_use1(float %a, float %b, float %c) {
587 ; CHECK-LABEL: @lerp_extra_use1(
588 ; CHECK-NEXT:    [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]]
589 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUB]], [[A:%.*]]
590 ; CHECK-NEXT:    [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]]
591 ; CHECK-NEXT:    call void @use(float [[BC]])
592 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]]
593 ; CHECK-NEXT:    ret float [[ADD]]
595   %sub = fsub fast float 1.0, %c
596   %mul = fmul fast float %a, %sub
597   %bc = fmul fast float %b, %c
598   call void @use(float %bc)
599   %add = fadd fast float %bc, %mul
600   ret float %add
603 define float @lerp_extra_use2(float %a, float %b, float %c) {
604 ; CHECK-LABEL: @lerp_extra_use2(
605 ; CHECK-NEXT:    [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]]
606 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUB]], [[A:%.*]]
607 ; CHECK-NEXT:    call void @use(float [[MUL]])
608 ; CHECK-NEXT:    [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]]
609 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]]
610 ; CHECK-NEXT:    ret float [[ADD]]
612   %sub = fsub fast float 1.0, %c
613   %mul = fmul fast float %a, %sub
614   call void @use(float %mul)
615   %bc = fmul fast float %b, %c
616   %add = fadd fast float %bc, %mul
617   ret float %add
620 define float @lerp_extra_use3(float %a, float %b, float %c) {
621 ; CHECK-LABEL: @lerp_extra_use3(
622 ; CHECK-NEXT:    [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]]
623 ; CHECK-NEXT:    call void @use(float [[SUB]])
624 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[SUB]], [[A:%.*]]
625 ; CHECK-NEXT:    [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]]
626 ; CHECK-NEXT:    [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]]
627 ; CHECK-NEXT:    ret float [[ADD]]
629   %sub = fsub fast float 1.0, %c
630   call void @use(float %sub)
631   %mul = fmul fast float %a, %sub
632   %bc = fmul fast float %b, %c
633   %add = fadd fast float %bc, %mul
634   ret float %add