1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -enable-no-signed-zeros-fp-math \
3 ; RUN: -enable-unsafe-fp-math < %s | FileCheck -check-prefix=CHECK-FAST %s
4 ; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -enable-no-signed-zeros-fp-math \
5 ; RUN: -enable-unsafe-fp-math -mattr=-vsx < %s | FileCheck -check-prefix=CHECK-FAST-NOVSX %s
6 ; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
8 define dso_local double @fma_combine1(double %a, double %b, double %c) {
9 ; CHECK-FAST-LABEL: fma_combine1:
10 ; CHECK-FAST: # %bb.0: # %entry
11 ; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2
12 ; CHECK-FAST-NEXT: blr
14 ; CHECK-FAST-NOVSX-LABEL: fma_combine1:
15 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
16 ; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 3, 2, 1
17 ; CHECK-FAST-NOVSX-NEXT: blr
19 ; CHECK-LABEL: fma_combine1:
20 ; CHECK: # %bb.0: # %entry
21 ; CHECK-NEXT: xsnegdp 0, 3
22 ; CHECK-NEXT: xsmuldp 0, 0, 2
23 ; CHECK-NEXT: xssubdp 1, 0, 1
26 %fneg1 = fneg double %c
27 %mul = fmul double %fneg1, %b
28 %add = fsub double %mul, %a
32 define dso_local double @fma_combine2(double %a, double %b, double %c) {
33 ; CHECK-FAST-LABEL: fma_combine2:
34 ; CHECK-FAST: # %bb.0: # %entry
35 ; CHECK-FAST-NEXT: xsnmaddadp 1, 2, 3
36 ; CHECK-FAST-NEXT: blr
38 ; CHECK-FAST-NOVSX-LABEL: fma_combine2:
39 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
40 ; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 2, 3, 1
41 ; CHECK-FAST-NOVSX-NEXT: blr
43 ; CHECK-LABEL: fma_combine2:
44 ; CHECK: # %bb.0: # %entry
45 ; CHECK-NEXT: xsnegdp 0, 3
46 ; CHECK-NEXT: xsmuldp 0, 2, 0
47 ; CHECK-NEXT: xssubdp 1, 0, 1
50 %fneg1 = fneg double %c
51 %mul = fmul double %b, %fneg1
52 %add = fsub double %mul, %a
56 @v = common dso_local local_unnamed_addr global double 0.000000e+00, align 8
57 @z = common dso_local local_unnamed_addr global double 0.000000e+00, align 8
58 define dso_local double @fma_combine_two_uses(double %a, double %b, double %c) {
59 ; CHECK-FAST-LABEL: fma_combine_two_uses:
60 ; CHECK-FAST: # %bb.0: # %entry
61 ; CHECK-FAST-NEXT: xsnegdp 0, 1
62 ; CHECK-FAST-NEXT: addis 3, 2, v@toc@ha
63 ; CHECK-FAST-NEXT: addis 4, 2, z@toc@ha
64 ; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2
65 ; CHECK-FAST-NEXT: xsnegdp 2, 3
66 ; CHECK-FAST-NEXT: stfd 0, v@toc@l(3)
67 ; CHECK-FAST-NEXT: stfd 2, z@toc@l(4)
68 ; CHECK-FAST-NEXT: blr
70 ; CHECK-FAST-NOVSX-LABEL: fma_combine_two_uses:
71 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
72 ; CHECK-FAST-NOVSX-NEXT: fnmadd 0, 3, 2, 1
73 ; CHECK-FAST-NOVSX-NEXT: fneg 2, 1
74 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha
75 ; CHECK-FAST-NOVSX-NEXT: addis 4, 2, z@toc@ha
76 ; CHECK-FAST-NOVSX-NEXT: fneg 3, 3
77 ; CHECK-FAST-NOVSX-NEXT: fmr 1, 0
78 ; CHECK-FAST-NOVSX-NEXT: stfd 2, v@toc@l(3)
79 ; CHECK-FAST-NOVSX-NEXT: stfd 3, z@toc@l(4)
80 ; CHECK-FAST-NOVSX-NEXT: blr
82 ; CHECK-LABEL: fma_combine_two_uses:
83 ; CHECK: # %bb.0: # %entry
84 ; CHECK-NEXT: xsnegdp 3, 3
85 ; CHECK-NEXT: addis 3, 2, v@toc@ha
86 ; CHECK-NEXT: addis 4, 2, z@toc@ha
87 ; CHECK-NEXT: xsmuldp 0, 3, 2
88 ; CHECK-NEXT: stfd 3, z@toc@l(4)
89 ; CHECK-NEXT: xsnegdp 2, 1
90 ; CHECK-NEXT: xssubdp 0, 0, 1
91 ; CHECK-NEXT: stfd 2, v@toc@l(3)
92 ; CHECK-NEXT: fmr 1, 0
95 %fneg = fneg double %a
96 store double %fneg, double* @v, align 8
97 %fneg1 = fneg double %c
98 store double %fneg1, double* @z, align 8
99 %mul = fmul double %fneg1, %b
100 %add = fsub double %mul, %a
104 define dso_local double @fma_combine_one_use(double %a, double %b, double %c) {
105 ; CHECK-FAST-LABEL: fma_combine_one_use:
106 ; CHECK-FAST: # %bb.0: # %entry
107 ; CHECK-FAST-NEXT: xsnegdp 0, 1
108 ; CHECK-FAST-NEXT: addis 3, 2, v@toc@ha
109 ; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2
110 ; CHECK-FAST-NEXT: stfd 0, v@toc@l(3)
111 ; CHECK-FAST-NEXT: blr
113 ; CHECK-FAST-NOVSX-LABEL: fma_combine_one_use:
114 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
115 ; CHECK-FAST-NOVSX-NEXT: fnmadd 0, 3, 2, 1
116 ; CHECK-FAST-NOVSX-NEXT: fneg 2, 1
117 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha
118 ; CHECK-FAST-NOVSX-NEXT: fmr 1, 0
119 ; CHECK-FAST-NOVSX-NEXT: stfd 2, v@toc@l(3)
120 ; CHECK-FAST-NOVSX-NEXT: blr
122 ; CHECK-LABEL: fma_combine_one_use:
123 ; CHECK: # %bb.0: # %entry
124 ; CHECK-NEXT: xsnegdp 0, 3
125 ; CHECK-NEXT: addis 3, 2, v@toc@ha
126 ; CHECK-NEXT: xsmuldp 0, 0, 2
127 ; CHECK-NEXT: xsnegdp 2, 1
128 ; CHECK-NEXT: xssubdp 0, 0, 1
129 ; CHECK-NEXT: stfd 2, v@toc@l(3)
130 ; CHECK-NEXT: fmr 1, 0
133 %fneg = fneg double %a
134 store double %fneg, double* @v, align 8
135 %fneg1 = fneg double %c
136 %mul = fmul double %fneg1, %b
137 %add = fsub double %mul, %a
141 define dso_local float @fma_combine_no_ice() {
142 ; CHECK-FAST-LABEL: fma_combine_no_ice:
143 ; CHECK-FAST: # %bb.0:
144 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_0@toc@ha
145 ; CHECK-FAST-NEXT: lfs 0, .LCPI4_0@toc@l(3)
146 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_1@toc@ha
147 ; CHECK-FAST-NEXT: lfs 2, 0(3)
148 ; CHECK-FAST-NEXT: lfs 3, .LCPI4_1@toc@l(3)
149 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_2@toc@ha
150 ; CHECK-FAST-NEXT: lfs 1, .LCPI4_2@toc@l(3)
151 ; CHECK-FAST-NEXT: xsmaddasp 3, 2, 0
152 ; CHECK-FAST-NEXT: xsmaddasp 1, 2, 3
153 ; CHECK-FAST-NEXT: xsnmsubasp 1, 3, 2
154 ; CHECK-FAST-NEXT: blr
156 ; CHECK-FAST-NOVSX-LABEL: fma_combine_no_ice:
157 ; CHECK-FAST-NOVSX: # %bb.0:
158 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_0@toc@ha
159 ; CHECK-FAST-NOVSX-NEXT: lfs 0, .LCPI4_0@toc@l(3)
160 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_1@toc@ha
161 ; CHECK-FAST-NOVSX-NEXT: lfs 1, 0(3)
162 ; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_1@toc@l(3)
163 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_2@toc@ha
164 ; CHECK-FAST-NOVSX-NEXT: fmadds 0, 1, 2, 0
165 ; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_2@toc@l(3)
166 ; CHECK-FAST-NOVSX-NEXT: fmadds 2, 1, 0, 2
167 ; CHECK-FAST-NOVSX-NEXT: fnmsubs 1, 0, 1, 2
168 ; CHECK-FAST-NOVSX-NEXT: blr
170 ; CHECK-LABEL: fma_combine_no_ice:
172 ; CHECK-NEXT: addis 3, 2, .LCPI4_0@toc@ha
173 ; CHECK-NEXT: lfs 0, .LCPI4_0@toc@l(3)
174 ; CHECK-NEXT: addis 3, 2, .LCPI4_1@toc@ha
175 ; CHECK-NEXT: lfs 2, 0(3)
176 ; CHECK-NEXT: lfs 3, .LCPI4_1@toc@l(3)
177 ; CHECK-NEXT: addis 3, 2, .LCPI4_2@toc@ha
178 ; CHECK-NEXT: lfs 1, .LCPI4_2@toc@l(3)
179 ; CHECK-NEXT: fmr 4, 3
180 ; CHECK-NEXT: xsmaddasp 3, 2, 0
181 ; CHECK-NEXT: xsnmaddasp 4, 2, 0
182 ; CHECK-NEXT: xsmaddasp 1, 2, 3
183 ; CHECK-NEXT: xsmaddasp 1, 4, 2
185 %tmp = load float, float* undef, align 4
186 %tmp2 = load float, float* undef, align 4
187 %tmp3 = fmul contract reassoc float %tmp, 0x3FE372D780000000
188 %tmp4 = fadd contract reassoc float %tmp3, 1.000000e+00
189 %tmp5 = fmul contract reassoc float %tmp2, %tmp4
190 %tmp6 = load float, float* undef, align 4
191 %tmp7 = load float, float* undef, align 4
192 %tmp8 = fmul contract reassoc float %tmp7, 0x3FE372D780000000
193 %tmp9 = fsub contract reassoc nsz float -1.000000e+00, %tmp8
194 %tmp10 = fmul contract reassoc float %tmp9, %tmp6
195 %tmp11 = fadd contract reassoc float %tmp5, 5.000000e-01
196 %tmp12 = fadd contract reassoc float %tmp11, %tmp10
200 ; This would crash while trying getNegatedExpression().
201 define dso_local double @getNegatedExpression_crash(double %x, double %y) {
202 ; CHECK-FAST-LABEL: getNegatedExpression_crash:
203 ; CHECK-FAST: # %bb.0:
204 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI5_1@toc@ha
205 ; CHECK-FAST-NEXT: lfs 3, .LCPI5_1@toc@l(3)
206 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI5_0@toc@ha
207 ; CHECK-FAST-NEXT: lfs 4, .LCPI5_0@toc@l(3)
208 ; CHECK-FAST-NEXT: xssubdp 0, 1, 3
209 ; CHECK-FAST-NEXT: xsmaddadp 3, 1, 4
210 ; CHECK-FAST-NEXT: xsmaddadp 0, 3, 2
211 ; CHECK-FAST-NEXT: fmr 1, 0
212 ; CHECK-FAST-NEXT: blr
214 ; CHECK-FAST-NOVSX-LABEL: getNegatedExpression_crash:
215 ; CHECK-FAST-NOVSX: # %bb.0:
216 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI5_0@toc@ha
217 ; CHECK-FAST-NOVSX-NEXT: addis 4, 2, .LCPI5_1@toc@ha
218 ; CHECK-FAST-NOVSX-NEXT: lfs 0, .LCPI5_0@toc@l(3)
219 ; CHECK-FAST-NOVSX-NEXT: lfs 3, .LCPI5_1@toc@l(4)
220 ; CHECK-FAST-NOVSX-NEXT: fmadd 3, 1, 3, 0
221 ; CHECK-FAST-NOVSX-NEXT: fsub 0, 1, 0
222 ; CHECK-FAST-NOVSX-NEXT: fmadd 1, 3, 2, 0
223 ; CHECK-FAST-NOVSX-NEXT: blr
225 ; CHECK-LABEL: getNegatedExpression_crash:
227 ; CHECK-NEXT: addis 3, 2, .LCPI5_1@toc@ha
228 ; CHECK-NEXT: lfs 3, .LCPI5_1@toc@l(3)
229 ; CHECK-NEXT: addis 3, 2, .LCPI5_0@toc@ha
230 ; CHECK-NEXT: lfs 4, .LCPI5_0@toc@l(3)
231 ; CHECK-NEXT: xssubdp 0, 1, 3
232 ; CHECK-NEXT: xsmaddadp 3, 1, 4
233 ; CHECK-NEXT: xsmaddadp 0, 3, 2
234 ; CHECK-NEXT: fmr 1, 0
236 %neg = fneg reassoc double %x
237 %fma = call reassoc nsz double @llvm.fma.f64(double %neg, double 42.0, double -1.0)
238 %add = fadd reassoc nsz double %x, 1.0
239 %fma1 = call reassoc nsz double @llvm.fma.f64(double %fma, double %y, double %add)
243 define dso_local double @fma_flag_propagation(double %a) {
244 ; CHECK-FAST-LABEL: fma_flag_propagation:
245 ; CHECK-FAST: # %bb.0: # %entry
246 ; CHECK-FAST-NEXT: xxlxor 1, 1, 1
247 ; CHECK-FAST-NEXT: blr
249 ; CHECK-FAST-NOVSX-LABEL: fma_flag_propagation:
250 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
251 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI6_0@toc@ha
252 ; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI6_0@toc@l(3)
253 ; CHECK-FAST-NOVSX-NEXT: blr
255 ; CHECK-LABEL: fma_flag_propagation:
256 ; CHECK: # %bb.0: # %entry
257 ; CHECK-NEXT: xxlxor 1, 1, 1
261 %1 = call reassoc nnan double @llvm.fma.f64(double %0, double 1.0, double %a)
265 define dso_local double @neg_fma_flag_propagation(double %a) {
266 ; CHECK-FAST-LABEL: neg_fma_flag_propagation:
267 ; CHECK-FAST: # %bb.0: # %entry
268 ; CHECK-FAST-NEXT: xxlxor 1, 1, 1
269 ; CHECK-FAST-NEXT: blr
271 ; CHECK-FAST-NOVSX-LABEL: neg_fma_flag_propagation:
272 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
273 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI7_0@toc@ha
274 ; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI7_0@toc@l(3)
275 ; CHECK-FAST-NOVSX-NEXT: blr
277 ; CHECK-LABEL: neg_fma_flag_propagation:
278 ; CHECK: # %bb.0: # %entry
279 ; CHECK-NEXT: xxlxor 1, 1, 1
282 %0 = call reassoc nnan double @llvm.fma.f64(double %a, double -1.0, double %a)
286 define <2 x double> @vec_neg_fma_flag_propagation(<2 x double> %a) {
287 ; CHECK-FAST-LABEL: vec_neg_fma_flag_propagation:
288 ; CHECK-FAST: # %bb.0: # %entry
289 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI8_0@toc@ha
290 ; CHECK-FAST-NEXT: addi 3, 3, .LCPI8_0@toc@l
291 ; CHECK-FAST-NEXT: lxvd2x 0, 0, 3
292 ; CHECK-FAST-NEXT: xxswapd 0, 0
293 ; CHECK-FAST-NEXT: xvmaddadp 34, 34, 0
294 ; CHECK-FAST-NEXT: blr
296 ; CHECK-FAST-NOVSX-LABEL: vec_neg_fma_flag_propagation:
297 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
298 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI8_0@toc@ha
299 ; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI8_0@toc@l(3)
300 ; CHECK-FAST-NOVSX-NEXT: fmr 2, 1
301 ; CHECK-FAST-NOVSX-NEXT: blr
303 ; CHECK-LABEL: vec_neg_fma_flag_propagation:
304 ; CHECK: # %bb.0: # %entry
305 ; CHECK-NEXT: addis 3, 2, .LCPI8_0@toc@ha
306 ; CHECK-NEXT: addi 3, 3, .LCPI8_0@toc@l
307 ; CHECK-NEXT: lxvd2x 0, 0, 3
308 ; CHECK-NEXT: xxswapd 0, 0
309 ; CHECK-NEXT: xvmaddadp 34, 34, 0
312 %0 = call reassoc nnan <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> <double -1.0, double -1.0>, <2 x double> %a)
316 define dso_local double @fma_combine_const(double %a, double %b) {
317 ; CHECK-FAST-LABEL: fma_combine_const:
318 ; CHECK-FAST: # %bb.0: # %entry
319 ; CHECK-FAST-NEXT: addis 3, 2, .LCPI9_0@toc@ha
320 ; CHECK-FAST-NEXT: lfd 0, .LCPI9_0@toc@l(3)
321 ; CHECK-FAST-NEXT: xsmaddadp 2, 1, 0
322 ; CHECK-FAST-NEXT: fmr 1, 2
323 ; CHECK-FAST-NEXT: blr
325 ; CHECK-FAST-NOVSX-LABEL: fma_combine_const:
326 ; CHECK-FAST-NOVSX: # %bb.0: # %entry
327 ; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI9_0@toc@ha
328 ; CHECK-FAST-NOVSX-NEXT: lfd 0, .LCPI9_0@toc@l(3)
329 ; CHECK-FAST-NOVSX-NEXT: fmadd 1, 1, 0, 2
330 ; CHECK-FAST-NOVSX-NEXT: blr
332 ; CHECK-LABEL: fma_combine_const:
333 ; CHECK: # %bb.0: # %entry
334 ; CHECK-NEXT: addis 3, 2, .LCPI9_0@toc@ha
335 ; CHECK-NEXT: lfd 0, .LCPI9_0@toc@l(3)
336 ; CHECK-NEXT: addis 3, 2, .LCPI9_1@toc@ha
337 ; CHECK-NEXT: lfd 3, .LCPI9_1@toc@l(3)
338 ; CHECK-NEXT: xsmuldp 0, 1, 0
339 ; CHECK-NEXT: fmr 1, 2
340 ; CHECK-NEXT: xsmaddadp 1, 0, 3
343 %0 = fmul double %a, 1.1
344 %1 = call contract double @llvm.fma.f64(double %0, double 2.1, double %b)
348 declare double @llvm.fma.f64(double, double, double) nounwind readnone
349 declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone