1; FIXME: FastISel currently returns false if it hits code that uses VSX
2; registers and with -fast-isel-abort=1 turned on the test case will then fail.
3; When fastisel better supports VSX fix up this test case.
4;
5; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=-vsx -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck %s --check-prefix=ELF64
6; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=spe  -mtriple=powerpc-unknown-linux-gnu -mcpu=e500 | FileCheck %s --check-prefix=SPE
7
8; This test verifies that load/store instructions are properly generated,
9; and that they pass MI verification.
10
11@a = global i8 1, align 1
12@b = global i16 2, align 2
13@c = global i32 4, align 4
14@d = global i64 8, align 8
15@e = global float 1.25, align 4
16@f = global double 3.5, align 8
17
18%struct.s = type<{ i8, i32 }>
19%struct.t = type<{ i8, i64 }>
20
21@g = global %struct.s <{ i8 1, i32 2 }>, align 1
22@h = global %struct.t <{ i8 1, i64 2 }>, align 1
23
24@i = common global [8192 x i64] zeroinitializer, align 8
25
26; load
27
28define i8 @t1() nounwind {
29; ELF64: t1
30  %1 = load i8, i8* @a, align 1
31; ELF64: lbz
32  %2 = add nsw i8 %1, 1
33; ELF64: addi
34  ret i8 %2
35}
36
37define i16 @t2() nounwind {
38; ELF64: t2
39  %1 = load i16, i16* @b, align 2
40; ELF64: lhz
41  %2 = add nsw i16 %1, 1
42; ELF64: addi
43  ret i16 %2
44}
45
46define i32 @t3() nounwind {
47; ELF64: t3
48  %1 = load i32, i32* @c, align 4
49; ELF64: lwz
50  %2 = add nsw i32 %1, 1
51; ELF64: addi
52  ret i32 %2
53}
54
55define i64 @t4() nounwind {
56; ELF64: t4
57  %1 = load i64, i64* @d, align 4
58; ELF64: ld
59  %2 = add nsw i64 %1, 1
60; ELF64: addi
61  ret i64 %2
62}
63
64define float @t5() nounwind {
65; ELF64: t5
66; SPE: t5
67  %1 = load float, float* @e, align 4
68; ELF64: lfs
69; SPE: lwz
70  %2 = fadd float %1, 1.0
71; ELF64: fadds
72; SPE: efsadd
73  ret float %2
74}
75
76define double @t6() nounwind {
77; ELF64: t6
78; SPE: t6
79  %1 = load double, double* @f, align 8
80; ELF64: lfd
81; SPE: evldd
82  %2 = fadd double %1, 1.0
83; ELF64: fadd
84; SPE: efdadd
85  ret double %2
86}
87
88; store
89
90define void @t7(i8 %v) nounwind {
91; ELF64: t7
92  %1 = add nsw i8 %v, 1
93  store i8 %1, i8* @a, align 1
94; ELF64: addis
95; ELF64: addi
96; ELF64: addi
97; ELF64: stb
98  ret void
99}
100
101define void @t8(i16 %v) nounwind {
102; ELF64: t8
103  %1 = add nsw i16 %v, 1
104  store i16 %1, i16* @b, align 2
105; ELF64: addis
106; ELF64: addi
107; ELF64: addi
108; ELF64: sth
109  ret void
110}
111
112define void @t9(i32 %v) nounwind {
113; ELF64: t9
114  %1 = add nsw i32 %v, 1
115  store i32 %1, i32* @c, align 4
116; ELF64: addis
117; ELF64: addi
118; ELF64: addi
119; ELF64: stw
120  ret void
121}
122
123define void @t10(i64 %v) nounwind {
124; ELF64: t10
125  %1 = add nsw i64 %v, 1
126  store i64 %1, i64* @d, align 4
127; ELF64: addis
128; ELF64: addi
129; ELF64: addi
130; ELF64: std
131  ret void
132}
133
134define void @t11(float %v) nounwind {
135; ELF64: t11
136; SPE: t11
137  %1 = fadd float %v, 1.0
138  store float %1, float* @e, align 4
139; ELF64: fadds
140; ELF64: stfs
141; SPE: efsadd
142; SPE: stw
143  ret void
144}
145
146define void @t12(double %v) nounwind {
147; ELF64: t12
148; SPE: t12
149  %1 = fadd double %v, 1.0
150  store double %1, double* @f, align 8
151; ELF64: fadd
152; ELF64: stfd
153; SPE: efdadd
154; SPE: evstdd
155  ret void
156}
157
158;; lwa requires an offset divisible by 4, so we need lwax here.
159define i64 @t13() nounwind {
160; ELF64: t13
161  %1 = load i32, i32* getelementptr inbounds (%struct.s, %struct.s* @g, i32 0, i32 1), align 1
162  %2 = sext i32 %1 to i64
163; ELF64: li
164; ELF64: lwax
165  %3 = add nsw i64 %2, 1
166; ELF64: addi
167  ret i64 %3
168}
169
170;; ld requires an offset divisible by 4, so we need ldx here.
171define i64 @t14() nounwind {
172; ELF64: t14
173  %1 = load i64, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1
174; ELF64: li
175; ELF64: ldx
176  %2 = add nsw i64 %1, 1
177; ELF64: addi
178  ret i64 %2
179}
180
181;; std requires an offset divisible by 4, so we need stdx here.
182define void @t15(i64 %v) nounwind {
183; ELF64: t15
184  %1 = add nsw i64 %v, 1
185  store i64 %1, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1
186; ELF64: addis
187; ELF64: addi
188; ELF64: addi
189; ELF64: li
190; ELF64: stdx
191  ret void
192}
193
194;; ld requires an offset that fits in 16 bits, so we need ldx here.
195define i64 @t16() nounwind {
196; ELF64: t16
197  %1 = load i64, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8
198; ELF64: lis
199; ELF64: ori
200; ELF64: ldx
201  %2 = add nsw i64 %1, 1
202; ELF64: addi
203  ret i64 %2
204}
205
206;; std requires an offset that fits in 16 bits, so we need stdx here.
207define void @t17(i64 %v) nounwind {
208; ELF64: t17
209  %1 = add nsw i64 %v, 1
210  store i64 %1, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8
211; ELF64: addis
212; ELF64: addi
213; ELF64: addi
214; ELF64: lis
215; ELF64: ori
216; ELF64: stdx
217  ret void
218}
219
220