1; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
2
3define float @fadd_zero_strict(float %x) {
4; CHECK-LABEL: fadd_zero_strict:
5; CHECK:       # %bb.0:
6; CHECK-NEXT:    xorps %xmm1, %xmm1
7; CHECK-NEXT:    addss %xmm1, %xmm0
8; CHECK-NEXT:    retq
9  %r = fadd float %x, 0.0
10  ret float %r
11}
12
13define float @fadd_negzero(float %x) {
14; CHECK-LABEL: fadd_negzero:
15; CHECK:       # %bb.0:
16; CHECK-NEXT:    retq
17  %r = fadd float %x, -0.0
18  ret float %r
19}
20
21define float @fadd_produce_zero(float %x) {
22; CHECK-LABEL: fadd_produce_zero:
23; CHECK:       # %bb.0:
24; CHECK-NEXT:    xorps %xmm0, %xmm0
25; CHECK-NEXT:    retq
26  %neg = fsub nsz float 0.0, %x
27  %r = fadd nnan float %neg, %x
28  ret float %r
29}
30
31define float @fadd_reassociate(float %x) {
32; CHECK-LABEL: fadd_reassociate:
33; CHECK:       # %bb.0:
34; CHECK-NEXT:    addss {{.*}}(%rip), %xmm0
35; CHECK-NEXT:    retq
36  %sum = fadd float %x, 8.0
37  %r = fadd reassoc nsz float %sum, 12.0
38  ret float %r
39}
40
41define float @fadd_negzero_nsz(float %x) {
42; CHECK-LABEL: fadd_negzero_nsz:
43; CHECK:       # %bb.0:
44; CHECK-NEXT:    retq
45  %r = fadd nsz float %x, -0.0
46  ret float %r
47}
48
49define float @fadd_zero_nsz(float %x) {
50; CHECK-LABEL: fadd_zero_nsz:
51; CHECK:       # %bb.0:
52; CHECK-NEXT:    retq
53  %r = fadd nsz float %x, 0.0
54  ret float %r
55}
56
57define float @fsub_zero(float %x) {
58; CHECK-LABEL: fsub_zero:
59; CHECK:       # %bb.0:
60; CHECK-NEXT:    retq
61  %r = fsub float %x, 0.0
62  ret float %r
63}
64
65define float @fsub_self(float %x) {
66; CHECK-LABEL: fsub_self:
67; CHECK:       # %bb.0:
68; CHECK-NEXT:    xorps %xmm0, %xmm0
69; CHECK-NEXT:    retq
70  %r = fsub nnan float %x, %x
71  ret float %r
72}
73
74define float @fsub_neg_x_y(float %x, float %y) {
75; CHECK-LABEL: fsub_neg_x_y:
76; CHECK:       # %bb.0:
77; CHECK-NEXT:    subss %xmm0, %xmm1
78; CHECK-NEXT:    movaps %xmm1, %xmm0
79; CHECK-NEXT:    retq
80  %neg = fsub nsz float 0.0, %x
81  %r = fadd nsz float %neg, %y
82  ret float %r
83}
84
85define float @fsub_neg_y(float %x, float %y) {
86; CHECK-LABEL: fsub_neg_y:
87; CHECK:       # %bb.0:
88; CHECK-NEXT:    mulss {{.*}}(%rip), %xmm0
89; CHECK-NEXT:    retq
90  %mul = fmul float %x, 5.0
91  %add = fadd float %mul, %y
92  %r = fsub nsz reassoc float %y, %add
93  ret float %r
94}
95
96define <4 x float> @fsub_neg_y_vector(<4 x float> %x, <4 x float> %y) {
97; CHECK-LABEL: fsub_neg_y_vector:
98; CHECK:       # %bb.0:
99; CHECK-NEXT:    mulps {{.*}}(%rip), %xmm0
100; CHECK-NEXT:    retq
101  %mul = fmul <4 x float> %x, <float 5.0, float 5.0, float 5.0, float 5.0>
102  %add = fadd <4 x float> %mul, %y
103  %r = fsub nsz reassoc <4 x float> %y, %add
104  ret <4 x float> %r
105}
106
107define <4 x float> @fsub_neg_y_vector_nonuniform(<4 x float> %x, <4 x float> %y) {
108; CHECK-LABEL: fsub_neg_y_vector_nonuniform:
109; CHECK:       # %bb.0:
110; CHECK-NEXT:    mulps {{.*}}(%rip), %xmm0
111; CHECK-NEXT:    retq
112  %mul = fmul <4 x float> %x, <float 5.0, float 6.0, float 7.0, float 8.0>
113  %add = fadd <4 x float> %mul, %y
114  %r = fsub nsz reassoc <4 x float> %y, %add
115  ret <4 x float> %r
116}
117
118define float @fsub_neg_y_commute(float %x, float %y) {
119; CHECK-LABEL: fsub_neg_y_commute:
120; CHECK:       # %bb.0:
121; CHECK-NEXT:    mulss {{.*}}(%rip), %xmm0
122; CHECK-NEXT:    retq
123  %mul = fmul float %x, 5.0
124  %add = fadd float %y, %mul
125  %r = fsub nsz reassoc float %y, %add
126  ret float %r
127}
128
129define <4 x float> @fsub_neg_y_commute_vector(<4 x float> %x, <4 x float> %y) {
130; CHECK-LABEL: fsub_neg_y_commute_vector:
131; CHECK:       # %bb.0:
132; CHECK-NEXT:    mulps {{.*}}(%rip), %xmm0
133; CHECK-NEXT:    retq
134  %mul = fmul <4 x float> %x, <float 5.0, float 5.0, float 5.0, float 5.0>
135  %add = fadd <4 x float> %y, %mul
136  %r = fsub nsz reassoc <4 x float> %y, %add
137  ret <4 x float> %r
138}
139
140; Y - (X + Y) --> -X
141
142define float @fsub_fadd_common_op_fneg(float %x, float %y) {
143; CHECK-LABEL: fsub_fadd_common_op_fneg:
144; CHECK:       # %bb.0:
145; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
146; CHECK-NEXT:    retq
147  %a = fadd float %x, %y
148  %r = fsub reassoc nsz float %y, %a
149  ret float %r
150}
151
152; Y - (X + Y) --> -X
153
154define <4 x float> @fsub_fadd_common_op_fneg_vec(<4 x float> %x, <4 x float> %y) {
155; CHECK-LABEL: fsub_fadd_common_op_fneg_vec:
156; CHECK:       # %bb.0:
157; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
158; CHECK-NEXT:    retq
159  %a = fadd <4 x float> %x, %y
160  %r = fsub nsz reassoc <4 x float> %y, %a
161  ret <4 x float> %r
162}
163
164; Y - (Y + X) --> -X
165; Commute operands of the 'add'.
166
167define float @fsub_fadd_common_op_fneg_commute(float %x, float %y) {
168; CHECK-LABEL: fsub_fadd_common_op_fneg_commute:
169; CHECK:       # %bb.0:
170; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
171; CHECK-NEXT:    retq
172  %a = fadd float %y, %x
173  %r = fsub reassoc nsz float %y, %a
174  ret float %r
175}
176
177; Y - (Y + X) --> -X
178
179define <4 x float> @fsub_fadd_common_op_fneg_commute_vec(<4 x float> %x, <4 x float> %y) {
180; CHECK-LABEL: fsub_fadd_common_op_fneg_commute_vec:
181; CHECK:       # %bb.0:
182; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
183; CHECK-NEXT:    retq
184  %a = fadd <4 x float> %y, %x
185  %r = fsub reassoc nsz <4 x float> %y, %a
186  ret <4 x float> %r
187}
188
189define float @fsub_negzero_strict(float %x) {
190; CHECK-LABEL: fsub_negzero_strict:
191; CHECK:       # %bb.0:
192; CHECK-NEXT:    xorps %xmm1, %xmm1
193; CHECK-NEXT:    addss %xmm1, %xmm0
194; CHECK-NEXT:    retq
195  %r = fsub float %x, -0.0
196  ret float %r
197}
198
199define float @fsub_negzero_nsz(float %x) {
200; CHECK-LABEL: fsub_negzero_nsz:
201; CHECK:       # %bb.0:
202; CHECK-NEXT:    retq
203  %r = fsub nsz float %x, -0.0
204  ret float %r
205}
206
207define <4 x float> @fsub_negzero_strict_vector(<4 x float> %x) {
208; CHECK-LABEL: fsub_negzero_strict_vector:
209; CHECK:       # %bb.0:
210; CHECK-NEXT:    xorps %xmm1, %xmm1
211; CHECK-NEXT:    addps %xmm1, %xmm0
212; CHECK-NEXT:    retq
213  %r = fsub <4 x float> %x, <float -0.0, float -0.0, float -0.0, float -0.0>
214  ret <4 x float> %r
215}
216
217define <4 x float> @fsub_negzero_nsz_vector(<4 x float> %x) {
218; CHECK-LABEL: fsub_negzero_nsz_vector:
219; CHECK:       # %bb.0:
220; CHECK-NEXT:    retq
221  %r = fsub nsz <4 x float> %x, <float -0.0, float -0.0, float -0.0, float -0.0>
222  ret <4 x float> %r
223}
224
225define float @fsub_zero_nsz_1(float %x) {
226; CHECK-LABEL: fsub_zero_nsz_1:
227; CHECK:       # %bb.0:
228; CHECK-NEXT:    retq
229  %r = fsub nsz float %x, 0.0
230  ret float %r
231}
232
233define float @fsub_zero_nsz_2(float %x) {
234; CHECK-LABEL: fsub_zero_nsz_2:
235; CHECK:       # %bb.0:
236; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
237; CHECK-NEXT:    retq
238  %r = fsub nsz float 0.0, %x
239  ret float %r
240}
241
242define float @fmul_zero(float %x) {
243; CHECK-LABEL: fmul_zero:
244; CHECK:       # %bb.0:
245; CHECK-NEXT:    xorps %xmm0, %xmm0
246; CHECK-NEXT:    retq
247  %r = fmul nnan nsz float %x, 0.0
248  ret float %r
249}
250
251define float @fmul_one(float %x) {
252; CHECK-LABEL: fmul_one:
253; CHECK:       # %bb.0:
254; CHECK-NEXT:    retq
255  %r = fmul float %x, 1.0
256  ret float %r
257}
258
259define float @fmul_x_const_const(float %x) {
260; CHECK-LABEL: fmul_x_const_const:
261; CHECK:       # %bb.0:
262; CHECK-NEXT:    mulss {{.*}}(%rip), %xmm0
263; CHECK-NEXT:    retq
264  %mul = fmul reassoc float %x, 9.0
265  %r = fmul reassoc float %mul, 4.0
266  ret float %r
267}
268