1; RUN: llc -relocation-model=pic -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown \
2; RUN:   -enable-ppc-quad-precision -verify-machineinstrs \
3; RUN:   -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s
4; RUN: llc -relocation-model=pic -mcpu=pwr9 -mtriple=powerpc64-unknown-unknown \
5; RUN:   -enable-ppc-quad-precision -verify-machineinstrs \
6; RUN:   -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s \
7; RUN:   | FileCheck -check-prefix=CHECK-BE %s
8
9; Testing homogeneous aggregates.
10
11%struct.With9fp128params = type { fp128, fp128, fp128, fp128, fp128, fp128,
12                                  fp128, fp128, fp128 }
13
14@a1 = common local_unnamed_addr global [3 x fp128] zeroinitializer, align 16
15
16; Function Attrs: norecurse nounwind readonly
17define fp128 @testArray_01(fp128* nocapture readonly %sa) {
18; CHECK-LABEL: testArray_01:
19; CHECK:       # %bb.0: # %entry
20; CHECK-NEXT:    lxv v2, 32(r3)
21; CHECK-NEXT:    blr
22
23; CHECK-BE-LABEL: testArray_01:
24; CHECK-BE:       lxv v2, 32(r3)
25; CHECK-BE-NEXT:  blr
26entry:
27  %arrayidx = getelementptr inbounds fp128, fp128* %sa, i64 2
28  %0 = load fp128, fp128* %arrayidx, align 16
29  ret fp128 %0
30}
31
32; Function Attrs: norecurse nounwind readonly
33define fp128 @testArray_02() {
34; CHECK-LABEL: testArray_02:
35; CHECK:       # %bb.0: # %entry
36; CHECK-NEXT:    addis r3, r2, .LC0@toc@ha
37; CHECK-NEXT:    ld r3, .LC0@toc@l(r3)
38; CHECK-NEXT:    lxv v2, 32(r3)
39; CHECK-NEXT:    blr
40
41; CHECK-BE-LABEL: testArray_02:
42; CHECK-BE:       lxv v2, 32(r3)
43; CHECK-BE-NEXT:  blr
44entry:
45  %0 = load fp128, fp128* getelementptr inbounds ([3 x fp128], [3 x fp128]* @a1,
46                                                  i64 0, i64 2), align 16
47  ret fp128 %0
48}
49
50; Function Attrs: norecurse nounwind readnone
51define fp128 @testStruct_01(fp128 inreg returned %a.coerce) {
52; CHECK-LABEL: testStruct_01:
53; CHECK:       # %bb.0: # %entry
54; CHECK-NEXT:    blr
55
56; CHECK-BE-LABEL: testStruct_01:
57; CHECK-BE:       # %bb.0: # %entry
58; CHECK-BE-NEXT:  blr
59entry:
60  ret fp128 %a.coerce
61}
62
63; Function Attrs: norecurse nounwind readnone
64define fp128 @testStruct_02([8 x fp128] %a.coerce) {
65; CHECK-LABEL: testStruct_02:
66; CHECK:       # %bb.0: # %entry
67; CHECK-NEXT:    vmr v2, v9
68; CHECK-NEXT:    blr
69
70; CHECK-BE-LABEL: testStruct_02:
71; CHECK-BE:       vmr v2, v9
72; CHECK-BE-NEXT:  blr
73entry:
74  %a.coerce.fca.7.extract = extractvalue [8 x fp128] %a.coerce, 7
75  ret fp128 %a.coerce.fca.7.extract
76}
77
78; Since we can only pass a max of 8 float128 value in VSX registers, ensure we
79; store to stack if passing more.
80; Function Attrs: norecurse nounwind readonly
81define fp128 @testStruct_03(%struct.With9fp128params* byval nocapture readonly
82                            align 16 %a) {
83; CHECK-LABEL: testStruct_03:
84; CHECK:       # %bb.0: # %entry
85; CHECK:        lxv v2, 128(r1)
86; CHECK-DAG:    std r10, 88(r1)
87; CHECK-DAG:    std r9, 80(r1)
88; CHECK-DAG:    std r8, 72(r1)
89; CHECK-DAG:    std r7, 64(r1)
90; CHECK-DAG:    std r6, 56(r1)
91; CHECK-DAG:    std r5, 48(r1)
92; CHECK-DAG:    std r4, 40(r1)
93; CHECK-DAG:    std r3, 32(r1)
94; CHECK-NEXT:    blr
95
96; CHECK-BE-LABEL: testStruct_03:
97; CHECK-BE:       # %bb.0: # %entry
98; CHECK-BE:        lxv v2, 144(r1)
99; CHECK-BE-DAG:    std r10, 104(r1)
100; CHECK-BE-DAG:    std r9, 96(r1)
101; CHECK-BE-DAG:    std r8, 88(r1)
102; CHECK-BE-DAG:    std r7, 80(r1)
103; CHECK-BE-DAG:    std r6, 72(r1)
104; CHECK-BE-DAG:    std r5, 64(r1)
105; CHECK-BE-DAG:    std r4, 56(r1)
106; CHECK-BE-DAG:    std r3, 48(r1)
107; CHECK-BE-NEXT:    blr
108entry:
109  %a7 = getelementptr inbounds %struct.With9fp128params,
110                               %struct.With9fp128params* %a, i64 0, i32 6
111  %0 = load fp128, fp128* %a7, align 16
112  ret fp128 %0
113}
114
115; Function Attrs: norecurse nounwind readnone
116define fp128 @testStruct_04([8 x fp128] %a.coerce) {
117; CHECK-LABEL: testStruct_04:
118; CHECK:       # %bb.0: # %entry
119; CHECK-NEXT:    vmr v2, v5
120; CHECK-NEXT:    blr
121
122; CHECK-BE-LABEL: testStruct_04:
123; CHECK-BE:       vmr v2, v5
124; CHECK-BE-NEXT:  blr
125entry:
126  %a.coerce.fca.3.extract = extractvalue [8 x fp128] %a.coerce, 3
127  ret fp128 %a.coerce.fca.3.extract
128}
129
130; Function Attrs: norecurse nounwind readnone
131define fp128 @testHUnion_01([1 x fp128] %a.coerce) {
132; CHECK-LABEL: testHUnion_01:
133; CHECK:       # %bb.0: # %entry
134; CHECK-NEXT:    blr
135
136; CHECK-BE-LABEL: testHUnion_01:
137; CHECK-BE:       # %bb.0: # %entry
138; CHECK-BE-NEXT:  blr
139entry:
140  %a.coerce.fca.0.extract = extractvalue [1 x fp128] %a.coerce, 0
141  ret fp128 %a.coerce.fca.0.extract
142}
143
144; Function Attrs: norecurse nounwind readnone
145define fp128 @testHUnion_02([3 x fp128] %a.coerce) {
146; CHECK-LABEL: testHUnion_02:
147; CHECK:       # %bb.0: # %entry
148; CHECK-NEXT:    blr
149
150; CHECK-BE-LABEL: testHUnion_02:
151; CHECK-BE:       # %bb.0: # %entry
152; CHECK-BE-NEXT:  blr
153entry:
154  %a.coerce.fca.0.extract = extractvalue [3 x fp128] %a.coerce, 0
155  ret fp128 %a.coerce.fca.0.extract
156}
157
158; Function Attrs: norecurse nounwind readnone
159define fp128 @testHUnion_03([3 x fp128] %a.coerce) {
160; CHECK-LABEL: testHUnion_03:
161; CHECK:       # %bb.0: # %entry
162; CHECK-NEXT:    vmr v2, v3
163; CHECK-NEXT:    blr
164
165; CHECK-BE-LABEL: testHUnion_03:
166; CHECK-BE:       # %bb.0: # %entry
167; CHECK-BE-NEXT:  vmr v2, v3
168; CHECK-BE-NEXT:  blr
169entry:
170  %a.coerce.fca.1.extract = extractvalue [3 x fp128] %a.coerce, 1
171  ret fp128 %a.coerce.fca.1.extract
172}
173
174; Function Attrs: norecurse nounwind readnone
175define fp128 @testHUnion_04([3 x fp128] %a.coerce) {
176; CHECK-LABEL: testHUnion_04:
177; CHECK:       # %bb.0: # %entry
178; CHECK-NEXT:    vmr v2, v4
179; CHECK-NEXT:    blr
180
181; CHECK-BE-LABEL: testHUnion_04:
182; CHECK-BE:       # %bb.0: # %entry
183; CHECK-BE-NEXT:  vmr v2, v4
184; CHECK-BE-NEXT:  blr
185entry:
186  %a.coerce.fca.2.extract = extractvalue [3 x fp128] %a.coerce, 2
187  ret fp128 %a.coerce.fca.2.extract
188}
189
190; Testing mixed member aggregates.
191
192%struct.MixedC = type { i32, %struct.SA, float, [12 x i8] }
193%struct.SA = type { double, fp128, <4 x float> }
194
195; Function Attrs: norecurse nounwind readnone
196define fp128 @testMixedAggregate([3 x i128] %a.coerce) {
197; CHECK-LABEL: testMixedAggregate:
198; CHECK:       # %bb.0: # %entry
199; CHECK-NEXT:    mtvsrdd v2, r8, r7
200; CHECK-NEXT:    blr
201
202; CHECK-BE-LABEL: testMixedAggregate:
203; CHECK-BE:       mtvsrdd v2, r8, r7
204; CHECK-BE-NEXT:  blr
205entry:
206  %a.coerce.fca.2.extract = extractvalue [3 x i128] %a.coerce, 2
207  %0 = bitcast i128 %a.coerce.fca.2.extract to fp128
208  ret fp128 %0
209}
210
211; Function Attrs: norecurse nounwind readnone
212define fp128 @testMixedAggregate_02([4 x i128] %a.coerce) {
213; CHECK-LABEL: testMixedAggregate_02:
214; CHECK:       # %bb.0: # %entry
215; CHECK-NEXT:    mtvsrdd v2, r6, r5
216; CHECK-NEXT:    blr
217
218; CHECK-BE-LABEL: testMixedAggregate_02:
219; CHECK-BE:       mtvsrdd v2, r6, r5
220; CHECK-BE-NEXT:  blr
221entry:
222  %a.coerce.fca.1.extract = extractvalue [4 x i128] %a.coerce, 1
223  %0 = bitcast i128 %a.coerce.fca.1.extract to fp128
224  ret fp128 %0
225}
226
227; Function Attrs: norecurse nounwind readnone
228define fp128 @testMixedAggregate_03([4 x i128] %sa.coerce) {
229; CHECK-LABEL: testMixedAggregate_03:
230; CHECK:       # %bb.0: # %entry
231; CHECK:         mtvsrwa v2, r3
232; CHECK:         xscvsdqp v2, v2
233; CHECK:         mtvsrdd v3, r6, r5
234; CHECK:         xsaddqp v2, v3, v2
235; CHECK:         mtvsrd v[[REG1:[0-9]+]], r10
236; CHECK:         xscvsdqp v[[REG:[0-9]+]], v[[REG1]]
237; CHECK:         xsaddqp v2, v2, v[[REG]]
238; CHECK-NEXT:    blr
239entry:
240  %sa.coerce.fca.0.extract = extractvalue [4 x i128] %sa.coerce, 0
241  %sa.sroa.0.0.extract.trunc = trunc i128 %sa.coerce.fca.0.extract to i32
242  %sa.coerce.fca.1.extract = extractvalue [4 x i128] %sa.coerce, 1
243  %sa.coerce.fca.3.extract = extractvalue [4 x i128] %sa.coerce, 3
244  %sa.sroa.6.48.extract.shift = lshr i128 %sa.coerce.fca.3.extract, 64
245  %sa.sroa.6.48.extract.trunc = trunc i128 %sa.sroa.6.48.extract.shift to i64
246  %conv = sitofp i32 %sa.sroa.0.0.extract.trunc to fp128
247  %0 = bitcast i128 %sa.coerce.fca.1.extract to fp128
248  %add = fadd fp128 %0, %conv
249  %conv2 = sitofp i64 %sa.sroa.6.48.extract.trunc to fp128
250  %add3 = fadd fp128 %add, %conv2
251  ret fp128 %add3
252}
253
254
255; Function Attrs: norecurse nounwind readonly
256define fp128 @testNestedAggregate(%struct.MixedC* byval nocapture readonly align 16 %a) {
257; CHECK-LABEL: testNestedAggregate:
258; CHECK:       # %bb.0: # %entry
259; CHECK-DAG:     std r8, 72(r1)
260; CHECK-DAG:     std r7, 64(r1)
261; CHECK:         lxv v2, 64(r1)
262; CHECK-DAG:     std r10, 88(r1)
263; CHECK-DAG:     std r9, 80(r1)
264; CHECK-DAG:     std r6, 56(r1)
265; CHECK-DAG:     std r5, 48(r1)
266; CHECK-DAG:     std r4, 40(r1)
267; CHECK-DAG:     std r3, 32(r1)
268; CHECK-NEXT:    blr
269
270; CHECK-BE-LABEL: testNestedAggregate:
271; CHECK-BE:       # %bb.0: # %entry
272; CHECK-BE-DAG:     std r8, 88(r1)
273; CHECK-BE-DAG:     std r7, 80(r1)
274; CHECK-BE-NEXT:    lxv v2, 80(r1)
275; CHECK-BE-DAG:     std r10, 104(r1)
276; CHECK-BE-DAG:     std r9, 96(r1)
277; CHECK-BE-DAG:     std r6, 72(r1)
278; CHECK-BE-DAG:     std r5, 64(r1)
279; CHECK-BE-DAG:     std r4, 56(r1)
280; CHECK-BE-DAG:     std r3, 48(r1)
281; CHECK-BE-NEXT:    blr
282entry:
283  %c = getelementptr inbounds %struct.MixedC, %struct.MixedC* %a, i64 0, i32 1, i32 1
284  %0 = load fp128, fp128* %c, align 16
285  ret fp128 %0
286}
287
288; Function Attrs: norecurse nounwind readnone
289define fp128 @testUnion_01([1 x i128] %a.coerce) {
290; CHECK-LABEL: testUnion_01:
291; CHECK:       # %bb.0: # %entry
292; CHECK-NEXT:    mtvsrdd v2, r4, r3
293; CHECK-NEXT:    blr
294
295; CHECK-BE-LABEL: testUnion_01:
296; CHECK-BE:       mtvsrdd v2, r4, r3
297; CHECK-BE-NEXT:  blr
298entry:
299  %a.coerce.fca.0.extract = extractvalue [1 x i128] %a.coerce, 0
300  %0 = bitcast i128 %a.coerce.fca.0.extract to fp128
301  ret fp128 %0
302}
303
304; Function Attrs: norecurse nounwind readnone
305define fp128 @testUnion_02([1 x i128] %a.coerce) {
306; CHECK-LABEL: testUnion_02:
307; CHECK:       # %bb.0: # %entry
308; CHECK-NEXT:    mtvsrdd v2, r4, r3
309; CHECK-NEXT:    blr
310
311; CHECK-BE-LABEL: testUnion_02:
312; CHECK-BE:       mtvsrdd v2, r4, r3
313; CHECK-BE-NEXT:  blr
314entry:
315  %a.coerce.fca.0.extract = extractvalue [1 x i128] %a.coerce, 0
316  %0 = bitcast i128 %a.coerce.fca.0.extract to fp128
317  ret fp128 %0
318}
319
320; Function Attrs: norecurse nounwind readnone
321define fp128 @testUnion_03([4 x i128] %a.coerce) {
322; CHECK-LABEL: testUnion_03:
323; CHECK:       # %bb.0: # %entry
324; CHECK-NEXT:    mtvsrdd v2, r8, r7
325; CHECK-NEXT:    blr
326
327; CHECK-BE-LABEL: testUnion_03:
328; CHECK-BE:       mtvsrdd v2, r8, r7
329; CHECK-BE-NEXT:  blr
330entry:
331  %a.coerce.fca.2.extract = extractvalue [4 x i128] %a.coerce, 2
332  %0 = bitcast i128 %a.coerce.fca.2.extract to fp128
333  ret fp128 %0
334}
335
336; Function Attrs: nounwind
337define fp128 @sum_float128(i32 signext %count, ...) {
338; CHECK-LABEL: sum_float128:
339; CHECK:       # %bb.0: # %entry
340; CHECK-DAG:     std r10, 88(r1)
341; CHECK-DAG:     std r9, 80(r1)
342; CHECK-DAG:     std r8, 72(r1)
343; CHECK-DAG:     std r7, 64(r1)
344; CHECK-DAG:     std r6, 56(r1)
345; CHECK-DAG:     std r4, 40(r1)
346; CHECK-DAG:     cmpwi cr0, r3, 1
347; CHECK-DAG:     std r5, 48(r1)
348; CHECK-DAG:     addis [[REG:r[0-9]+]], r2, .LCPI17_0@toc@ha
349; CHECK-DAG:     addi [[REG1:r[0-9]+]], [[REG]], .LCPI17_0@toc@l
350; CHECK-DAG:     lxvx v2, 0, [[REG1]]
351; CHECK-NEXT:    bltlr cr0
352; CHECK-NEXT:  # %bb.1: # %if.end
353; CHECK-NEXT:    addi r3, r1, 40
354; CHECK-NEXT:    lxvx v3, 0, r3
355; CHECK-NEXT:    xsaddqp v2, v3, v2
356; CHECK-NEXT:    addi [[REG2:r[0-9]+]], r1, 72
357; CHECK-NEXT:    std [[REG2]], -8(r1)
358; CHECK-NEXT:    lxv v3, 16(r3)
359; CHECK-NEXT:    xsaddqp v2, v2, v3
360; CHECK-NEXT:    blr
361entry:
362  %ap = alloca i8*, align 8
363  %0 = bitcast i8** %ap to i8*
364  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) #2
365  %cmp = icmp slt i32 %count, 1
366  br i1 %cmp, label %cleanup, label %if.end
367
368if.end:                                           ; preds = %entry
369  call void @llvm.va_start(i8* nonnull %0)
370  %argp.cur = load i8*, i8** %ap, align 8
371  %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16
372  %1 = bitcast i8* %argp.cur to fp128*
373  %2 = load fp128, fp128* %1, align 8
374  %add = fadd fp128 %2, 0xL00000000000000000000000000000000
375  %argp.next3 = getelementptr inbounds i8, i8* %argp.cur, i64 32
376  store i8* %argp.next3, i8** %ap, align 8
377  %3 = bitcast i8* %argp.next to fp128*
378  %4 = load fp128, fp128* %3, align 8
379  %add4 = fadd fp128 %add, %4
380  call void @llvm.va_end(i8* nonnull %0)
381  br label %cleanup
382
383cleanup:                                          ; preds = %entry, %if.end
384  %retval.0 = phi fp128 [ %add4, %if.end ], [ 0xL00000000000000000000000000000000, %entry ]
385  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) #2
386  ret fp128 %retval.0
387}
388
389declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
390declare void @llvm.va_start(i8*) #2
391declare void @llvm.va_end(i8*) #2
392declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
393