1; RUN: llc -verify-machineinstrs -O3 -mcpu=pwr7 < %s | FileCheck  %s -check-prefix=CHECK -check-prefix=CHECK-PWR
2; RUN: llc -verify-machineinstrs -O3 -mcpu=a2q < %s | FileCheck  %s -check-prefix=CHECK -check-prefix=CHECK-QPX
3; RUN: llc -verify-machineinstrs -O3 -mcpu=pwr9 < %s | FileCheck  %s -check-prefix=FIXPOINT
4target datalayout = "E-m:e-i64:64-n32:64"
5target triple = "powerpc64-unknown-linux-gnu"
6
7; Verify that the first two adds are independent regardless of how the inputs are
8; commuted. The destination registers are used as source registers for the third add.
9
10define float @reassociate_adds1(float %x0, float %x1, float %x2, float %x3) {
11; CHECK-LABEL: reassociate_adds1:
12; CHECK:       # %bb.0:
13; CHECK:       fadds [[REG0:[0-9]+]], 1, 2
14; CHECK:       fadds [[REG1:[0-9]+]], 3, 4
15; CHECK:       fadds 1, [[REG0]], [[REG1]]
16; CHECK-NEXT:  blr
17
18  %t0 = fadd reassoc nsz float %x0, %x1
19  %t1 = fadd reassoc nsz float %t0, %x2
20  %t2 = fadd reassoc nsz float %t1, %x3
21  ret float %t2
22}
23
24define float @reassociate_adds2(float %x0, float %x1, float %x2, float %x3) {
25; CHECK-LABEL: reassociate_adds2:
26; CHECK:       # %bb.0:
27; CHECK:       fadds [[REG0:[0-9]+]], 1, 2
28; CHECK:       fadds [[REG1:[0-9]+]], 3, 4
29; CHECK:       fadds 1, [[REG0]], [[REG1]]
30; CHECK-NEXT:  blr
31
32  %t0 = fadd reassoc nsz float %x0, %x1
33  %t1 = fadd reassoc nsz float %x2, %t0
34  %t2 = fadd reassoc nsz float %t1, %x3
35  ret float %t2
36}
37
38define float @reassociate_adds3(float %x0, float %x1, float %x2, float %x3) {
39; CHECK-LABEL: reassociate_adds3:
40; CHECK:       # %bb.0:
41; CHECK:       fadds [[REG0:[0-9]+]], 1, 2
42; CHECK:       fadds [[REG1:[0-9]+]], 3, 4
43; CHECK:       fadds 1, [[REG0]], [[REG1]]
44; CHECK-NEXT:  blr
45
46  %t0 = fadd reassoc nsz float %x0, %x1
47  %t1 = fadd reassoc nsz float %t0, %x2
48  %t2 = fadd reassoc nsz float %x3, %t1
49  ret float %t2
50}
51
52define float @reassociate_adds4(float %x0, float %x1, float %x2, float %x3) {
53; CHECK-LABEL: reassociate_adds4:
54; CHECK:       # %bb.0:
55; CHECK:       fadds [[REG0:[0-9]+]], 1, 2
56; CHECK:       fadds [[REG1:[0-9]+]], 3, 4
57; CHECK:       fadds 1, [[REG0]], [[REG1]]
58; CHECK-NEXT:  blr
59
60  %t0 = fadd reassoc nsz float %x0, %x1
61  %t1 = fadd reassoc nsz float %x2, %t0
62  %t2 = fadd reassoc nsz float %x3, %t1
63  ret float %t2
64}
65
66; Verify that we reassociate some of these ops. The optimal balanced tree of adds is not
67; produced because that would cost more compile time.
68
69define float @reassociate_adds5(float %x0, float %x1, float %x2, float %x3, float %x4, float %x5, float %x6, float %x7) {
70; CHECK-LABEL: reassociate_adds5:
71; CHECK:       # %bb.0:
72; CHECK-DAG:   fadds [[REG12:[0-9]+]], 5, 6
73; CHECK-DAG:   fadds [[REG0:[0-9]+]], 1, 2
74; CHECK-DAG:   fadds [[REG11:[0-9]+]], 3, 4
75; CHECK-DAG:   fadds [[REG13:[0-9]+]], [[REG12]], 7
76; CHECK-DAG:   fadds [[REG1:[0-9]+]], [[REG0]], [[REG11]]
77; CHECK-DAG:   fadds [[REG2:[0-9]+]], [[REG1]], [[REG13]]
78; CHECK:       fadds 1, [[REG2]], 8
79; CHECK-NEXT:    blr
80
81  %t0 = fadd reassoc nsz float %x0, %x1
82  %t1 = fadd reassoc nsz float %t0, %x2
83  %t2 = fadd reassoc nsz float %t1, %x3
84  %t3 = fadd reassoc nsz float %t2, %x4
85  %t4 = fadd reassoc nsz float %t3, %x5
86  %t5 = fadd reassoc nsz float %t4, %x6
87  %t6 = fadd reassoc nsz float %t5, %x7
88  ret float %t6
89}
90
91; Verify that we reassociate vector instructions too.
92
93define <4 x float> @vector_reassociate_adds1(<4 x float> %x0, <4 x float> %x1, <4 x float> %x2, <4 x float> %x3) {
94; CHECK-LABEL: vector_reassociate_adds1:
95; CHECK:       # %bb.0:
96; CHECK-QPX:       qvfadds [[REG0:[0-9]+]], 1, 2
97; CHECK-QPX:       qvfadds [[REG1:[0-9]+]], 3, 4
98; CHECK-QPX:       qvfadds 1, [[REG0]], [[REG1]]
99; CHECK-PWR:       xvaddsp [[REG0:[0-9]+]], 34, 35
100; CHECK-PWR:       xvaddsp [[REG1:[0-9]+]], 36, 37
101; CHECK-PWR:       xvaddsp 34, [[REG0]], [[REG1]]
102; CHECK-NEXT:  blr
103
104  %t0 = fadd reassoc nsz <4 x float> %x0, %x1
105  %t1 = fadd reassoc nsz <4 x float> %t0, %x2
106  %t2 = fadd reassoc nsz <4 x float> %t1, %x3
107  ret <4 x float> %t2
108}
109
110define <4 x float> @vector_reassociate_adds2(<4 x float> %x0, <4 x float> %x1, <4 x float> %x2, <4 x float> %x3) {
111; CHECK-LABEL: vector_reassociate_adds2:
112; CHECK:       # %bb.0:
113; CHECK-QPX:       qvfadds [[REG0:[0-9]+]], 1, 2
114; CHECK-QPX:       qvfadds [[REG1:[0-9]+]], 3, 4
115; CHECK-QPX:       qvfadds 1, [[REG0]], [[REG1]]
116; CHECK-PWR:       xvaddsp [[REG0:[0-9]+]], 34, 35
117; CHECK-PWR:       xvaddsp [[REG1:[0-9]+]], 36, 37
118; CHECK-PWR:       xvaddsp 34, [[REG0]], [[REG1]]
119; CHECK-NEXT:  blr
120
121  %t0 = fadd reassoc nsz <4 x float> %x0, %x1
122  %t1 = fadd reassoc nsz <4 x float> %x2, %t0
123  %t2 = fadd reassoc nsz <4 x float> %t1, %x3
124  ret <4 x float> %t2
125}
126
127define <4 x float> @vector_reassociate_adds3(<4 x float> %x0, <4 x float> %x1, <4 x float> %x2, <4 x float> %x3) {
128; CHECK-LABEL: vector_reassociate_adds3:
129; CHECK:       # %bb.0:
130; CHECK-QPX:       qvfadds [[REG0:[0-9]+]], 1, 2
131; CHECK-QPX:       qvfadds [[REG1:[0-9]+]], 3, 4
132; CHECK-QPX:       qvfadds 1, [[REG0]], [[REG1]]
133; CHECK-PWR:       xvaddsp [[REG0:[0-9]+]], 34, 35
134; CHECK-PWR:       xvaddsp [[REG1:[0-9]+]], 36, 37
135; CHECK-PWR:       xvaddsp 34, [[REG0]], [[REG1]]
136; CHECK-NEXT:  blr
137
138  %t0 = fadd reassoc nsz <4 x float> %x0, %x1
139  %t1 = fadd reassoc nsz <4 x float> %t0, %x2
140  %t2 = fadd reassoc nsz <4 x float> %x3, %t1
141  ret <4 x float> %t2
142}
143
144define <4 x float> @vector_reassociate_adds4(<4 x float> %x0, <4 x float> %x1, <4 x float> %x2, <4 x float> %x3) {
145; CHECK-LABEL: vector_reassociate_adds4:
146; CHECK:       # %bb.0:
147; CHECK-QPX:       qvfadds [[REG0:[0-9]+]], 1, 2
148; CHECK-QPX:       qvfadds [[REG1:[0-9]+]], 3, 4
149; CHECK-QPX:       qvfadds 1, [[REG0]], [[REG1]]
150; CHECK-PWR:       xvaddsp [[REG0:[0-9]+]], 34, 35
151; CHECK-PWR:       xvaddsp [[REG1:[0-9]+]], 36, 37
152; CHECK-PWR:       xvaddsp 34, [[REG0]], [[REG1]]
153; CHECK-NEXT:  blr
154
155  %t0 = fadd reassoc nsz <4 x float> %x0, %x1
156  %t1 = fadd reassoc nsz <4 x float> %x2, %t0
157  %t2 = fadd reassoc nsz <4 x float> %x3, %t1
158  ret <4 x float> %t2
159}
160
161define float @reassociate_adds6(float %x0, float %x1, float %x2, float %x3) {
162  %t0 = fdiv float %x0, %x1
163  %t1 = fadd float %x2, %t0
164  %t2 = fadd float %x3, %t1
165  ret float %t2
166}
167
168define float @reassociate_muls1(float %x0, float %x1, float %x2, float %x3) {
169  %t0 = fdiv float %x0, %x1
170  %t1 = fmul float %x2, %t0
171  %t2 = fmul float %x3, %t1
172  ret float %t2
173}
174
175define double @reassociate_adds_double(double %x0, double %x1, double %x2, double %x3) {
176  %t0 = fdiv double %x0, %x1
177  %t1 = fadd double %x2, %t0
178  %t2 = fadd double %x3, %t1
179  ret double %t2
180}
181
182define double @reassociate_muls_double(double %x0, double %x1, double %x2, double %x3) {
183  %t0 = fdiv double %x0, %x1
184  %t1 = fmul double %x2, %t0
185  %t2 = fmul double %x3, %t1
186  ret double %t2
187}
188
189define i32 @reassociate_mullw(i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
190; FIXPOINT-LABEL: reassociate_mullw:
191; FIXPOINT:       # %bb.0:
192; FIXPOINT:       mullw [[REG0:[0-9]+]], 3, 4
193; FIXPOINT:       mullw [[REG1:[0-9]+]], 5, 6
194; FIXPOINT:       mullw 3, [[REG0]], [[REG1]]
195; FIXPOINT-NEXT:  blr
196
197  %t0 = mul i32 %x0, %x1
198  %t1 = mul i32 %t0, %x2
199  %t2 = mul i32 %t1, %x3
200  ret i32 %t2
201}
202
203define i64 @reassociate_mulld(i64 %x0, i64 %x1, i64 %x2, i64 %x3) {
204; FIXPOINT-LABEL: reassociate_mulld:
205; FIXPOINT:       # %bb.0:
206; FIXPOINT:       mulld [[REG0:[0-9]+]], 3, 4
207; FIXPOINT:       mulld [[REG1:[0-9]+]], 5, 6
208; FIXPOINT:       mulld 3, [[REG0]], [[REG1]]
209; FIXPOINT-NEXT:  blr
210
211  %t0 = mul i64 %x0, %x1
212  %t1 = mul i64 %t0, %x2
213  %t2 = mul i64 %t1, %x3
214  ret i64 %t2
215}
216
217define double @reassociate_mamaa_double(double %0, double %1, double %2, double %3, double %4, double %5) {
218; CHECK-LABEL: reassociate_mamaa_double:
219; CHECK:       # %bb.0:
220; CHECK-QPX-DAG:   fmadd [[REG0:[0-9]+]], 4, 3, 2
221; CHECK-QPX-DAG:   fmadd [[REG1:[0-9]+]], 6, 5, 1
222; CHECK-QPX:       fadd 1, [[REG0]], [[REG1]]
223; CHECK-PWR-DAG:   xsmaddadp 1, 6, 5
224; CHECK-PWR-DAG:   xsmaddadp 2, 4, 3
225; CHECK-PWR:       xsadddp 1, 2, 1
226; CHECK-NEXT:  blr
227  %7 = fmul reassoc nsz double %3, %2
228  %8 = fmul reassoc nsz double %5, %4
229  %9 = fadd reassoc nsz double %1, %0
230  %10 = fadd reassoc nsz double %9, %7
231  %11 = fadd reassoc nsz double %10, %8
232  ret double %11
233}
234
235define float @reassociate_mamaa_float(float %0, float %1, float %2, float %3, float %4, float %5) {
236; CHECK-LABEL: reassociate_mamaa_float:
237; CHECK:       # %bb.0:
238; CHECK-DAG:   fmadds [[REG0:[0-9]+]], 4, 3, 2
239; CHECK-DAG:   fmadds [[REG1:[0-9]+]], 6, 5, 1
240; CHECK:       fadds 1, [[REG0]], [[REG1]]
241; CHECK-NEXT:  blr
242  %7 = fmul reassoc nsz float %3, %2
243  %8 = fmul reassoc nsz float %5, %4
244  %9 = fadd reassoc nsz float %1, %0
245  %10 = fadd reassoc nsz float %9, %7
246  %11 = fadd reassoc nsz float %10, %8
247  ret float %11
248}
249
250define <4 x float> @reassociate_mamaa_vec(<4 x float> %0, <4 x float> %1, <4 x float> %2, <4 x float> %3, <4 x float> %4, <4 x float> %5) {
251; CHECK-LABEL: reassociate_mamaa_vec:
252; CHECK:       # %bb.0:
253; CHECK-QPX-DAG:   qvfmadds [[REG0:[0-9]+]], 4, 3, 2
254; CHECK-QPX-DAG:   qvfmadds [[REG1:[0-9]+]], 6, 5, 1
255; CHECK-QPX:       qvfadds 1, [[REG0]], [[REG1]]
256; CHECK-PWR-DAG:   xvmaddasp [[REG0:[0-9]+]], 39, 38
257; CHECK-PWR-DAG:   xvmaddasp [[REG1:[0-9]+]], 37, 36
258; CHECK-PWR:       xvaddsp 34, [[REG1]], [[REG0]]
259; CHECK-NEXT:  blr
260  %7 = fmul reassoc nsz <4 x float> %3, %2
261  %8 = fmul reassoc nsz <4 x float> %5, %4
262  %9 = fadd reassoc nsz <4 x float> %1, %0
263  %10 = fadd reassoc nsz <4 x float> %9, %7
264  %11 = fadd reassoc nsz <4 x float> %10, %8
265  ret <4 x float> %11
266}
267
268define double @reassociate_mamama_double(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8) {
269; CHECK-LABEL: reassociate_mamama_double:
270; CHECK:       # %bb.0:
271; CHECK-QPX:       fmadd [[REG0:[0-9]+]], 2, 1, 7
272; CHECK-QPX-DAG:   fmul [[REG1:[0-9]+]], 4, 3
273; CHECK-QPX-DAG:   fmadd [[REG2:[0-9]+]], 6, 5, [[REG0]]
274; CHECK-QPX-DAG:   fmadd [[REG3:[0-9]+]], 9, 8, [[REG1]]
275; CHECK-QPX:       fadd 1, [[REG2]], [[REG3]]
276; CHECK-PWR:       xsmaddadp 7, 2, 1
277; CHECK-PWR-DAG:   xsmuldp [[REG0:[0-9]+]], 4, 3
278; CHECK-PWR-DAG:   xsmaddadp 7, 6, 5
279; CHECK-PWR-DAG:   xsmaddadp [[REG0]], 9, 8
280; CHECK-PWR:       xsadddp 1, 7, [[REG0]]
281; CHECK-NEXT:  blr
282  %10 = fmul reassoc nsz double %1, %0
283  %11 = fmul reassoc nsz double %3, %2
284  %12 = fmul reassoc nsz double %5, %4
285  %13 = fmul reassoc nsz double %8, %7
286  %14 = fadd reassoc nsz double %11, %10
287  %15 = fadd reassoc nsz double %14, %6
288  %16 = fadd reassoc nsz double %15, %12
289  %17 = fadd reassoc nsz double %16, %13
290  ret double %17
291}
292
293define dso_local float @reassociate_mamama_8(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, float %8,
294                                             float %9, float %10, float %11, float %12, float %13, float %14, float %15, float %16) {
295; CHECK-LABEL: reassociate_mamama_8:
296; CHECK:       # %bb.0:
297; CHECK-DAG:    fmadds [[REG0:[0-9]+]], 3, 2, 1
298; CHECK-DAG:    fmuls  [[REG1:[0-9]+]], 5, 4
299; CHECK-DAG:    fmadds [[REG2:[0-9]+]], 7, 6, [[REG0]]
300; CHECK-DAG:    fmadds [[REG3:[0-9]+]], 9, 8, [[REG1]]
301;
302; CHECK-DAG:    fmadds [[REG4:[0-9]+]], 13, 12, [[REG3]]
303; CHECK-DAG:    fmadds [[REG5:[0-9]+]], 11, 10, [[REG2]]
304;
305; CHECK-DAG:    fmadds [[REG6:[0-9]+]], 3, 2, [[REG4]]
306; CHECK-DAG:    fmadds [[REG7:[0-9]+]], 5, 4, [[REG5]]
307; CHECK:        fadds 1, [[REG7]], [[REG6]]
308; CHECK-NEXT:   blr
309  %18 = fmul reassoc nsz float %2, %1
310  %19 = fadd reassoc nsz float %18, %0
311  %20 = fmul reassoc nsz float %4, %3
312  %21 = fadd reassoc nsz float %19, %20
313  %22 = fmul reassoc nsz float %6, %5
314  %23 = fadd reassoc nsz float %21, %22
315  %24 = fmul reassoc nsz float %8, %7
316  %25 = fadd reassoc nsz float %23, %24
317  %26 = fmul reassoc nsz float %10, %9
318  %27 = fadd reassoc nsz float %25, %26
319  %28 = fmul reassoc nsz float %12, %11
320  %29 = fadd reassoc nsz float %27, %28
321  %30 = fmul reassoc nsz float %14, %13
322  %31 = fadd reassoc nsz float %29, %30
323  %32 = fmul reassoc nsz float %16, %15
324  %33 = fadd reassoc nsz float %31, %32
325  ret float %33
326}
327
328