1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-apple-ios -global-isel -global-isel-abort=1 | FileCheck %s
4 define dso_local void @trunc_i16_to_i8(i16 %x, ptr %p) {
5 ; CHECK-LABEL: trunc_i16_to_i8:
7 ; CHECK-NEXT: strh w0, [x1]
9 %t1 = trunc i16 %x to i8
11 %t2 = trunc i16 %sh to i8
12 store i8 %t1, ptr %p, align 1
13 %p1 = getelementptr inbounds i8, ptr %p, i64 1
14 store i8 %t2, ptr %p1, align 1
18 define dso_local void @trunc_i32_to_i8(i32 %x, ptr %p) {
19 ; CHECK-LABEL: trunc_i32_to_i8:
21 ; CHECK-NEXT: str w0, [x1]
23 %t1 = trunc i32 %x to i8
25 %t2 = trunc i32 %sh1 to i8
26 %sh2 = lshr i32 %x, 16
27 %t3 = trunc i32 %sh2 to i8
28 %sh3 = lshr i32 %x, 24
29 %t4 = trunc i32 %sh3 to i8
30 store i8 %t1, ptr %p, align 1
31 %p1 = getelementptr inbounds i8, ptr %p, i64 1
32 store i8 %t2, ptr %p1, align 1
33 %p2 = getelementptr inbounds i8, ptr %p, i64 2
34 store i8 %t3, ptr %p2, align 1
35 %p3 = getelementptr inbounds i8, ptr %p, i64 3
36 store i8 %t4, ptr %p3, align 1
40 define dso_local void @trunc_i32_to_i16(i32 %x, ptr %p) {
41 ; CHECK-LABEL: trunc_i32_to_i16:
43 ; CHECK-NEXT: str w0, [x1]
45 %t1 = trunc i32 %x to i16
47 %t2 = trunc i32 %sh to i16
48 store i16 %t1, ptr %p, align 2
49 %p1 = getelementptr inbounds i16, ptr %p, i64 1
50 store i16 %t2, ptr %p1, align 2
54 define dso_local void @be_i32_to_i16(i32 %x, ptr %p0) {
55 ; CHECK-LABEL: be_i32_to_i16:
57 ; CHECK-NEXT: ror w8, w0, #16
58 ; CHECK-NEXT: str w8, [x1]
60 %sh1 = lshr i32 %x, 16
61 %t0 = trunc i32 %x to i16
62 %t1 = trunc i32 %sh1 to i16
63 %p1 = getelementptr inbounds i16, ptr %p0, i64 1
64 store i16 %t0, ptr %p1, align 2
65 store i16 %t1, ptr %p0, align 2
69 define dso_local void @be_i32_to_i16_order(i32 %x, ptr %p0) {
70 ; CHECK-LABEL: be_i32_to_i16_order:
72 ; CHECK-NEXT: ror w8, w0, #16
73 ; CHECK-NEXT: str w8, [x1]
75 %sh1 = lshr i32 %x, 16
76 %t0 = trunc i32 %x to i16
77 %t1 = trunc i32 %sh1 to i16
78 %p1 = getelementptr inbounds i16, ptr %p0, i64 1
79 store i16 %t1, ptr %p0, align 2
80 store i16 %t0, ptr %p1, align 2
84 define dso_local void @trunc_i64_to_i8(i64 %x, ptr %p) {
85 ; CHECK-LABEL: trunc_i64_to_i8:
87 ; CHECK-NEXT: str x0, [x1]
89 %t1 = trunc i64 %x to i8
91 %t2 = trunc i64 %sh1 to i8
92 %sh2 = lshr i64 %x, 16
93 %t3 = trunc i64 %sh2 to i8
94 %sh3 = lshr i64 %x, 24
95 %t4 = trunc i64 %sh3 to i8
96 %sh4 = lshr i64 %x, 32
97 %t5 = trunc i64 %sh4 to i8
98 %sh5 = lshr i64 %x, 40
99 %t6 = trunc i64 %sh5 to i8
100 %sh6 = lshr i64 %x, 48
101 %t7 = trunc i64 %sh6 to i8
102 %sh7 = lshr i64 %x, 56
103 %t8 = trunc i64 %sh7 to i8
104 store i8 %t1, ptr %p, align 1
105 %p1 = getelementptr inbounds i8, ptr %p, i64 1
106 store i8 %t2, ptr %p1, align 1
107 %p2 = getelementptr inbounds i8, ptr %p, i64 2
108 store i8 %t3, ptr %p2, align 1
109 %p3 = getelementptr inbounds i8, ptr %p, i64 3
110 store i8 %t4, ptr %p3, align 1
111 %p4 = getelementptr inbounds i8, ptr %p, i64 4
112 store i8 %t5, ptr %p4, align 1
113 %p5 = getelementptr inbounds i8, ptr %p, i64 5
114 store i8 %t6, ptr %p5, align 1
115 %p6 = getelementptr inbounds i8, ptr %p, i64 6
116 store i8 %t7, ptr %p6, align 1
117 %p7 = getelementptr inbounds i8, ptr %p, i64 7
118 store i8 %t8, ptr %p7, align 1
122 define dso_local void @trunc_i64_to_i16(i64 %x, ptr %p) {
123 ; CHECK-LABEL: trunc_i64_to_i16:
125 ; CHECK-NEXT: str x0, [x1]
127 %t1 = trunc i64 %x to i16
128 %sh1 = lshr i64 %x, 16
129 %t2 = trunc i64 %sh1 to i16
130 %sh2 = lshr i64 %x, 32
131 %t3 = trunc i64 %sh2 to i16
132 %sh3 = lshr i64 %x, 48
133 %t4 = trunc i64 %sh3 to i16
134 store i16 %t1, ptr %p, align 2
135 %p1 = getelementptr inbounds i16, ptr %p, i64 1
136 store i16 %t2, ptr %p1, align 2
137 %p2 = getelementptr inbounds i16, ptr %p, i64 2
138 store i16 %t3, ptr %p2, align 2
139 %p3 = getelementptr inbounds i16, ptr %p, i64 3
140 store i16 %t4, ptr %p3, align 2
144 define dso_local void @trunc_i64_to_i32(i64 %x, ptr %p) {
145 ; CHECK-LABEL: trunc_i64_to_i32:
147 ; CHECK-NEXT: str x0, [x1]
149 %t1 = trunc i64 %x to i32
150 %sh = lshr i64 %x, 32
151 %t2 = trunc i64 %sh to i32
152 store i32 %t1, ptr %p, align 4
153 %p1 = getelementptr inbounds i32, ptr %p, i64 1
154 store i32 %t2, ptr %p1, align 4
157 define dso_local void @be_i64_to_i32(i64 %x, ptr %p0) {
158 ; CHECK-LABEL: be_i64_to_i32:
160 ; CHECK-NEXT: ror x8, x0, #32
161 ; CHECK-NEXT: str x8, [x1]
163 %sh1 = lshr i64 %x, 32
164 %t0 = trunc i64 %x to i32
165 %t1 = trunc i64 %sh1 to i32
166 %p1 = getelementptr inbounds i32, ptr %p0, i64 1
167 store i32 %t0, ptr %p1, align 4
168 store i32 %t1, ptr %p0, align 4
172 define dso_local void @be_i64_to_i32_order(i64 %x, ptr %p0) {
173 ; CHECK-LABEL: be_i64_to_i32_order:
175 ; CHECK-NEXT: ror x8, x0, #32
176 ; CHECK-NEXT: str x8, [x1]
178 %sh1 = lshr i64 %x, 32
179 %t0 = trunc i64 %x to i32
180 %t1 = trunc i64 %sh1 to i32
181 %p1 = getelementptr inbounds i32, ptr %p0, i64 1
182 store i32 %t1, ptr %p0, align 4
183 store i32 %t0, ptr %p1, align 4
189 define void @merge_hole(i32 %x, ptr %p) {
190 ; CHECK-LABEL: merge_hole:
192 ; CHECK-NEXT: lsr w8, w0, #16
193 ; CHECK-NEXT: strb w0, [x1]
194 ; CHECK-NEXT: strh w8, [x1, #2]
196 %p2 = getelementptr inbounds i16, ptr %p, i64 1
197 %x3 = trunc i32 %x to i8
198 store i8 %x3, ptr %p, align 1
199 %sh = lshr i32 %x, 16
200 %x01 = trunc i32 %sh to i16
201 store i16 %x01, ptr %p2, align 1
205 define void @merge_hole2(i32 %x, ptr %p) {
206 ; CHECK-LABEL: merge_hole2:
208 ; CHECK-NEXT: lsr w8, w0, #16
209 ; CHECK-NEXT: strb w0, [x1]
210 ; CHECK-NEXT: strh w8, [x1, #2]
212 %p2 = getelementptr inbounds i16, ptr %p, i64 1
213 %sh = lshr i32 %x, 16
214 %x01 = trunc i32 %sh to i16
215 store i16 %x01, ptr %p2, align 1
216 %x3 = trunc i32 %x to i8
217 store i8 %x3, ptr %p, align 1
221 define void @merge_hole3(i32 %x, ptr %p) {
222 ; CHECK-LABEL: merge_hole3:
224 ; CHECK-NEXT: lsr w8, w0, #16
225 ; CHECK-NEXT: strb w0, [x1, #1]
226 ; CHECK-NEXT: strh w8, [x1, #2]
228 %p1 = getelementptr inbounds i8, ptr %p, i64 1
229 %p2 = getelementptr inbounds i16, ptr %p, i64 1
230 %x3 = trunc i32 %x to i8
231 store i8 %x3, ptr %p1, align 1
232 %sh = lshr i32 %x, 16
233 %x01 = trunc i32 %sh to i16
234 store i16 %x01, ptr %p2, align 1
238 define void @merge_hole4(i32 %x, ptr %p) {
239 ; CHECK-LABEL: merge_hole4:
241 ; CHECK-NEXT: lsr w8, w0, #16
242 ; CHECK-NEXT: strb w0, [x1, #2]
243 ; CHECK-NEXT: strh w8, [x1]
245 %p2 = getelementptr inbounds i8, ptr %p, i64 2
246 %x3 = trunc i32 %x to i8
247 store i8 %x3, ptr %p2, align 1
248 %sh = lshr i32 %x, 16
249 %x01 = trunc i32 %sh to i16
250 store i16 %x01, ptr %p, align 1
254 define dso_local i32 @load_between_stores(i32 %x, ptr %p, ptr %ptr) {
255 ; CHECK-LABEL: load_between_stores:
257 ; CHECK-NEXT: strh w0, [x1]
258 ; CHECK-NEXT: lsr w9, w0, #16
259 ; CHECK-NEXT: ldr w8, [x2]
260 ; CHECK-NEXT: strh w9, [x1, #2]
261 ; CHECK-NEXT: mov w0, w8
263 %t1 = trunc i32 %x to i16
264 %sh = lshr i32 %x, 16
265 %t2 = trunc i32 %sh to i16
266 store i16 %t1, ptr %p, align 2
267 %ld = load i32, ptr %ptr
268 %p1 = getelementptr inbounds i16, ptr %p, i64 1
269 store i16 %t2, ptr %p1, align 2
273 define dso_local void @invalid_shift(i16 %x, ptr %p) {
274 ; CHECK-LABEL: invalid_shift:
276 ; CHECK-NEXT: ubfx w8, w0, #4, #12
277 ; CHECK-NEXT: strb w0, [x1]
278 ; CHECK-NEXT: strb w8, [x1, #1]
280 %t1 = trunc i16 %x to i8
282 %t2 = trunc i16 %sh to i8
283 store i8 %t1, ptr %p, align 1
284 %p1 = getelementptr inbounds i8, ptr %p, i64 1
285 store i8 %t2, ptr %p1, align 1
289 define dso_local void @missing_store(i32 %x, ptr %p) {
290 ; The missing store of shift 16 means we can't merge to 32 bit store,
291 ; but we can still partially merge to a 16 bit one.
292 ; CHECK-LABEL: missing_store:
294 ; CHECK-NEXT: lsr w8, w0, #24
295 ; CHECK-NEXT: strh w0, [x1]
296 ; CHECK-NEXT: strb w8, [x1, #3]
298 %t1 = trunc i32 %x to i8
299 %sh1 = lshr i32 %x, 8
300 %t2 = trunc i32 %sh1 to i8
301 %sh3 = lshr i32 %x, 24
302 %t4 = trunc i32 %sh3 to i8
303 store i8 %t1, ptr %p, align 1
304 %p1 = getelementptr inbounds i8, ptr %p, i64 1
305 store i8 %t2, ptr %p1, align 1
306 %p3 = getelementptr inbounds i8, ptr %p, i64 3
307 store i8 %t4, ptr %p3, align 1
311 define dso_local void @different_base_reg(i16 %x, ptr %p, ptr %p2) {
312 ; CHECK-LABEL: different_base_reg:
314 ; CHECK-NEXT: ubfx w8, w0, #8, #8
315 ; CHECK-NEXT: strb w0, [x1]
316 ; CHECK-NEXT: strb w8, [x2, #1]
318 %t1 = trunc i16 %x to i8
320 %t2 = trunc i16 %sh to i8
321 store i8 %t1, ptr %p, align 1
322 %p1 = getelementptr inbounds i8, ptr %p2, i64 1
323 store i8 %t2, ptr %p1, align 1
327 define dso_local void @second_store_is_volatile(i16 %x, ptr %p) {
328 ; CHECK-LABEL: second_store_is_volatile:
330 ; CHECK-NEXT: ubfx w8, w0, #8, #8
331 ; CHECK-NEXT: strb w0, [x1]
332 ; CHECK-NEXT: strb w8, [x1, #1]
334 %t1 = trunc i16 %x to i8
336 %t2 = trunc i16 %sh to i8
337 store volatile i8 %t1, ptr %p, align 1
338 %p1 = getelementptr inbounds i8, ptr %p, i64 1
339 store i8 %t2, ptr %p1, align 1
343 declare void @use_ptr(ptr)
345 define dso_local void @trunc_from_larger_src_val(i64 %hold.4.lcssa, ptr %check1792) {
346 ; Here we can merge these i8 stores into a single i32 store, but first we need
347 ; to truncate the i64 value to i32.
348 ; CHECK-LABEL: trunc_from_larger_src_val:
350 ; CHECK-NEXT: sub sp, sp, #32
351 ; CHECK-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
352 ; CHECK-NEXT: .cfi_def_cfa_offset 32
353 ; CHECK-NEXT: .cfi_offset w30, -8
354 ; CHECK-NEXT: .cfi_offset w29, -16
355 ; CHECK-NEXT: str w0, [sp, #12]
356 ; CHECK-NEXT: add x0, sp, #12
357 ; CHECK-NEXT: bl _use_ptr
358 ; CHECK-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
359 ; CHECK-NEXT: add sp, sp, #32
361 %hbuf = alloca [4 x i8], align 1
362 %arrayidx177 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 1
363 %arrayidx234 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 2
364 %arrayidx237 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 3
365 %conv227 = trunc i64 %hold.4.lcssa to i8
366 store i8 %conv227, ptr %hbuf, align 1
367 %shr229 = lshr i64 %hold.4.lcssa, 8
368 %conv230 = trunc i64 %shr229 to i8
369 store i8 %conv230, ptr %arrayidx177, align 1
370 %shr232 = lshr i64 %hold.4.lcssa, 16
371 %conv233 = trunc i64 %shr232 to i8
372 store i8 %conv233, ptr %arrayidx234, align 1
373 %shr235 = lshr i64 %hold.4.lcssa, 24
374 %conv236 = trunc i64 %shr235 to i8
375 store i8 %conv236, ptr %arrayidx237, align 1
376 call void @use_ptr(ptr noundef nonnull %hbuf)