• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
2
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() {
12; CHECK: ldst_8bit:
13
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() {
66; CHECK: ldst_16bit:
67
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() {
120; CHECK: ldst_32bit:
121
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() {
228; CHECK: ldst_float:
229
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() {
241; CHECK: ldst_double:
242
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}
252