[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / PowerPC / ppc64le-aggregates.ll
blob3819e2654f2aee560cdc9a6a6baef8169f286721
1 ; RUN: llc -relocation-model=pic -verify-machineinstrs < %s -mcpu=pwr8 \
2 ; RUN:   -mattr=+altivec -mattr=-vsx | FileCheck %s
3 ; RUN: llc -relocation-model=pic -verify-machineinstrs < %s -mattr=+altivec \
4 ; RUN:   -mattr=-vsx | FileCheck %s
5 ; RUN: llc -relocation-model=pic -verify-machineinstrs < %s -mcpu=pwr9 \
6 ; RUN:   -mattr=-direct-move -mattr=+altivec | FileCheck %s
8 ; Currently VSX support is disabled for this test because we generate lxsdx
9 ; instead of lfd, and stxsdx instead of stfd.  That is a poor choice when we
10 ; have reg+imm addressing, and is on the list of things to be fixed.
11 ; The second run step is to ensure that -march=ppc64le is adequate to select
12 ; the same feature set as with -mcpu=pwr8 since that is the baseline for ppc64le.
14 target datalayout = "e-m:e-i64:64-n32:64"
15 target triple = "powerpc64le-unknown-linux-gnu"
18 ; Verify use of registers for float/vector aggregate return.
21 define [8 x float] @return_float([8 x float] %x) {
22 entry:
23   ret [8 x float] %x
25 ; CHECK-LABEL: @return_float
26 ; CHECK: %entry
27 ; CHECK-NEXT: blr
29 define [8 x double] @return_double([8 x double] %x) {
30 entry:
31   ret [8 x double] %x
33 ; CHECK-LABEL: @return_double
34 ; CHECK: %entry
35 ; CHECK-NEXT: blr
37 define [4 x ppc_fp128] @return_ppcf128([4 x ppc_fp128] %x) {
38 entry:
39   ret [4 x ppc_fp128] %x
41 ; CHECK-LABEL: @return_ppcf128
42 ; CHECK: %entry
43 ; CHECK-NEXT: blr
45 define [8 x <4 x i32>] @return_v4i32([8 x <4 x i32>] %x) {
46 entry:
47   ret [8 x <4 x i32>] %x
49 ; CHECK-LABEL: @return_v4i32
50 ; CHECK: %entry
51 ; CHECK-NEXT: blr
55 ; Verify amount of space taken up by aggregates in the parameter save area.
58 define i64 @callee_float([7 x float] %a, [7 x float] %b, i64 %c) {
59 entry:
60   ret i64 %c
62 ; CHECK-LABEL: @callee_float
63 ; CHECK: ld 3, 96(1)
64 ; CHECK: blr
66 define void @caller_float(i64 %x, [7 x float] %y) {
67 entry:
68   tail call void @test_float([7 x float] %y, [7 x float] %y, i64 %x)
69   ret void
71 ; CHECK-LABEL: @caller_float
72 ; CHECK: std 3, 96(1)
73 ; CHECK: bl test_float
75 declare void @test_float([7 x float], [7 x float], i64)
77 define i64 @callee_double(i64 %a, [7 x double] %b, i64 %c) {
78 entry:
79   ret i64 %c
81 ; CHECK-LABEL: @callee_double
82 ; CHECK: ld 3, 96(1)
83 ; CHECK: blr
85 define void @caller_double(i64 %x, [7 x double] %y) {
86 entry:
87   tail call void @test_double(i64 %x, [7 x double] %y, i64 %x)
88   ret void
90 ; CHECK-LABEL: @caller_double
91 ; CHECK: std 3, 96(1)
92 ; CHECK: bl test_double
94 declare void @test_double(i64, [7 x double], i64)
96 define i64 @callee_ppcf128(i64 %a, [4 x ppc_fp128] %b, i64 %c) {
97 entry:
98   ret i64 %c
100 ; CHECK-LABEL: @callee_ppcf128
101 ; CHECK: ld 3, 104(1)
102 ; CHECK: blr
104 define void @caller_ppcf128(i64 %x, [4 x ppc_fp128] %y) {
105 entry:
106   tail call void @test_ppcf128(i64 %x, [4 x ppc_fp128] %y, i64 %x)
107   ret void
109 ; CHECK-LABEL: @caller_ppcf128
110 ; CHECK: std 3, 104(1)
111 ; CHECK: bl test_ppcf128
113 declare void @test_ppcf128(i64, [4 x ppc_fp128], i64)
115 define i64 @callee_i64(i64 %a, [7 x i64] %b, i64 %c) {
116 entry:
117   ret i64 %c
119 ; CHECK-LABEL: @callee_i64
120 ; CHECK: ld 3, 96(1)
121 ; CHECK: blr
123 define void @caller_i64(i64 %x, [7 x i64] %y) {
124 entry:
125   tail call void @test_i64(i64 %x, [7 x i64] %y, i64 %x)
126   ret void
128 ; CHECK-LABEL: @caller_i64
129 ; CHECK: std 3, 96(1)
130 ; CHECK: bl test_i64
132 declare void @test_i64(i64, [7 x i64], i64)
134 define i64 @callee_i128(i64 %a, [4 x i128] %b, i64 %c) {
135 entry:
136   ret i64 %c
138 ; CHECK-LABEL: @callee_i128
139 ; CHECK: ld 3, 112(1)
140 ; CHECK: blr
142 define void @caller_i128(i64 %x, [4 x i128] %y) {
143 entry:
144   tail call void @test_i128(i64 %x, [4 x i128] %y, i64 %x)
145   ret void
147 ; CHECK-LABEL: @caller_i128
148 ; CHECK: std 3, 112(1)
149 ; CHECK: bl test_i128
151 declare void @test_i128(i64, [4 x i128], i64)
153 define i64 @callee_v4i32(i64 %a, [4 x <4 x i32>] %b, i64 %c) {
154 entry:
155   ret i64 %c
157 ; CHECK-LABEL: @callee_v4i32
158 ; CHECK: ld 3, 112(1)
159 ; CHECK: blr
161 define void @caller_v4i32(i64 %x, [4 x <4 x i32>] %y) {
162 entry:
163   tail call void @test_v4i32(i64 %x, [4 x <4 x i32>] %y, i64 %x)
164   ret void
166 ; CHECK-LABEL: @caller_v4i32
167 ; CHECK: std 3, 112(1)
168 ; CHECK: bl test_v4i32
170 declare void @test_v4i32(i64, [4 x <4 x i32>], i64)
174 ; Verify handling of floating point arguments in GPRs
177 %struct.float8 = type { [8 x float] }
178 %struct.float5 = type { [5 x float] }
179 %struct.float2 = type { [2 x float] }
181 @g8 = common global %struct.float8 zeroinitializer, align 4
182 @g5 = common global %struct.float5 zeroinitializer, align 4
183 @g2 = common global %struct.float2 zeroinitializer, align 4
185 define float @callee0([7 x float] %a, [7 x float] %b) {
186 entry:
187   %b.extract = extractvalue [7 x float] %b, 6
188   ret float %b.extract
190 ; CHECK-LABEL: @callee0
191 ; CHECK: stw 10, [[OFF:.*]](1)
192 ; CHECK: lfs 1, [[OFF]](1)
193 ; CHECK: blr
195 define void @caller0([7 x float] %a) {
196 entry:
197   tail call void @test0([7 x float] %a, [7 x float] %a)
198   ret void
200 ; CHECK-LABEL: @caller0
201 ; CHECK-DAG: fmr 8, 1
202 ; CHECK-DAG: fmr 9, 2
203 ; CHECK-DAG: fmr 10, 3
204 ; CHECK-DAG: fmr 11, 4
205 ; CHECK-DAG: fmr 12, 5
206 ; CHECK-DAG: fmr 13, 6
207 ; CHECK-DAG: stfs 7, [[OFF:[0-9]+]](1)
208 ; CHECK-DAG: lwz 10, [[OFF]](1)
209 ; CHECK: bl test0
211 declare void @test0([7 x float], [7 x float])
213 define float @callee1([8 x float] %a, [8 x float] %b) {
214 entry:
215   %b.extract = extractvalue [8 x float] %b, 7
216   ret float %b.extract
218 ; CHECK-LABEL: @callee1
219 ; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32
220 ; CHECK: stw [[REG]], [[OFF:.*]](1)
221 ; CHECK: lfs 1, [[OFF]](1)
222 ; CHECK: blr
224 define void @caller1([8 x float] %a) {
225 entry:
226   tail call void @test1([8 x float] %a, [8 x float] %a)
227   ret void
229 ; CHECK-LABEL: @caller1
230 ; CHECK-DAG: fmr 9, 1
231 ; CHECK-DAG: fmr 10, 2
232 ; CHECK-DAG: fmr 11, 3
233 ; CHECK-DAG: fmr 12, 4
234 ; CHECK-DAG: fmr 13, 5
235 ; CHECK-DAG: stfs 5, [[OFF0:[0-9]+]](1)
236 ; CHECK-DAG: stfs 6, [[OFF1:[0-9]+]](1)
237 ; CHECK-DAG: stfs 7, [[OFF2:[0-9]+]](1)
238 ; CHECK-DAG: stfs 8, [[OFF3:[0-9]+]](1)
239 ; CHECK-DAG: lwz 9, [[OFF0]](1)
240 ; CHECK-DAG: lwz [[REG1:[0-9]+]], [[OFF1]](1)
241 ; CHECK-DAG: lwz 10, [[OFF2]](1)
242 ; CHECK-DAG: lwz [[REG3:[0-9]+]], [[OFF3]](1)
243 ; CHECK-DAG: rldimi 9, [[REG1]], 32, 0
244 ; CHECK-DAG: rldimi 10, [[REG3]], 32, 0
245 ; CHECK: bl test1
247 declare void @test1([8 x float], [8 x float])
249 define float @callee2([8 x float] %a, [5 x float] %b, [2 x float] %c) {
250 entry:
251   %c.extract = extractvalue [2 x float] %c, 1
252   ret float %c.extract
254 ; CHECK-LABEL: @callee2
255 ; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32
256 ; CHECK: stw [[REG]], [[OFF:.*]](1)
257 ; CHECK: lfs 1, [[OFF]](1)
258 ; CHECK: blr
260 define void @caller2() {
261 entry:
262   %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4
263   %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4
264   %2 = load [2 x float], [2 x float]* getelementptr inbounds (%struct.float2, %struct.float2* @g2, i64 0, i32 0), align 4
265   tail call void @test2([8 x float] %0, [5 x float] %1, [2 x float] %2)
266   ret void
268 ; CHECK-LABEL: @caller2
269 ; CHECK: ld {{[0-9]+}}, .LC
270 ; CHECK-DAG: lfs 1, 0({{[0-9]+}})
271 ; CHECK-DAG: lfs 2, 4({{[0-9]+}})
272 ; CHECK-DAG: lfs 3, 8({{[0-9]+}})
273 ; CHECK-DAG: lfs 4, 12({{[0-9]+}})
274 ; CHECK-DAG: lfs 5, 16({{[0-9]+}})
275 ; CHECK-DAG: lfs 6, 20({{[0-9]+}})
276 ; CHECK-DAG: lfs 7, 24({{[0-9]+}})
277 ; CHECK-DAG: lfs 8, 28({{[0-9]+}})
279 ; CHECK-DAG: lfs 9, 0({{[0-9]+}})
280 ; CHECK-DAG: lfs 10, 4({{[0-9]+}})
281 ; CHECK-DAG: lfs 11, 8({{[0-9]+}})
282 ; CHECK-DAG: lfs 12, 12({{[0-9]+}})
283 ; CHECK-DAG: lfs 13, 16({{[0-9]+}})
285 ; CHECK-DAG: ld 10, 0({{[0-9]+}})
286 ; CHECK: bl test2
288 declare void @test2([8 x float], [5 x float], [2 x float])
290 define double @callee3([8 x float] %a, [5 x float] %b, double %c) {
291 entry:
292   ret double %c
294 ; CHECK-LABEL: @callee3
295 ; CHECK: std 10, [[OFF:.*]](1)
296 ; CHECK: lfd 1, [[OFF]](1)
297 ; CHECK: blr
299 define void @caller3(double %d) {
300 entry:
301   %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4
302   %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4
303   tail call void @test3([8 x float] %0, [5 x float] %1, double %d)
304   ret void
306 ; CHECK-LABEL: @caller3
307 ; CHECK: stfd 1, [[OFF:.*]](1)
308 ; CHECK: ld 10, [[OFF]](1)
309 ; CHECK: bl test3
311 declare void @test3([8 x float], [5 x float], double)
313 define float @callee4([8 x float] %a, [5 x float] %b, float %c) {
314 entry:
315   ret float %c
317 ; CHECK-LABEL: @callee4
318 ; CHECK: stw 10, [[OFF:.*]](1)
319 ; CHECK: lfs 1, [[OFF]](1)
320 ; CHECK: blr
322 define void @caller4(float %f) {
323 entry:
324   %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4
325   %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4
326   tail call void @test4([8 x float] %0, [5 x float] %1, float %f)
327   ret void
329 ; CHECK-LABEL: @caller4
330 ; CHECK: stfs 1, [[OFF:.*]](1)
331 ; CHECK: lwz 10, [[OFF]](1)
332 ; CHECK: bl test4
334 declare void @test4([8 x float], [5 x float], float)