[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / SystemZ / swift-return.ll
blob84e257f93218f743978f31ddfefd48963d314d2a
1 ; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s
2 ; RUN: llc < %s -mtriple=s390x-linux-gnu -O0 -verify-machineinstrs | FileCheck --check-prefix=CHECK-O0 %s
4 @var = global i32 0
6 ; Test how llvm handles return type of {i16, i8}. The return value will be
7 ; passed in %r2 and %r3.
8 ; CHECK-LABEL: test:
9 ; CHECK: st %r2
10 ; CHECK: brasl %r14, gen
11 ; CHECK-DAG: lhr %{{r[0,2]+}}, %r2
12 ; CHECK-DAG: lbr %{{r[0,2]+}}, %r3
13 ; CHECK: ar %r2, %r0
14 ; CHECK-O0-LABEL: test
15 ; CHECK-O0: st %r2
16 ; CHECK-O0: brasl %r14, gen
17 ; CHECK-O0-DAG: lhr %[[REG1:r[0-9]+]], %r2
18 ; CHECK-O0-DAG: lbr %[[REG2:r[0-9]+]], %r3
19 ; CHECK-O0: ar %[[REG1]], %[[REG2]]
20 ; CHECK-O0: lr %r2, %[[REG1]]
21 define i16 @test(i32 %key) {
22 entry:
23   %key.addr = alloca i32, align 4
24   store i32 %key, i32* %key.addr, align 4
25   %0 = load i32, i32* %key.addr, align 4
26   %call = call swiftcc { i16, i8 } @gen(i32 %0)
27   %v3 = extractvalue { i16, i8 } %call, 0
28   %v1 = sext i16 %v3 to i32
29   %v5 = extractvalue { i16, i8 } %call, 1
30   %v2 = sext i8 %v5 to i32
31   %add = add nsw i32 %v1, %v2
32   %conv = trunc i32 %add to i16
33   ret i16 %conv
36 declare swiftcc { i16, i8 } @gen(i32)
38 ; If we can't pass every return value in registers, we will pass everything
39 ; in memroy. The caller provides space for the return value and passes
40 ; the address in %r2. The first input argument will be in %r3.
41 ; CHECK-LABEL: test2:
42 ; CHECK: lr %r3, %r2
43 ; CHECK-DAG: la %r2, 160(%r15)
44 ; CHECK: brasl %r14, gen2
45 ; CHECK: l %r2, 160(%r15)
46 ; CHECK: a %r2, 164(%r15)
47 ; CHECK: a %r2, 168(%r15)
48 ; CHECK: a %r2, 172(%r15)
49 ; CHECK: a %r2, 176(%r15)
50 ; CHECK-O0-LABEL: test2:
51 ; CHECK-O0: st %r2, [[SPILL1:[0-9]+]](%r15)
52 ; CHECK-O0: l %r3, [[SPILL1]](%r15)
53 ; CHECK-O0: la %r2, 160(%r15)
54 ; CHECK-O0: brasl %r14, gen2
55 ; CHECK-O0-DAG: l %r{{.*}}, 176(%r15)
56 ; CHECK-O0-DAG: l %r{{.*}}, 172(%r15)
57 ; CHECK-O0-DAG: l %r{{.*}}, 168(%r15)
58 ; CHECK-O0-DAG: l %r{{.*}}, 164(%r15)
59 ; CHECK-O0-DAG: l %r{{.*}}, 160(%r15)
60 ; CHECK-O0: ar
61 ; CHECK-O0: ar
62 ; CHECK-O0: ar
63 ; CHECK-O0: ar
64 ; CHECK-O0: lr %r2
65 define i32 @test2(i32 %key) #0 {
66 entry:
67   %key.addr = alloca i32, align 4
68   store i32 %key, i32* %key.addr, align 4
69   %0 = load i32, i32* %key.addr, align 4
70   %call = call swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %0)
72   %v3 = extractvalue { i32, i32, i32, i32, i32 } %call, 0
73   %v5 = extractvalue { i32, i32, i32, i32, i32 } %call, 1
74   %v6 = extractvalue { i32, i32, i32, i32, i32 } %call, 2
75   %v7 = extractvalue { i32, i32, i32, i32, i32 } %call, 3
76   %v8 = extractvalue { i32, i32, i32, i32, i32 } %call, 4
78   %add = add nsw i32 %v3, %v5
79   %add1 = add nsw i32 %add, %v6
80   %add2 = add nsw i32 %add1, %v7
81   %add3 = add nsw i32 %add2, %v8
82   ret i32 %add3
85 ; The address of the return value is passed in %r2.
86 ; On return, %r2 will contain the adddress that has been passed in by the caller in %r2.
87 ; CHECK-LABEL: gen2:
88 ; CHECK: st %r3, 16(%r2)
89 ; CHECK: st %r3, 12(%r2)
90 ; CHECK: st %r3, 8(%r2)
91 ; CHECK: st %r3, 4(%r2)
92 ; CHECK: st %r3, 0(%r2)
93 ; CHECK-O0-LABEL: gen2:
94 ; CHECK-O0-DAG: st %r3, 16(%r2)
95 ; CHECK-O0-DAG: st %r3, 12(%r2)
96 ; CHECK-O0-DAG: st %r3, 8(%r2)
97 ; CHECK-O0-DAG: st %r3, 4(%r2)
98 ; CHECK-O0-DAG: st %r3, 0(%r2)
99 define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) {
100   %Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0
101   %Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1
102   %Z2 = insertvalue { i32, i32, i32, i32, i32 } %Z, i32 %key, 2
103   %Z3 = insertvalue { i32, i32, i32, i32, i32 } %Z2, i32 %key, 3
104   %Z4 = insertvalue { i32, i32, i32, i32, i32 } %Z3, i32 %key, 4
105   ret { i32, i32, i32, i32, i32 } %Z4
108 ; The return value {i32, i32, i32, i32} will be returned via registers
109 ; %r2, %r3, %r4, %r5.
110 ; CHECK-LABEL: test3:
111 ; CHECK: brasl %r14, gen3
112 ; CHECK: ar %r2, %r3
113 ; CHECK: ar %r2, %r4
114 ; CHECK: ar %r2, %r5
115 ; CHECK-O0-LABEL: test3:
116 ; CHECK-O0: brasl %r14, gen3
117 ; CHECK-O0: ar %r2, %r3
118 ; CHECK-O0: ar %r2, %r4
119 ; CHECK-O0: ar %r2, %r5
120 define i32 @test3(i32 %key) #0 {
121 entry:
122   %key.addr = alloca i32, align 4
123   store i32 %key, i32* %key.addr, align 4
124   %0 = load i32, i32* %key.addr, align 4
125   %call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0)
127   %v3 = extractvalue { i32, i32, i32, i32 } %call, 0
128   %v5 = extractvalue { i32, i32, i32, i32 } %call, 1
129   %v6 = extractvalue { i32, i32, i32, i32 } %call, 2
130   %v7 = extractvalue { i32, i32, i32, i32 } %call, 3
132   %add = add nsw i32 %v3, %v5
133   %add1 = add nsw i32 %add, %v6
134   %add2 = add nsw i32 %add1, %v7
135   ret i32 %add2
138 declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key)
140 ; The return value {float, float, float, float} will be returned via registers
141 ; %f0, %f2, %f4, %f6.
142 ; CHECK-LABEL: test4:
143 ; CHECK: brasl %r14, gen4
144 ; CHECK: aebr %f0, %f2
145 ; CHECK: aebr %f0, %f4
146 ; CHECK: aebr %f0, %f6
147 ; CHECK-O0-LABEL: test4:
148 ; CHECK-O0: brasl %r14, gen4
149 ; CHECK-O0: aebr %f0, %f2
150 ; CHECK-O0: aebr %f0, %f4
151 ; CHECK-O0: aebr %f0, %f6
152 define float @test4(float %key) #0 {
153 entry:
154   %key.addr = alloca float, align 4
155   store float %key, float* %key.addr, align 4
156   %0 = load float, float* %key.addr, align 4
157   %call = call swiftcc { float, float, float, float } @gen4(float %0)
159   %v3 = extractvalue { float, float, float, float } %call, 0
160   %v5 = extractvalue { float, float, float, float } %call, 1
161   %v6 = extractvalue { float, float, float, float } %call, 2
162   %v7 = extractvalue { float, float, float, float } %call, 3
164   %add = fadd float %v3, %v5
165   %add1 = fadd float %add, %v6
166   %add2 = fadd float %add1, %v7
167   ret float %add2
170 declare swiftcc { float, float, float, float } @gen4(float %key)
172 ; CHECK-LABEL: consume_i1_ret:
173 ; CHECK: brasl %r14, produce_i1_ret
174 ; CHECK: nilf %r2, 1
175 ; CHECK: nilf %r3, 1
176 ; CHECK: nilf %r4, 1
177 ; CHECK: nilf %r5, 1
178 ; CHECK-O0-LABEL: consume_i1_ret:
179 ; CHECK-O0: brasl %r14, produce_i1_ret
180 ; CHECK-O0: nilf %r2, 1
181 ; CHECK-O0: nilf %r3, 1
182 ; CHECK-O0: nilf %r4, 1
183 ; CHECK-O0: nilf %r5, 1
184 define void @consume_i1_ret() {
185   %call = call swiftcc { i1, i1, i1, i1 } @produce_i1_ret()
186   %v3 = extractvalue { i1, i1, i1, i1 } %call, 0
187   %v5 = extractvalue { i1, i1, i1, i1 } %call, 1
188   %v6 = extractvalue { i1, i1, i1, i1 } %call, 2
189   %v7 = extractvalue { i1, i1, i1, i1 } %call, 3
190   %val = zext i1 %v3 to i32
191   store volatile i32 %val, i32* @var
192   %val2 = zext i1 %v5 to i32
193   store volatile i32 %val2, i32* @var
194   %val3 = zext i1 %v6 to i32
195   store volatile i32 %val3, i32* @var
196   %val4 = zext i1 %v7 to i32
197   store i32 %val4, i32* @var
198   ret void
201 declare swiftcc { i1, i1, i1, i1 } @produce_i1_ret()