Revert r362472 as it is breaking PPC build bots
[llvm-core.git] / test / Transforms / InstCombine / fsub.ll
blobf4d971c7ff1747fba2b0ceaee77d0fc8add362f8
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; PR4374
6 define float @test1(float %x, float %y) {
7 ; CHECK-LABEL: @test1(
8 ; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
9 ; CHECK-NEXT:    [[T2:%.*]] = fsub float -0.000000e+00, [[T1]]
10 ; CHECK-NEXT:    ret float [[T2]]
12   %t1 = fsub float %x, %y
13   %t2 = fsub float -0.0, %t1
14   ret float %t2
17 define float @test1_unary(float %x, float %y) {
18 ; CHECK-LABEL: @test1_unary(
19 ; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
20 ; CHECK-NEXT:    [[T2:%.*]] = fneg float [[T1]]
21 ; CHECK-NEXT:    ret float [[T2]]
23   %t1 = fsub float %x, %y
24   %t2 = fneg float %t1
25   ret float %t2
28 ; Can't do anything with the test above because -0.0 - 0.0 = -0.0, but if we have nsz:
29 ; -(X - Y) --> Y - X
31 define float @neg_sub_nsz(float %x, float %y) {
32 ; CHECK-LABEL: @neg_sub_nsz(
33 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]
34 ; CHECK-NEXT:    ret float [[TMP1]]
36   %t1 = fsub float %x, %y
37   %t2 = fsub nsz float -0.0, %t1
38   ret float %t2
41 ; FIXME: This combine isn't working.
42 define float @unary_neg_sub_nsz(float %x, float %y) {
43 ; CHECK-LABEL: @unary_neg_sub_nsz(
44 ; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
45 ; CHECK-NEXT:    [[T2:%.*]] = fneg nsz float [[T1]]
46 ; CHECK-NEXT:    ret float [[T2]]
48   %t1 = fsub float %x, %y
49   %t2 = fneg nsz float %t1
50   ret float %t2
53 ; If the subtract has another use, we don't do the transform (even though it
54 ; doesn't increase the IR instruction count) because we assume that fneg is
55 ; easier to analyze and generally cheaper than generic fsub.
57 declare void @use(float)
58 declare void @use2(float, double)
60 define float @neg_sub_nsz_extra_use(float %x, float %y) {
61 ; CHECK-LABEL: @neg_sub_nsz_extra_use(
62 ; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
63 ; CHECK-NEXT:    [[T2:%.*]] = fsub nsz float -0.000000e+00, [[T1]]
64 ; CHECK-NEXT:    call void @use(float [[T1]])
65 ; CHECK-NEXT:    ret float [[T2]]
67   %t1 = fsub float %x, %y
68   %t2 = fsub nsz float -0.0, %t1
69   call void @use(float %t1)
70   ret float %t2
73 define float @unary_neg_sub_nsz_extra_use(float %x, float %y) {
74 ; CHECK-LABEL: @unary_neg_sub_nsz_extra_use(
75 ; CHECK-NEXT:    [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
76 ; CHECK-NEXT:    [[T2:%.*]] = fneg nsz float [[T1]]
77 ; CHECK-NEXT:    call void @use(float [[T1]])
78 ; CHECK-NEXT:    ret float [[T2]]
80   %t1 = fsub float %x, %y
81   %t2 = fneg nsz float %t1
82   call void @use(float %t1)
83   ret float %t2
86 ; With nsz: Z - (X - Y) --> Z + (Y - X)
88 define float @sub_sub_nsz(float %x, float %y, float %z) {
89 ; CHECK-LABEL: @sub_sub_nsz(
90 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]
91 ; CHECK-NEXT:    [[T2:%.*]] = fadd nsz float [[TMP1]], [[Z:%.*]]
92 ; CHECK-NEXT:    ret float [[T2]]
94   %t1 = fsub float %x, %y
95   %t2 = fsub nsz float %z, %t1
96   ret float %t2
99 ; With nsz and reassoc: Y - ((X * 5) + Y) --> X * -5
101 define float @sub_add_neg_x(float %x, float %y) {
102 ; CHECK-LABEL: @sub_add_neg_x(
103 ; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
104 ; CHECK-NEXT:    ret float [[R]]
106   %mul = fmul float %x, 5.000000e+00
107   %add = fadd float %mul, %y
108   %r = fsub nsz reassoc float %y, %add
109   ret float %r
112 ; Same as above: if 'Z' is not -0.0, swap fsub operands and convert to fadd.
114 define float @sub_sub_known_not_negzero(float %x, float %y) {
115 ; CHECK-LABEL: @sub_sub_known_not_negzero(
116 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
117 ; CHECK-NEXT:    [[T2:%.*]] = fadd float [[TMP1]], 4.200000e+01
118 ; CHECK-NEXT:    ret float [[T2]]
120   %t1 = fsub float %x, %y
121   %t2 = fsub float 42.0, %t1
122   ret float %t2
125 ; <rdar://problem/7530098>
127 define double @test2(double %x, double %y) {
128 ; CHECK-LABEL: @test2(
129 ; CHECK-NEXT:    [[T1:%.*]] = fadd double [[X:%.*]], [[Y:%.*]]
130 ; CHECK-NEXT:    [[T2:%.*]] = fsub double [[X]], [[T1]]
131 ; CHECK-NEXT:    ret double [[T2]]
133   %t1 = fadd double %x, %y
134   %t2 = fsub double %x, %t1
135   ret double %t2
138 ; X - C --> X + (-C)
140 define float @constant_op1(float %x, float %y) {
141 ; CHECK-LABEL: @constant_op1(
142 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[X:%.*]], -4.200000e+01
143 ; CHECK-NEXT:    ret float [[R]]
145   %r = fsub float %x, 42.0
146   ret float %r
149 define <2 x float> @constant_op1_vec(<2 x float> %x, <2 x float> %y) {
150 ; CHECK-LABEL: @constant_op1_vec(
151 ; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float 4.200000e+01>
152 ; CHECK-NEXT:    ret <2 x float> [[R]]
154   %r = fsub <2 x float> %x, <float 42.0, float -42.0>
155   ret <2 x float> %r
158 define <2 x float> @constant_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
159 ; CHECK-LABEL: @constant_op1_vec_undef(
160 ; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float undef, float 4.200000e+01>
161 ; CHECK-NEXT:    ret <2 x float> [[R]]
163   %r = fsub <2 x float> %x, <float undef, float -42.0>
164   ret <2 x float> %r
167 ; X - (-Y) --> X + Y
169 define float @neg_op1(float %x, float %y) {
170 ; CHECK-LABEL: @neg_op1(
171 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
172 ; CHECK-NEXT:    ret float [[R]]
174   %negy = fsub float -0.0, %y
175   %r = fsub float %x, %negy
176   ret float %r
179 define float @unary_neg_op1(float %x, float %y) {
180 ; CHECK-LABEL: @unary_neg_op1(
181 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
182 ; CHECK-NEXT:    ret float [[R]]
184   %negy = fneg float %y
185   %r = fsub float %x, %negy
186   ret float %r
189 define <2 x float> @neg_op1_vec(<2 x float> %x, <2 x float> %y) {
190 ; CHECK-LABEL: @neg_op1_vec(
191 ; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]
192 ; CHECK-NEXT:    ret <2 x float> [[R]]
194   %negy = fsub <2 x float> <float -0.0, float -0.0>, %y
195   %r = fsub <2 x float> %x, %negy
196   ret <2 x float> %r
199 define <2 x float> @unary_neg_op1_vec(<2 x float> %x, <2 x float> %y) {
200 ; CHECK-LABEL: @unary_neg_op1_vec(
201 ; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]
202 ; CHECK-NEXT:    ret <2 x float> [[R]]
204   %negy = fneg <2 x float> %y
205   %r = fsub <2 x float> %x, %negy
206   ret <2 x float> %r
209 define <2 x float> @neg_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
210 ; CHECK-LABEL: @neg_op1_vec_undef(
211 ; CHECK-NEXT:    [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]
212 ; CHECK-NEXT:    ret <2 x float> [[R]]
214   %negy = fsub <2 x float> <float -0.0, float undef>, %y
215   %r = fsub <2 x float> %x, %negy
216   ret <2 x float> %r
219 ; Similar to above - but look through fpext/fptrunc casts to find the fneg.
221 define double @neg_ext_op1(float %a, double %b) {
222 ; CHECK-LABEL: @neg_ext_op1(
223 ; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
224 ; CHECK-NEXT:    [[T3:%.*]] = fadd double [[TMP1]], [[B:%.*]]
225 ; CHECK-NEXT:    ret double [[T3]]
227   %t1 = fsub float -0.0, %a
228   %t2 = fpext float %t1 to double
229   %t3 = fsub double %b, %t2
230   ret double %t3
233 define double @unary_neg_ext_op1(float %a, double %b) {
234 ; CHECK-LABEL: @unary_neg_ext_op1(
235 ; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
236 ; CHECK-NEXT:    [[T3:%.*]] = fadd double [[TMP1]], [[B:%.*]]
237 ; CHECK-NEXT:    ret double [[T3]]
239   %t1 = fneg float %a
240   %t2 = fpext float %t1 to double
241   %t3 = fsub double %b, %t2
242   ret double %t3
245 ; Verify that vectors work too.
247 define <2 x float> @neg_trunc_op1(<2 x double> %a, <2 x float> %b) {
248 ; CHECK-LABEL: @neg_trunc_op1(
249 ; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[A:%.*]] to <2 x float>
250 ; CHECK-NEXT:    [[T3:%.*]] = fadd <2 x float> [[TMP1]], [[B:%.*]]
251 ; CHECK-NEXT:    ret <2 x float> [[T3]]
253   %t1 = fsub <2 x double> <double -0.0, double -0.0>, %a
254   %t2 = fptrunc <2 x double> %t1 to <2 x float>
255   %t3 = fsub <2 x float> %b, %t2
256   ret <2 x float> %t3
259 define <2 x float> @unary_neg_trunc_op1(<2 x double> %a, <2 x float> %b) {
260 ; CHECK-LABEL: @unary_neg_trunc_op1(
261 ; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[A:%.*]] to <2 x float>
262 ; CHECK-NEXT:    [[T3:%.*]] = fadd <2 x float> [[TMP1]], [[B:%.*]]
263 ; CHECK-NEXT:    ret <2 x float> [[T3]]
265   %t1 = fneg <2 x double> %a
266   %t2 = fptrunc <2 x double> %t1 to <2 x float>
267   %t3 = fsub <2 x float> %b, %t2
268   ret <2 x float> %t3
271 ; No FMF needed, but they should propagate to the fadd.
273 define double @neg_ext_op1_fast(float %a, double %b) {
274 ; CHECK-LABEL: @neg_ext_op1_fast(
275 ; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
276 ; CHECK-NEXT:    [[T3:%.*]] = fadd fast double [[TMP1]], [[B:%.*]]
277 ; CHECK-NEXT:    ret double [[T3]]
279   %t1 = fsub float -0.0, %a
280   %t2 = fpext float %t1 to double
281   %t3 = fsub fast double %b, %t2
282   ret double %t3
285 define double @unary_neg_ext_op1_fast(float %a, double %b) {
286 ; CHECK-LABEL: @unary_neg_ext_op1_fast(
287 ; CHECK-NEXT:    [[TMP1:%.*]] = fpext float [[A:%.*]] to double
288 ; CHECK-NEXT:    [[T3:%.*]] = fadd fast double [[TMP1]], [[B:%.*]]
289 ; CHECK-NEXT:    ret double [[T3]]
291   %t1 = fneg float %a
292   %t2 = fpext float %t1 to double
293   %t3 = fsub fast double %b, %t2
294   ret double %t3
297 ; Extra use should prevent the transform.
299 define float @neg_ext_op1_extra_use(half %a, float %b) {
300 ; CHECK-LABEL: @neg_ext_op1_extra_use(
301 ; CHECK-NEXT:    [[T1:%.*]] = fsub half 0xH8000, [[A:%.*]]
302 ; CHECK-NEXT:    [[T2:%.*]] = fpext half [[T1]] to float
303 ; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
304 ; CHECK-NEXT:    call void @use(float [[T2]])
305 ; CHECK-NEXT:    ret float [[T3]]
307   %t1 = fsub half -0.0, %a
308   %t2 = fpext half %t1 to float
309   %t3 = fsub float %b, %t2
310   call void @use(float %t2)
311   ret float %t3
314 define float @unary_neg_ext_op1_extra_use(half %a, float %b) {
315 ; CHECK-LABEL: @unary_neg_ext_op1_extra_use(
316 ; CHECK-NEXT:    [[T1:%.*]] = fneg half [[A:%.*]]
317 ; CHECK-NEXT:    [[T2:%.*]] = fpext half [[T1]] to float
318 ; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
319 ; CHECK-NEXT:    call void @use(float [[T2]])
320 ; CHECK-NEXT:    ret float [[T3]]
322   %t1 = fneg half %a
323   %t2 = fpext half %t1 to float
324   %t3 = fsub float %b, %t2
325   call void @use(float %t2)
326   ret float %t3
329 ; One-use fptrunc is always hoisted above fneg, so the corresponding
330 ; multi-use bug for fptrunc isn't visible with a fold starting from
331 ; the last fsub.
333 define float @neg_trunc_op1_extra_use(double %a, float %b) {
334 ; CHECK-LABEL: @neg_trunc_op1_extra_use(
335 ; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc double [[A:%.*]] to float
336 ; CHECK-NEXT:    [[T2:%.*]] = fsub float -0.000000e+00, [[TMP1]]
337 ; CHECK-NEXT:    [[T3:%.*]] = fadd float [[TMP1]], [[B:%.*]]
338 ; CHECK-NEXT:    call void @use(float [[T2]])
339 ; CHECK-NEXT:    ret float [[T3]]
341   %t1 = fsub double -0.0, %a
342   %t2 = fptrunc double %t1 to float
343   %t3 = fsub float %b, %t2
344   call void @use(float %t2)
345   ret float %t3
348 ; FIXME: This combine isn't working.
349 define float @unary_neg_trunc_op1_extra_use(double %a, float %b) {
350 ; CHECK-LABEL: @unary_neg_trunc_op1_extra_use(
351 ; CHECK-NEXT:    [[T1:%.*]] = fneg double [[A:%.*]]
352 ; CHECK-NEXT:    [[T2:%.*]] = fptrunc double [[T1]] to float
353 ; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
354 ; CHECK-NEXT:    call void @use(float [[T2]])
355 ; CHECK-NEXT:    ret float [[T3]]
357   %t1 = fneg double %a
358   %t2 = fptrunc double %t1 to float
359   %t3 = fsub float %b, %t2
360   call void @use(float %t2)
361   ret float %t3
364 ; Extra uses should prevent the transform.
366 define float @neg_trunc_op1_extra_uses(double %a, float %b) {
367 ; CHECK-LABEL: @neg_trunc_op1_extra_uses(
368 ; CHECK-NEXT:    [[T1:%.*]] = fsub double -0.000000e+00, [[A:%.*]]
369 ; CHECK-NEXT:    [[T2:%.*]] = fptrunc double [[T1]] to float
370 ; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
371 ; CHECK-NEXT:    call void @use2(float [[T2]], double [[T1]])
372 ; CHECK-NEXT:    ret float [[T3]]
374   %t1 = fsub double -0.0, %a
375   %t2 = fptrunc double %t1 to float
376   %t3 = fsub float %b, %t2
377   call void @use2(float %t2, double %t1)
378   ret float %t3
381 define float @unary_neg_trunc_op1_extra_uses(double %a, float %b) {
382 ; CHECK-LABEL: @unary_neg_trunc_op1_extra_uses(
383 ; CHECK-NEXT:    [[T1:%.*]] = fneg double [[A:%.*]]
384 ; CHECK-NEXT:    [[T2:%.*]] = fptrunc double [[T1]] to float
385 ; CHECK-NEXT:    [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]
386 ; CHECK-NEXT:    call void @use2(float [[T2]], double [[T1]])
387 ; CHECK-NEXT:    ret float [[T3]]
389   %t1 = fneg double %a
390   %t2 = fptrunc double %t1 to float
391   %t3 = fsub float %b, %t2
392   call void @use2(float %t2, double %t1)
393   ret float %t3
396 ; Don't negate a constant expression to form fadd and induce infinite looping:
397 ; https://bugs.llvm.org/show_bug.cgi?id=37605
399 @b = external global i16, align 1
401 define float @PR37605(float %conv) {
402 ; CHECK-LABEL: @PR37605(
403 ; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[CONV:%.*]], bitcast (i32 ptrtoint (i16* @b to i32) to float)
404 ; CHECK-NEXT:    ret float [[SUB]]
406   %sub = fsub float %conv, bitcast (i32 ptrtoint (i16* @b to i32) to float)
407   ret float %sub