blob: 77cef4eea0dbb125f25b2db6c5ba4cbb7687d660 [file] [log] [blame]
Tim Northovere3d42362013-02-01 11:40:47 +00001; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
Tim Northovere0e3aef2013-01-31 12:12:40 +00002
3@var_8bit = global i8 0
4@var_16bit = global i16 0
5@var_32bit = global i32 0
6@var_64bit = global i64 0
7
8@var_float = global float 0.0
9@var_double = global double 0.0
10
11define void @ldst_8bit() {
Stephen Lind24ab202013-07-14 06:24:09 +000012; CHECK-LABEL: ldst_8bit:
Tim Northovere0e3aef2013-01-31 12:12:40 +000013
14; No architectural support for loads to 16-bit or 8-bit since we
15; promote i8 during lowering.
16
17; match a sign-extending load 8-bit -> 32-bit
18 %val8_sext32 = load volatile i8* @var_8bit
19 %val32_signed = sext i8 %val8_sext32 to i32
20 store volatile i32 %val32_signed, i32* @var_32bit
21; CHECK: adrp {{x[0-9]+}}, var_8bit
22; CHECK: ldrsb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
23
24; match a zero-extending load volatile 8-bit -> 32-bit
25 %val8_zext32 = load volatile i8* @var_8bit
26 %val32_unsigned = zext i8 %val8_zext32 to i32
27 store volatile i32 %val32_unsigned, i32* @var_32bit
28; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
29
30; match an any-extending load volatile 8-bit -> 32-bit
31 %val8_anyext = load volatile i8* @var_8bit
32 %newval8 = add i8 %val8_anyext, 1
33 store volatile i8 %newval8, i8* @var_8bit
34; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
35
36; match a sign-extending load volatile 8-bit -> 64-bit
37 %val8_sext64 = load volatile i8* @var_8bit
38 %val64_signed = sext i8 %val8_sext64 to i64
39 store volatile i64 %val64_signed, i64* @var_64bit
40; CHECK: ldrsb {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
41
42; match a zero-extending load volatile 8-bit -> 64-bit.
43; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
44; of x0 so it's identical to load volatileing to 32-bits.
45 %val8_zext64 = load volatile i8* @var_8bit
46 %val64_unsigned = zext i8 %val8_zext64 to i64
47 store volatile i64 %val64_unsigned, i64* @var_64bit
48; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
49
50; truncating store volatile 32-bits to 8-bits
51 %val32 = load volatile i32* @var_32bit
52 %val8_trunc32 = trunc i32 %val32 to i8
53 store volatile i8 %val8_trunc32, i8* @var_8bit
54; CHECK: strb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
55
56; truncating store volatile 64-bits to 8-bits
57 %val64 = load volatile i64* @var_64bit
58 %val8_trunc64 = trunc i64 %val64 to i8
59 store volatile i8 %val8_trunc64, i8* @var_8bit
60; CHECK: strb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
61
62 ret void
63}
64
65define void @ldst_16bit() {
Stephen Lind24ab202013-07-14 06:24:09 +000066; CHECK-LABEL: ldst_16bit:
Tim Northovere0e3aef2013-01-31 12:12:40 +000067
68; No architectural support for load volatiles to 16-bit promote i16 during
69; lowering.
70
71; match a sign-extending load volatile 16-bit -> 32-bit
72 %val16_sext32 = load volatile i16* @var_16bit
73 %val32_signed = sext i16 %val16_sext32 to i32
74 store volatile i32 %val32_signed, i32* @var_32bit
75; CHECK: adrp {{x[0-9]+}}, var_16bit
76; CHECK: ldrsh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
77
78; match a zero-extending load volatile 16-bit -> 32-bit
79 %val16_zext32 = load volatile i16* @var_16bit
80 %val32_unsigned = zext i16 %val16_zext32 to i32
81 store volatile i32 %val32_unsigned, i32* @var_32bit
82; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
83
84; match an any-extending load volatile 16-bit -> 32-bit
85 %val16_anyext = load volatile i16* @var_16bit
86 %newval16 = add i16 %val16_anyext, 1
87 store volatile i16 %newval16, i16* @var_16bit
88; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
89
90; match a sign-extending load volatile 16-bit -> 64-bit
91 %val16_sext64 = load volatile i16* @var_16bit
92 %val64_signed = sext i16 %val16_sext64 to i64
93 store volatile i64 %val64_signed, i64* @var_64bit
94; CHECK: ldrsh {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
95
96; match a zero-extending load volatile 16-bit -> 64-bit.
97; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
98; of x0 so it's identical to load volatileing to 32-bits.
99 %val16_zext64 = load volatile i16* @var_16bit
100 %val64_unsigned = zext i16 %val16_zext64 to i64
101 store volatile i64 %val64_unsigned, i64* @var_64bit
102; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
103
104; truncating store volatile 32-bits to 16-bits
105 %val32 = load volatile i32* @var_32bit
106 %val16_trunc32 = trunc i32 %val32 to i16
107 store volatile i16 %val16_trunc32, i16* @var_16bit
108; CHECK: strh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
109
110; truncating store volatile 64-bits to 16-bits
111 %val64 = load volatile i64* @var_64bit
112 %val16_trunc64 = trunc i64 %val64 to i16
113 store volatile i16 %val16_trunc64, i16* @var_16bit
114; CHECK: strh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
115
116 ret void
117}
118
119define void @ldst_32bit() {
Stephen Lind24ab202013-07-14 06:24:09 +0000120; CHECK-LABEL: ldst_32bit:
Tim Northovere0e3aef2013-01-31 12:12:40 +0000121
122; Straight 32-bit load/store
123 %val32_noext = load volatile i32* @var_32bit
124 store volatile i32 %val32_noext, i32* @var_32bit
125; CHECK: adrp {{x[0-9]+}}, var_32bit
126; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
127; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
128
129; Zero-extension to 64-bits
130 %val32_zext = load volatile i32* @var_32bit
131 %val64_unsigned = zext i32 %val32_zext to i64
132 store volatile i64 %val64_unsigned, i64* @var_64bit
133; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
134; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
135
136; Sign-extension to 64-bits
137 %val32_sext = load volatile i32* @var_32bit
138 %val64_signed = sext i32 %val32_sext to i64
139 store volatile i64 %val64_signed, i64* @var_64bit
140; CHECK: ldrsw {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
141; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
142
143; Truncation from 64-bits
144 %val64_trunc = load volatile i64* @var_64bit
145 %val32_trunc = trunc i64 %val64_trunc to i32
146 store volatile i32 %val32_trunc, i32* @var_32bit
147; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
148; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
149
150 ret void
151}
152
153@arr8 = global i8* null
154@arr16 = global i16* null
155@arr32 = global i32* null
156@arr64 = global i64* null
157
158; Now check that our selection copes with accesses more complex than a
159; single symbol. Permitted offsets should be folded into the loads and
160; stores. Since all forms use the same Operand it's only necessary to
161; check the various access-sizes involved.
162
163define void @ldst_complex_offsets() {
164; CHECK: ldst_complex_offsets
165 %arr8_addr = load volatile i8** @arr8
166; CHECK: adrp {{x[0-9]+}}, arr8
167; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr8]
168
169 %arr8_sub1_addr = getelementptr i8* %arr8_addr, i64 1
170 %arr8_sub1 = load volatile i8* %arr8_sub1_addr
171 store volatile i8 %arr8_sub1, i8* @var_8bit
172; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #1]
173
174 %arr8_sub4095_addr = getelementptr i8* %arr8_addr, i64 4095
175 %arr8_sub4095 = load volatile i8* %arr8_sub4095_addr
176 store volatile i8 %arr8_sub4095, i8* @var_8bit
177; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #4095]
178
179
180 %arr16_addr = load volatile i16** @arr16
181; CHECK: adrp {{x[0-9]+}}, arr16
182; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr16]
183
184 %arr16_sub1_addr = getelementptr i16* %arr16_addr, i64 1
185 %arr16_sub1 = load volatile i16* %arr16_sub1_addr
186 store volatile i16 %arr16_sub1, i16* @var_16bit
187; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #2]
188
189 %arr16_sub4095_addr = getelementptr i16* %arr16_addr, i64 4095
190 %arr16_sub4095 = load volatile i16* %arr16_sub4095_addr
191 store volatile i16 %arr16_sub4095, i16* @var_16bit
192; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #8190]
193
194
195 %arr32_addr = load volatile i32** @arr32
196; CHECK: adrp {{x[0-9]+}}, arr32
197; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr32]
198
199 %arr32_sub1_addr = getelementptr i32* %arr32_addr, i64 1
200 %arr32_sub1 = load volatile i32* %arr32_sub1_addr
201 store volatile i32 %arr32_sub1, i32* @var_32bit
202; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #4]
203
204 %arr32_sub4095_addr = getelementptr i32* %arr32_addr, i64 4095
205 %arr32_sub4095 = load volatile i32* %arr32_sub4095_addr
206 store volatile i32 %arr32_sub4095, i32* @var_32bit
207; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #16380]
208
209
210 %arr64_addr = load volatile i64** @arr64
211; CHECK: adrp {{x[0-9]+}}, arr64
212; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr64]
213
214 %arr64_sub1_addr = getelementptr i64* %arr64_addr, i64 1
215 %arr64_sub1 = load volatile i64* %arr64_sub1_addr
216 store volatile i64 %arr64_sub1, i64* @var_64bit
217; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #8]
218
219 %arr64_sub4095_addr = getelementptr i64* %arr64_addr, i64 4095
220 %arr64_sub4095 = load volatile i64* %arr64_sub4095_addr
221 store volatile i64 %arr64_sub4095, i64* @var_64bit
222; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #32760]
223
224 ret void
225}
226
227define void @ldst_float() {
Stephen Lind24ab202013-07-14 06:24:09 +0000228; CHECK-LABEL: ldst_float:
Tim Northovere0e3aef2013-01-31 12:12:40 +0000229
230 %valfp = load volatile float* @var_float
231; CHECK: adrp {{x[0-9]+}}, var_float
232; CHECK: ldr {{s[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_float]
233
234 store volatile float %valfp, float* @var_float
235; CHECK: str {{s[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_float]
236
237 ret void
238}
239
240define void @ldst_double() {
Stephen Lind24ab202013-07-14 06:24:09 +0000241; CHECK-LABEL: ldst_double:
Tim Northovere0e3aef2013-01-31 12:12:40 +0000242
243 %valfp = load volatile double* @var_double
244; CHECK: adrp {{x[0-9]+}}, var_double
245; CHECK: ldr {{d[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_double]
246
247 store volatile double %valfp, double* @var_double
248; CHECK: str {{d[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_double]
249
250 ret void
251}