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