xref: /llvm-project/llvm/test/CodeGen/ARC/ldst.ll (revision 6e8718c3e32225c579a3a974be003c7f38c32a05)
1; RUN: llc -mtriple=arc < %s | FileCheck %s
2
3; CHECK-LABEL: load32
4; CHECK: ld %r0, [%r0,16000]
5
6define i32 @load32(ptr %bp) nounwind {
7entry:
8  %gep = getelementptr i32, ptr %bp, i32 4000
9  %v = load i32, ptr %gep, align 4
10  ret i32 %v
11}
12
13; CHECK-LABEL: load16
14; CHECK: ldh %r0, [%r0,8000]
15
16define i16 @load16(ptr %bp) nounwind {
17entry:
18  %gep = getelementptr i16, ptr %bp, i32 4000
19  %v = load i16, ptr %gep, align 2
20  ret i16 %v
21}
22
23; CHECK-LABEL: load8
24; CHECK: ldb %r0, [%r0,4000]
25
26define i8 @load8(ptr %bp) nounwind {
27entry:
28  %gep = getelementptr i8, ptr %bp, i32 4000
29  %v = load i8, ptr %gep, align 1
30  ret i8 %v
31}
32
33; CHECK-LABEL: sextload16
34; CHECK: ldh.x %r0, [%r0,8000]
35
36define i32 @sextload16(ptr %bp) nounwind {
37entry:
38  %gep = getelementptr i16, ptr %bp, i32 4000
39  %vl = load i16, ptr %gep, align 2
40  %v = sext i16 %vl to i32
41  ret i32 %v
42}
43
44; CHECK-LABEL: sextload8
45; CHECK: ldb.x %r0, [%r0,4000]
46
47define i32 @sextload8(ptr %bp) nounwind {
48entry:
49  %gep = getelementptr i8, ptr %bp, i32 4000
50  %vl = load i8, ptr %gep, align 1
51  %v = sext i8 %vl to i32
52  ret i32 %v
53}
54
55; CHECK-LABEL: s_sextload16
56; CHECK: ldh.x %r0, [%r0,32]
57
58define i32 @s_sextload16(ptr %bp) nounwind {
59entry:
60  %gep = getelementptr i16, ptr %bp, i32 16
61  %vl = load i16, ptr %gep, align 2
62  %v = sext i16 %vl to i32
63  ret i32 %v
64}
65
66; CHECK-LABEL: s_sextload8
67; CHECK: ldb.x %r0, [%r0,16]
68
69define i32 @s_sextload8(ptr %bp) nounwind {
70entry:
71  %gep = getelementptr i8, ptr %bp, i32 16
72  %vl = load i8, ptr %gep, align 1
73  %v = sext i8 %vl to i32
74  ret i32 %v
75}
76
77; CHECK-LABEL: store32
78; CHECK: add %r[[REG:[0-9]+]], %r1, 16000
79; CHECK: st %r0, [%r[[REG]],0]
80
81; Long range stores (offset does not fit in s9) must be add followed by st.
82define void @store32(i32 %val, ptr %bp) nounwind {
83entry:
84  %gep = getelementptr i32, ptr %bp, i32 4000
85  store i32 %val, ptr %gep, align 4
86  ret void
87}
88
89; CHECK-LABEL: store16
90; CHECK: add %r[[REG:[0-9]+]], %r1, 8000
91; CHECK: sth %r0, [%r[[REG]],0]
92
93define void @store16(i16 zeroext %val, ptr %bp) nounwind {
94entry:
95  %gep = getelementptr i16, ptr %bp, i32 4000
96  store i16 %val, ptr %gep, align 2
97  ret void
98}
99
100; CHECK-LABEL: store8
101; CHECK: add %r[[REG:[0-9]+]], %r1, 4000
102; CHECK: stb %r0, [%r[[REG]],0]
103
104define void @store8(i8 zeroext %val, ptr %bp) nounwind {
105entry:
106  %gep = getelementptr i8, ptr %bp, i32 4000
107  store i8 %val, ptr %gep, align 1
108  ret void
109}
110
111; Short range stores can be done with [reg, s9].
112; CHECK-LABEL: s_store32
113; CHECK-NOT: add
114; CHECK: st %r0, [%r1,64]
115define void @s_store32(i32 %val, ptr %bp) nounwind {
116entry:
117  %gep = getelementptr i32, ptr %bp, i32 16
118  store i32 %val, ptr %gep, align 4
119  ret void
120}
121
122; CHECK-LABEL: s_store16
123; CHECK-NOT: add
124; CHECK: sth %r0, [%r1,32]
125define void @s_store16(i16 zeroext %val, ptr %bp) nounwind {
126entry:
127  %gep = getelementptr i16, ptr %bp, i32 16
128  store i16 %val, ptr %gep, align 2
129  ret void
130}
131
132; CHECK-LABEL: s_store8
133; CHECK-NOT: add
134; CHECK: stb %r0, [%r1,16]
135define void @s_store8(i8 zeroext %val, ptr %bp) nounwind {
136entry:
137  %gep = getelementptr i8, ptr %bp, i32 16
138  store i8 %val, ptr %gep, align 1
139  ret void
140}
141
142
143@aaaa = internal global [128 x i32] zeroinitializer
144@bbbb = internal global [128 x i16] zeroinitializer
145@cccc = internal global [128 x i8]  zeroinitializer
146
147; CHECK-LABEL: g_store32
148; CHECK-NOT: add
149; CHECK: st %r0, [@aaaa+64]
150define void @g_store32(i32 %val) nounwind {
151entry:
152  store i32 %val, ptr getelementptr inbounds ([128 x i32], ptr @aaaa, i32 0, i32 16), align 4
153  ret void
154}
155
156; CHECK-LABEL: g_load32
157; CHECK-NOT: add
158; CHECK: ld %r0, [@aaaa+64]
159define i32 @g_load32() nounwind {
160  %gep = getelementptr inbounds [128 x i32], ptr @aaaa, i32 0, i32 16
161  %v = load i32, ptr %gep, align 4
162  ret i32 %v
163}
164
165; CHECK-LABEL: g_store16
166; CHECK-NOT: add
167; CHECK: sth %r0, [@bbbb+32]
168define void @g_store16(i16 %val) nounwind {
169entry:
170  store i16 %val, ptr getelementptr inbounds ([128 x i16], ptr @bbbb, i16 0, i16 16), align 2
171  ret void
172}
173
174; CHECK-LABEL: g_load16
175; CHECK-NOT: add
176; CHECK: ldh %r0, [@bbbb+32]
177define i16 @g_load16() nounwind {
178  %gep = getelementptr inbounds [128 x i16], ptr @bbbb, i16 0, i16 16
179  %v = load i16, ptr %gep, align 2
180  ret i16 %v
181}
182
183; CHECK-LABEL: g_store8
184; CHECK-NOT: add
185; CHECK: stb %r0, [@cccc+16]
186define void @g_store8(i8 %val) nounwind {
187entry:
188  store i8 %val, ptr getelementptr inbounds ([128 x i8], ptr @cccc, i8 0, i8 16), align 1
189  ret void
190}
191
192; CHECK-LABEL: g_load8
193; CHECK-NOT: add
194; CHECK: ldb %r0, [@cccc+16]
195define i8 @g_load8() nounwind {
196  %gep = getelementptr inbounds [128 x i8], ptr @cccc, i8 0, i8 16
197  %v = load i8, ptr %gep, align 1
198  ret i8 %v
199}
200
201; CHECK-LABEL: align2_load32
202; CHECK-DAG: ldh %r[[REG0:[0-9]+]], [%r0,0]
203; CHECK-DAG: ldh %r[[REG1:[0-9]+]], [%r0,2]
204; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 16
205define i32 @align2_load32(ptr %p) nounwind {
206entry:
207  %bp = bitcast ptr %p to ptr
208  %v = load i32, ptr %bp, align 2
209  ret i32 %v
210}
211
212; CHECK-LABEL: align1_load32
213; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0]
214; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1]
215; CHECK-DAG: ldb %r[[REG2:[0-9]+]], [%r0,2]
216; CHECK-DAG: ldb %r[[REG3:[0-9]+]], [%r0,3]
217; CHECK-DAG: asl %r[[AREG1:[0-9]+]], %r[[REG1]], 8
218; CHECK-DAG: asl %r[[AREG2:[0-9]+]], %r[[REG2]], 16
219; CHECK-DAG: asl %r[[AREG3:[0-9]+]], %r[[REG3]], 24
220; CHECK-DAG: or %r[[AREG01:[0-9]+]], %r[[AREG1]], %r[[REG0]]
221; CHECK-DAG: or %r[[AREG23:[0-9]+]], %r[[AREG3]], %r[[AREG2]]
222; CHECK-DAG: or %r0, %r[[AREG23]], %r[[AREG01]]
223define i32 @align1_load32(ptr %p) nounwind {
224entry:
225  %bp = bitcast ptr %p to ptr
226  %v = load i32, ptr %bp, align 1
227  ret i32 %v
228}
229
230; CHECK-LABEL: align1_load16
231; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0]
232; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1]
233; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 8
234define i16 @align1_load16(ptr %p) nounwind {
235entry:
236  %bp = bitcast ptr %p to ptr
237  %v = load i16, ptr %bp, align 1
238  ret i16 %v
239}
240
241; CHECK-LABEL: align2_store32
242; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 16
243; CHECK-DAG: sth %r1, [%r0,0]
244; CHECK-DAG: sth %r[[REG:[0-9]+]], [%r0,2]
245define void @align2_store32(ptr %p, i32 %v) nounwind {
246entry:
247  %bp = bitcast ptr %p to ptr
248  store i32 %v, ptr %bp, align 2
249  ret void
250}
251
252; CHECK-LABEL: align1_store16
253; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 8
254; CHECK-DAG: stb %r1, [%r0,0]
255; CHECK-DAG: stb %r[[REG:[0-9]+]], [%r0,1]
256define void @align1_store16(ptr %p, i16 %v) nounwind {
257entry:
258  %bp = bitcast ptr %p to ptr
259  store i16 %v, ptr %bp, align 1
260  ret void
261}
262
263; CHECK-LABEL: align1_store32
264; CHECK-DAG: lsr %r[[REG0:[0-9]+]], %r1, 8
265; CHECK-DAG: lsr %r[[REG1:[0-9]+]], %r1, 16
266; CHECK-DAG: lsr %r[[REG2:[0-9]+]], %r1, 24
267; CHECK-DAG: stb %r1, [%r0,0]
268; CHECK-DAG: stb %r[[REG0]], [%r0,1]
269; CHECK-DAG: stb %r[[REG1]], [%r0,2]
270; CHECK-DAG: stb %r[[REG2]], [%r0,3]
271define void @align1_store32(ptr %p, i32 %v) nounwind {
272entry:
273  %bp = bitcast ptr %p to ptr
274  store i32 %v, ptr %bp, align 1
275  ret void
276}
277