xref: /llvm-project/llvm/test/CodeGen/PowerPC/fma-combine.ll (revision 53c37f300dd1b450671f2aee4cc649c380adb5ad)
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
7
8define 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
13;
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
18;
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
24; CHECK-NEXT:    blr
25entry:
26  %fneg1 = fneg double %c
27  %mul = fmul double %fneg1, %b
28  %add = fsub double %mul, %a
29  ret double %add
30}
31
32define 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
37;
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
42;
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
48; CHECK-NEXT:    blr
49entry:
50  %fneg1 = fneg double %c
51  %mul = fmul double %b, %fneg1
52  %add = fsub double %mul, %a
53  ret double %add
54}
55
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
58define 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:    xsnmaddadp 1, 3, 2
64; CHECK-FAST-NEXT:    stfd 0, v@toc@l(3)
65; CHECK-FAST-NEXT:    xsnegdp 0, 3
66; CHECK-FAST-NEXT:    addis 3, 2, z@toc@ha
67; CHECK-FAST-NEXT:    stfd 0, z@toc@l(3)
68; CHECK-FAST-NEXT:    blr
69;
70; CHECK-FAST-NOVSX-LABEL: fma_combine_two_uses:
71; CHECK-FAST-NOVSX:       # %bb.0: # %entry
72; CHECK-FAST-NOVSX-NEXT:    fneg 0, 1
73; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, v@toc@ha
74; CHECK-FAST-NOVSX-NEXT:    fnmadd 1, 3, 2, 1
75; CHECK-FAST-NOVSX-NEXT:    stfd 0, v@toc@l(3)
76; CHECK-FAST-NOVSX-NEXT:    fneg 0, 3
77; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, z@toc@ha
78; CHECK-FAST-NOVSX-NEXT:    stfd 0, z@toc@l(3)
79; CHECK-FAST-NOVSX-NEXT:    blr
80;
81; CHECK-LABEL: fma_combine_two_uses:
82; CHECK:       # %bb.0: # %entry
83; CHECK-NEXT:    xsnegdp 0, 1
84; CHECK-NEXT:    addis 3, 2, v@toc@ha
85; CHECK-NEXT:    stfd 0, v@toc@l(3)
86; CHECK-NEXT:    xsnegdp 0, 3
87; CHECK-NEXT:    addis 3, 2, z@toc@ha
88; CHECK-NEXT:    stfd 0, z@toc@l(3)
89; CHECK-NEXT:    xsmuldp 0, 0, 2
90; CHECK-NEXT:    xssubdp 1, 0, 1
91; CHECK-NEXT:    blr
92entry:
93  %fneg = fneg double %a
94  store double %fneg, ptr @v, align 8
95  %fneg1 = fneg double %c
96  store double %fneg1, ptr @z, align 8
97  %mul = fmul double %fneg1, %b
98  %add = fsub double %mul, %a
99  ret double %add
100}
101
102define dso_local double @fma_combine_one_use(double %a, double %b, double %c) {
103; CHECK-FAST-LABEL: fma_combine_one_use:
104; CHECK-FAST:       # %bb.0: # %entry
105; CHECK-FAST-NEXT:    xsnegdp 0, 1
106; CHECK-FAST-NEXT:    xsnmaddadp 1, 3, 2
107; CHECK-FAST-NEXT:    addis 3, 2, v@toc@ha
108; CHECK-FAST-NEXT:    stfd 0, v@toc@l(3)
109; CHECK-FAST-NEXT:    blr
110;
111; CHECK-FAST-NOVSX-LABEL: fma_combine_one_use:
112; CHECK-FAST-NOVSX:       # %bb.0: # %entry
113; CHECK-FAST-NOVSX-NEXT:    fneg 0, 1
114; CHECK-FAST-NOVSX-NEXT:    fnmadd 1, 3, 2, 1
115; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, v@toc@ha
116; CHECK-FAST-NOVSX-NEXT:    stfd 0, v@toc@l(3)
117; CHECK-FAST-NOVSX-NEXT:    blr
118;
119; CHECK-LABEL: fma_combine_one_use:
120; CHECK:       # %bb.0: # %entry
121; CHECK-NEXT:    xsnegdp 0, 1
122; CHECK-NEXT:    addis 3, 2, v@toc@ha
123; CHECK-NEXT:    stfd 0, v@toc@l(3)
124; CHECK-NEXT:    xsnegdp 0, 3
125; CHECK-NEXT:    xsmuldp 0, 0, 2
126; CHECK-NEXT:    xssubdp 1, 0, 1
127; CHECK-NEXT:    blr
128entry:
129  %fneg = fneg double %a
130  store double %fneg, ptr @v, align 8
131  %fneg1 = fneg double %c
132  %mul = fmul double %fneg1, %b
133  %add = fsub double %mul, %a
134  ret double %add
135}
136
137define dso_local float @fma_combine_no_ice() {
138; CHECK-FAST-LABEL: fma_combine_no_ice:
139; CHECK-FAST:       # %bb.0:
140; CHECK-FAST-NEXT:    vspltisw 2, 1
141; CHECK-FAST-NEXT:    addis 3, 2, .LCPI4_0@toc@ha
142; CHECK-FAST-NEXT:    xvcvsxwdp 3, 34
143; CHECK-FAST-NEXT:    lfs 0, .LCPI4_0@toc@l(3)
144; CHECK-FAST-NEXT:    lfs 2, 0(3)
145; CHECK-FAST-NEXT:    addis 3, 2, .LCPI4_1@toc@ha
146; CHECK-FAST-NEXT:    lfs 1, .LCPI4_1@toc@l(3)
147; CHECK-FAST-NEXT:    xsmaddasp 3, 2, 0
148; CHECK-FAST-NEXT:    xsmaddasp 1, 2, 3
149; CHECK-FAST-NEXT:    xsnmsubasp 1, 3, 2
150; CHECK-FAST-NEXT:    blr
151;
152; CHECK-FAST-NOVSX-LABEL: fma_combine_no_ice:
153; CHECK-FAST-NOVSX:       # %bb.0:
154; CHECK-FAST-NOVSX-NEXT:    lfs 0, 0(3)
155; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI4_0@toc@ha
156; CHECK-FAST-NOVSX-NEXT:    lfs 1, .LCPI4_0@toc@l(3)
157; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI4_1@toc@ha
158; CHECK-FAST-NOVSX-NEXT:    lfs 2, .LCPI4_1@toc@l(3)
159; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI4_2@toc@ha
160; CHECK-FAST-NOVSX-NEXT:    fmadds 1, 0, 2, 1
161; CHECK-FAST-NOVSX-NEXT:    lfs 2, .LCPI4_2@toc@l(3)
162; CHECK-FAST-NOVSX-NEXT:    fmadds 2, 0, 1, 2
163; CHECK-FAST-NOVSX-NEXT:    fnmsubs 1, 1, 0, 2
164; CHECK-FAST-NOVSX-NEXT:    blr
165;
166; CHECK-LABEL: fma_combine_no_ice:
167; CHECK:       # %bb.0:
168; CHECK-NEXT:    vspltisw 2, 1
169; CHECK-NEXT:    addis 3, 2, .LCPI4_0@toc@ha
170; CHECK-NEXT:    xvcvsxwdp 3, 34
171; CHECK-NEXT:    lfs 0, .LCPI4_0@toc@l(3)
172; CHECK-NEXT:    lfs 2, 0(3)
173; CHECK-NEXT:    addis 3, 2, .LCPI4_1@toc@ha
174; CHECK-NEXT:    lfs 1, .LCPI4_1@toc@l(3)
175; CHECK-NEXT:    fmr 4, 3
176; CHECK-NEXT:    xsmaddasp 3, 2, 0
177; CHECK-NEXT:    xsnmaddasp 4, 2, 0
178; CHECK-NEXT:    xsmaddasp 1, 2, 3
179; CHECK-NEXT:    xsmaddasp 1, 4, 2
180; CHECK-NEXT:    blr
181  %tmp = load float, ptr undef, align 4
182  %tmp2 = load float, ptr undef, align 4
183  %tmp3 = fmul contract reassoc float %tmp, 0x3FE372D780000000
184  %tmp4 = fadd contract reassoc float %tmp3, 1.000000e+00
185  %tmp5 = fmul contract reassoc float %tmp2, %tmp4
186  %tmp6 = load float, ptr undef, align 4
187  %tmp7 = load float, ptr undef, align 4
188  %tmp8 = fmul contract reassoc float %tmp7, 0x3FE372D780000000
189  %tmp9 = fsub contract reassoc nsz float -1.000000e+00, %tmp8
190  %tmp10 = fmul contract reassoc float %tmp9, %tmp6
191  %tmp11 = fadd contract reassoc float %tmp5, 5.000000e-01
192  %tmp12 = fadd contract reassoc float %tmp11, %tmp10
193  ret float %tmp12
194}
195
196; This would crash while trying getNegatedExpression().
197define dso_local double @getNegatedExpression_crash(double %x, double %y) {
198; CHECK-FAST-LABEL: getNegatedExpression_crash:
199; CHECK-FAST:       # %bb.0:
200; CHECK-FAST-NEXT:    vspltisw 2, -1
201; CHECK-FAST-NEXT:    addis 3, 2, .LCPI5_0@toc@ha
202; CHECK-FAST-NEXT:    xvcvsxwdp 4, 34
203; CHECK-FAST-NEXT:    lfs 3, .LCPI5_0@toc@l(3)
204; CHECK-FAST-NEXT:    xssubdp 0, 1, 4
205; CHECK-FAST-NEXT:    xsmaddadp 4, 1, 3
206; CHECK-FAST-NEXT:    xsmaddadp 0, 4, 2
207; CHECK-FAST-NEXT:    fmr 1, 0
208; CHECK-FAST-NEXT:    blr
209;
210; CHECK-FAST-NOVSX-LABEL: getNegatedExpression_crash:
211; CHECK-FAST-NOVSX:       # %bb.0:
212; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI5_0@toc@ha
213; CHECK-FAST-NOVSX-NEXT:    lfs 0, .LCPI5_0@toc@l(3)
214; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI5_1@toc@ha
215; CHECK-FAST-NOVSX-NEXT:    lfs 3, .LCPI5_1@toc@l(3)
216; CHECK-FAST-NOVSX-NEXT:    fmadd 3, 1, 3, 0
217; CHECK-FAST-NOVSX-NEXT:    fsub 0, 1, 0
218; CHECK-FAST-NOVSX-NEXT:    fmadd 1, 3, 2, 0
219; CHECK-FAST-NOVSX-NEXT:    blr
220;
221; CHECK-LABEL: getNegatedExpression_crash:
222; CHECK:       # %bb.0:
223; CHECK-NEXT:    vspltisw 2, -1
224; CHECK-NEXT:    addis 3, 2, .LCPI5_0@toc@ha
225; CHECK-NEXT:    xvcvsxwdp 4, 34
226; CHECK-NEXT:    lfs 3, .LCPI5_0@toc@l(3)
227; CHECK-NEXT:    xssubdp 0, 1, 4
228; CHECK-NEXT:    xsmaddadp 4, 1, 3
229; CHECK-NEXT:    xsmaddadp 0, 4, 2
230; CHECK-NEXT:    fmr 1, 0
231; CHECK-NEXT:    blr
232  %neg = fneg reassoc double %x
233  %fma = call reassoc nsz double @llvm.fma.f64(double %neg, double 42.0, double -1.0)
234  %add = fadd reassoc nsz double %x, 1.0
235  %fma1 = call reassoc nsz double @llvm.fma.f64(double %fma, double %y, double %add)
236  ret double %fma1
237}
238
239define dso_local double @fma_flag_propagation(double %a) {
240; CHECK-FAST-LABEL: fma_flag_propagation:
241; CHECK-FAST:       # %bb.0: # %entry
242; CHECK-FAST-NEXT:    xxlxor 1, 1, 1
243; CHECK-FAST-NEXT:    blr
244;
245; CHECK-FAST-NOVSX-LABEL: fma_flag_propagation:
246; CHECK-FAST-NOVSX:       # %bb.0: # %entry
247; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI6_0@toc@ha
248; CHECK-FAST-NOVSX-NEXT:    lfs 1, .LCPI6_0@toc@l(3)
249; CHECK-FAST-NOVSX-NEXT:    blr
250;
251; CHECK-LABEL: fma_flag_propagation:
252; CHECK:       # %bb.0: # %entry
253; CHECK-NEXT:    xxlxor 1, 1, 1
254; CHECK-NEXT:    blr
255entry:
256  %0 = fneg double %a
257  %1 = call reassoc nnan double @llvm.fma.f64(double %0, double 1.0, double %a)
258  ret double %1
259}
260
261define dso_local double @neg_fma_flag_propagation(double %a) {
262; CHECK-FAST-LABEL: neg_fma_flag_propagation:
263; CHECK-FAST:       # %bb.0: # %entry
264; CHECK-FAST-NEXT:    xxlxor 1, 1, 1
265; CHECK-FAST-NEXT:    blr
266;
267; CHECK-FAST-NOVSX-LABEL: neg_fma_flag_propagation:
268; CHECK-FAST-NOVSX:       # %bb.0: # %entry
269; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI7_0@toc@ha
270; CHECK-FAST-NOVSX-NEXT:    lfs 1, .LCPI7_0@toc@l(3)
271; CHECK-FAST-NOVSX-NEXT:    blr
272;
273; CHECK-LABEL: neg_fma_flag_propagation:
274; CHECK:       # %bb.0: # %entry
275; CHECK-NEXT:    xxlxor 1, 1, 1
276; CHECK-NEXT:    blr
277entry:
278  %0 = call reassoc nnan double @llvm.fma.f64(double %a, double -1.0, double %a)
279  ret double %0
280}
281
282define <2 x double> @vec_neg_fma_flag_propagation(<2 x double> %a) {
283; CHECK-FAST-LABEL: vec_neg_fma_flag_propagation:
284; CHECK-FAST:       # %bb.0: # %entry
285; CHECK-FAST-NEXT:    addis 3, 2, .LCPI8_0@toc@ha
286; CHECK-FAST-NEXT:    addi 3, 3, .LCPI8_0@toc@l
287; CHECK-FAST-NEXT:    lxvd2x 0, 0, 3
288; CHECK-FAST-NEXT:    xvmaddadp 34, 34, 0
289; CHECK-FAST-NEXT:    blr
290;
291; CHECK-FAST-NOVSX-LABEL: vec_neg_fma_flag_propagation:
292; CHECK-FAST-NOVSX:       # %bb.0: # %entry
293; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI8_0@toc@ha
294; CHECK-FAST-NOVSX-NEXT:    lfs 1, .LCPI8_0@toc@l(3)
295; CHECK-FAST-NOVSX-NEXT:    fmr 2, 1
296; CHECK-FAST-NOVSX-NEXT:    blr
297;
298; CHECK-LABEL: vec_neg_fma_flag_propagation:
299; CHECK:       # %bb.0: # %entry
300; CHECK-NEXT:    addis 3, 2, .LCPI8_0@toc@ha
301; CHECK-NEXT:    addi 3, 3, .LCPI8_0@toc@l
302; CHECK-NEXT:    lxvd2x 0, 0, 3
303; CHECK-NEXT:    xvmaddadp 34, 34, 0
304; CHECK-NEXT:    blr
305entry:
306  %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)
307  ret <2 x double> %0
308}
309
310define dso_local double @fma_combine_const(double %a, double %b) {
311; CHECK-FAST-LABEL: fma_combine_const:
312; CHECK-FAST:       # %bb.0: # %entry
313; CHECK-FAST-NEXT:    addis 3, 2, .LCPI9_0@toc@ha
314; CHECK-FAST-NEXT:    lfd 0, .LCPI9_0@toc@l(3)
315; CHECK-FAST-NEXT:    xsmaddadp 2, 1, 0
316; CHECK-FAST-NEXT:    fmr 1, 2
317; CHECK-FAST-NEXT:    blr
318;
319; CHECK-FAST-NOVSX-LABEL: fma_combine_const:
320; CHECK-FAST-NOVSX:       # %bb.0: # %entry
321; CHECK-FAST-NOVSX-NEXT:    addis 3, 2, .LCPI9_0@toc@ha
322; CHECK-FAST-NOVSX-NEXT:    lfd 0, .LCPI9_0@toc@l(3)
323; CHECK-FAST-NOVSX-NEXT:    fmadd 1, 1, 0, 2
324; CHECK-FAST-NOVSX-NEXT:    blr
325;
326; CHECK-LABEL: fma_combine_const:
327; CHECK:       # %bb.0: # %entry
328; CHECK-NEXT:    addis 3, 2, .LCPI9_0@toc@ha
329; CHECK-NEXT:    lfd 0, .LCPI9_0@toc@l(3)
330; CHECK-NEXT:    addis 3, 2, .LCPI9_1@toc@ha
331; CHECK-NEXT:    xsmuldp 0, 1, 0
332; CHECK-NEXT:    lfd 1, .LCPI9_1@toc@l(3)
333; CHECK-NEXT:    xsmaddadp 2, 0, 1
334; CHECK-NEXT:    fmr 1, 2
335; CHECK-NEXT:    blr
336entry:
337  %0 = fmul double %a, 1.1
338  %1 = call contract double @llvm.fma.f64(double %0, double 2.1, double %b)
339  ret double %1
340}
341
342declare double @llvm.fma.f64(double, double, double) nounwind readnone
343declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone
344