1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 declare void @use(float)
5 declare void @use_vec(<2 x float>)
9 define float @fneg_op0(float %x, float %y) {
10 ; CHECK-LABEL: @fneg_op0(
11 ; CHECK-NEXT: [[ADD:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
12 ; CHECK-NEXT: ret float [[ADD]]
14 %neg = fsub float -0.0, %x
15 %add = fadd float %neg, %y
21 define float @fneg_op1(float %x, float %y) {
22 ; CHECK-LABEL: @fneg_op1(
23 ; CHECK-NEXT: [[ADD:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
24 ; CHECK-NEXT: ret float [[ADD]]
26 %neg = fsub float -0.0, %y
27 %add = fadd float %x, %neg
31 ; Z + (-X / Y) --> Z - (X / Y)
33 define double @fdiv_fneg1(double %x, double %y, double %pz) {
34 ; CHECK-LABEL: @fdiv_fneg1(
35 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
36 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
37 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
38 ; CHECK-NEXT: ret double [[R]]
40 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
41 %neg = fsub double -0.000000e+00, %x
42 %div = fdiv double %neg, %y
43 %r = fadd double %z, %div
47 ; Z + (Y / -X) --> Z - (Y / X)
49 define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
50 ; CHECK-LABEL: @fdiv_fneg2(
51 ; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
52 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
53 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
54 ; CHECK-NEXT: ret <2 x double> [[R]]
56 %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
57 %neg = fsub <2 x double> <double -0.0, double -0.0>, %x
58 %div = fdiv <2 x double> %y, %neg
59 %r = fadd <2 x double> %z, %div
63 ; Z + (-X * Y) --> Z - (X * Y)
65 define double @fmul_fneg1(double %x, double %y, double %pz) {
66 ; CHECK-LABEL: @fmul_fneg1(
67 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
68 ; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
69 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
70 ; CHECK-NEXT: ret double [[R]]
72 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
73 %neg = fsub double -0.000000e+00, %x
74 %mul = fmul double %neg, %y
75 %r = fadd double %z, %mul
79 ; Z + (Y * -X) --> Z - (Y * X)
81 define double @fmul_fneg2(double %x, double %py, double %pz) {
82 ; CHECK-LABEL: @fmul_fneg2(
83 ; CHECK-NEXT: [[Y:%.*]] = frem double -4.200000e+01, [[PY:%.*]]
84 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
85 ; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[Y]], [[X:%.*]]
86 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
87 ; CHECK-NEXT: ret double [[R]]
89 %y = frem double -42.0, %py ; thwart complexity-based canonicalization
90 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
91 %neg = fsub double -0.000000e+00, %x
92 %mul = fmul double %y, %neg
93 %r = fadd double %z, %mul
97 ; (-X / Y) + Z --> Z - (X / Y)
99 define double @fdiv_fneg1_commute(double %x, double %y, double %pz) {
100 ; CHECK-LABEL: @fdiv_fneg1_commute(
101 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
102 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
103 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
104 ; CHECK-NEXT: ret double [[R]]
106 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
107 %neg = fsub double -0.000000e+00, %x
108 %div = fdiv double %neg, %y
109 %r = fadd double %div, %z
113 ; (Y / -X) + Z --> Z - (Y / X)
115 define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
116 ; CHECK-LABEL: @fdiv_fneg2_commute(
117 ; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
118 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
119 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
120 ; CHECK-NEXT: ret <2 x double> [[R]]
122 %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
123 %neg = fsub <2 x double> <double -0.0, double -0.0>, %x
124 %div = fdiv <2 x double> %y, %neg
125 %r = fadd <2 x double> %div, %z
129 ; (-X * Y) + Z --> Z - (X * Y)
131 define double @fmul_fneg1_commute(double %x, double %y, double %pz) {
132 ; CHECK-LABEL: @fmul_fneg1_commute(
133 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
134 ; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
135 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
136 ; CHECK-NEXT: ret double [[R]]
138 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
139 %neg = fsub double -0.000000e+00, %x
140 %mul = fmul double %neg, %y
141 %r = fadd double %mul, %z
145 ; (Y * -X) + Z --> Z - (Y * X)
147 define double @fmul_fneg2_commute(double %x, double %py, double %pz) {
148 ; CHECK-LABEL: @fmul_fneg2_commute(
149 ; CHECK-NEXT: [[Y:%.*]] = frem double 4.100000e+01, [[PY:%.*]]
150 ; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
151 ; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[Y]], [[X:%.*]]
152 ; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
153 ; CHECK-NEXT: ret double [[R]]
155 %y = frem double 41.0, %py ; thwart complexity-based canonicalization
156 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization
157 %neg = fsub double -0.000000e+00, %x
158 %mul = fmul double %y, %neg
159 %r = fadd double %mul, %z
163 ; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction
165 define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) {
166 ; CHECK-LABEL: @fdiv_fneg1_extra_use(
167 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
168 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
169 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
170 ; CHECK-NEXT: call void @use(float [[DIV]])
171 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
172 ; CHECK-NEXT: ret float [[R]]
174 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
175 %neg = fsub float -0.000000e+00, %x
176 %div = fdiv float %neg, %y
177 call void @use(float %div)
178 %r = fadd float %z, %div
182 ; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction
184 define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) {
185 ; CHECK-LABEL: @fdiv_fneg2_extra_use(
186 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
187 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
188 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
189 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y]], [[NEG]]
190 ; CHECK-NEXT: call void @use(float [[DIV]])
191 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
192 ; CHECK-NEXT: ret float [[R]]
194 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
195 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
196 %neg = fsub float -0.000000e+00, %x
197 %div = fdiv float %y, %neg
198 call void @use(float %div)
199 %r = fadd float %z, %div
203 ; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction
205 define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) {
206 ; CHECK-LABEL: @fmul_fneg1_extra_use(
207 ; CHECK-NEXT: [[Z:%.*]] = frem <2 x float> <float 4.200000e+01, float -1.000000e+00>, [[PZ:%.*]]
208 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
209 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
210 ; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
211 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]]
212 ; CHECK-NEXT: ret <2 x float> [[R]]
214 %z = frem <2 x float> <float 42.0, float -1.0>, %pz ; thwart complexity-based canonicalization
215 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
216 %mul = fmul <2 x float> %neg, %y
217 call void @use_vec(<2 x float> %mul)
218 %r = fadd <2 x float> %z, %mul
222 ; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction
224 define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) {
225 ; CHECK-LABEL: @fmul_fneg2_extra_use(
226 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
227 ; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
228 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
229 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
230 ; CHECK-NEXT: call void @use(float [[MUL]])
231 ; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[MUL]]
232 ; CHECK-NEXT: ret float [[R]]
234 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
235 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization
236 %neg = fsub float -0.000000e+00, %x
237 %mul = fmul float %y, %neg
238 call void @use(float %mul)
239 %r = fadd float %z, %mul
243 ; (-X / Y) + Z --> Z - (X / Y)
245 define float @fdiv_fneg1_extra_use2(float %x, float %y, float %z) {
246 ; CHECK-LABEL: @fdiv_fneg1_extra_use2(
247 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
248 ; CHECK-NEXT: call void @use(float [[NEG]])
249 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]
250 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
251 ; CHECK-NEXT: ret float [[R]]
253 %neg = fsub float -0.000000e+00, %x
254 call void @use(float %neg)
255 %div = fdiv float %neg, %y
256 %r = fadd float %div, %z
260 ; (Y / -X) + Z --> Z - (Y / X)
262 define float @fdiv_fneg2_extra_use2(float %x, float %y, float %z) {
263 ; CHECK-LABEL: @fdiv_fneg2_extra_use2(
264 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
265 ; CHECK-NEXT: call void @use(float [[NEG]])
266 ; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]
267 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
268 ; CHECK-NEXT: ret float [[R]]
270 %neg = fsub float -0.000000e+00, %x
271 call void @use(float %neg)
272 %div = fdiv float %y, %neg
273 %r = fadd float %div, %z
277 ; (-X * Y) + Z --> Z - (X * Y)
279 define <2 x float> @fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
280 ; CHECK-LABEL: @fmul_fneg1_extra_use2(
281 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
282 ; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])
283 ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]
284 ; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[TMP1]]
285 ; CHECK-NEXT: ret <2 x float> [[R]]
287 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
288 call void @use_vec(<2 x float> %neg)
289 %mul = fmul <2 x float> %neg, %y
290 %r = fadd <2 x float> %mul, %z
294 ; (Y * -X) + Z --> Z - (Y * X)
296 define float @fmul_fneg2_extra_use2(float %x, float %py, float %z) {
297 ; CHECK-LABEL: @fmul_fneg2_extra_use2(
298 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
299 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
300 ; CHECK-NEXT: call void @use(float [[NEG]])
301 ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[Y]], [[X]]
302 ; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
303 ; CHECK-NEXT: ret float [[R]]
305 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
306 %neg = fsub float -0.000000e+00, %x
307 call void @use(float %neg)
308 %mul = fmul float %y, %neg
309 %r = fadd float %mul, %z
313 ; (-X / Y) + Z --> Z - (X / Y)
315 define float @fdiv_fneg1_extra_use3(float %x, float %y, float %z) {
316 ; CHECK-LABEL: @fdiv_fneg1_extra_use3(
317 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
318 ; CHECK-NEXT: call void @use(float [[NEG]])
319 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
320 ; CHECK-NEXT: call void @use(float [[DIV]])
321 ; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
322 ; CHECK-NEXT: ret float [[R]]
324 %neg = fsub float -0.000000e+00, %x
325 call void @use(float %neg)
326 %div = fdiv float %neg, %y
327 call void @use(float %div)
328 %r = fadd float %div, %z
332 ; (Y / -X) + Z --> Z - (Y / X)
334 define float @fdiv_fneg2_extra_use3(float %x, float %y, float %z) {
335 ; CHECK-LABEL: @fdiv_fneg2_extra_use3(
336 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
337 ; CHECK-NEXT: call void @use(float [[NEG]])
338 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
339 ; CHECK-NEXT: call void @use(float [[DIV]])
340 ; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
341 ; CHECK-NEXT: ret float [[R]]
343 %neg = fsub float -0.000000e+00, %x
344 call void @use(float %neg)
345 %div = fdiv float %y, %neg
346 call void @use(float %div)
347 %r = fadd float %div, %z
351 ; (-X * Y) + Z --> Z - (X * Y)
353 define <2 x float> @fmul_fneg1_extra_use3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
354 ; CHECK-LABEL: @fmul_fneg1_extra_use3(
355 ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
356 ; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])
357 ; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[NEG]], [[Y:%.*]]
358 ; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
359 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[MUL]], [[Z:%.*]]
360 ; CHECK-NEXT: ret <2 x float> [[R]]
362 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
363 call void @use_vec(<2 x float> %neg)
364 %mul = fmul <2 x float> %neg, %y
365 call void @use_vec(<2 x float> %mul)
366 %r = fadd <2 x float> %mul, %z
370 ; (Y * -X) + Z --> Z - (Y * X)
372 define float @fmul_fneg2_extra_use3(float %x, float %py, float %z) {
373 ; CHECK-LABEL: @fmul_fneg2_extra_use3(
374 ; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
375 ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
376 ; CHECK-NEXT: call void @use(float [[NEG]])
377 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
378 ; CHECK-NEXT: call void @use(float [[MUL]])
379 ; CHECK-NEXT: [[R:%.*]] = fadd float [[MUL]], [[Z:%.*]]
380 ; CHECK-NEXT: ret float [[R]]
382 %y = frem float -42.0, %py ; thwart complexity-based canonicalization
383 %neg = fsub float -0.000000e+00, %x
384 call void @use(float %neg)
385 %mul = fmul float %y, %neg
386 call void @use(float %mul)
387 %r = fadd float %mul, %z