1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s
3
4%structTy = type { i8, i32, i32 }
5
6@e = common global %structTy zeroinitializer, align 4
7
8;; Ensure that MergeConsecutiveStores doesn't incorrectly reorder
9;; store operations.  The first test stores in increasing address
10;; order, the second in decreasing -- but in both cases should have
11;; the same result in memory in the end.
12
13define void @redundant_stores_merging() {
14; CHECK-LABEL: redundant_stores_merging:
15; CHECK:       # %bb.0:
16; CHECK-NEXT:    movabsq $1958505086977, %rax # imm = 0x1C800000001
17; CHECK-NEXT:    movq %rax, e+{{.*}}(%rip)
18; CHECK-NEXT:    retq
19  store i32 1, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 1), align 4
20  store i32 123, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 2), align 4
21  store i32 456, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 2), align 4
22  ret void
23}
24
25;; This variant tests PR25154.
26define void @redundant_stores_merging_reverse() {
27; CHECK-LABEL: redundant_stores_merging_reverse:
28; CHECK:       # %bb.0:
29; CHECK-NEXT:    movabsq $528280977409, %rax # imm = 0x7B00000001
30; CHECK-NEXT:    movq %rax, e+{{.*}}(%rip)
31; CHECK-NEXT:    movl $456, e+{{.*}}(%rip) # imm = 0x1C8
32; CHECK-NEXT:    retq
33  store i32 123, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 2), align 4
34  store i32 456, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 2), align 4
35  store i32 1, i32* getelementptr inbounds (%structTy, %structTy* @e, i64 0, i32 1), align 4
36  ret void
37}
38
39@b = common global [8 x i8] zeroinitializer, align 2
40
41;; The 2-byte store to offset 3 overlaps the 2-byte store to offset 2;
42;; these must not be reordered in MergeConsecutiveStores such that the
43;; store to 3 comes first (e.g. by merging the stores to 0 and 2 into
44;; a movl, after the store to 3).
45
46define void @overlapping_stores_merging() {
47; CHECK-LABEL: overlapping_stores_merging:
48; CHECK:       # %bb.0:
49; CHECK-NEXT:    movl $1, {{.*}}(%rip)
50; CHECK-NEXT:    movw $2, b+{{.*}}(%rip)
51; CHECK-NEXT:    retq
52  store i16 0, i16* bitcast (i8* getelementptr inbounds ([8 x i8], [8 x i8]* @b, i64 0, i64 2) to i16*), align 2
53  store i16 2, i16* bitcast (i8* getelementptr inbounds ([8 x i8], [8 x i8]* @b, i64 0, i64 3) to i16*), align 1
54  store i16 1, i16* bitcast (i8* getelementptr inbounds ([8 x i8], [8 x i8]* @b, i64 0, i64 0) to i16*), align 2
55  ret void
56}
57
58define void @extract_vector_store_16_consecutive_bytes(<2 x i64> %v, i8* %ptr) #0 {
59; CHECK-LABEL: extract_vector_store_16_consecutive_bytes:
60; CHECK:       # %bb.0:
61; CHECK-NEXT:    vmovups %xmm0, (%rdi)
62; CHECK-NEXT:    retq
63  %bc = bitcast <2 x i64> %v to <16 x i8>
64  %ext00 = extractelement <16 x i8> %bc, i32 0
65  %ext01 = extractelement <16 x i8> %bc, i32 1
66  %ext02 = extractelement <16 x i8> %bc, i32 2
67  %ext03 = extractelement <16 x i8> %bc, i32 3
68  %ext04 = extractelement <16 x i8> %bc, i32 4
69  %ext05 = extractelement <16 x i8> %bc, i32 5
70  %ext06 = extractelement <16 x i8> %bc, i32 6
71  %ext07 = extractelement <16 x i8> %bc, i32 7
72  %ext08 = extractelement <16 x i8> %bc, i32 8
73  %ext09 = extractelement <16 x i8> %bc, i32 9
74  %ext10 = extractelement <16 x i8> %bc, i32 10
75  %ext11 = extractelement <16 x i8> %bc, i32 11
76  %ext12 = extractelement <16 x i8> %bc, i32 12
77  %ext13 = extractelement <16 x i8> %bc, i32 13
78  %ext14 = extractelement <16 x i8> %bc, i32 14
79  %ext15 = extractelement <16 x i8> %bc, i32 15
80  %gep00 = getelementptr inbounds i8, i8* %ptr, i64 0
81  %gep01 = getelementptr inbounds i8, i8* %ptr, i64 1
82  %gep02 = getelementptr inbounds i8, i8* %ptr, i64 2
83  %gep03 = getelementptr inbounds i8, i8* %ptr, i64 3
84  %gep04 = getelementptr inbounds i8, i8* %ptr, i64 4
85  %gep05 = getelementptr inbounds i8, i8* %ptr, i64 5
86  %gep06 = getelementptr inbounds i8, i8* %ptr, i64 6
87  %gep07 = getelementptr inbounds i8, i8* %ptr, i64 7
88  %gep08 = getelementptr inbounds i8, i8* %ptr, i64 8
89  %gep09 = getelementptr inbounds i8, i8* %ptr, i64 9
90  %gep10 = getelementptr inbounds i8, i8* %ptr, i64 10
91  %gep11 = getelementptr inbounds i8, i8* %ptr, i64 11
92  %gep12 = getelementptr inbounds i8, i8* %ptr, i64 12
93  %gep13 = getelementptr inbounds i8, i8* %ptr, i64 13
94  %gep14 = getelementptr inbounds i8, i8* %ptr, i64 14
95  %gep15 = getelementptr inbounds i8, i8* %ptr, i64 15
96  store i8 %ext00, i8* %gep00, align 1
97  store i8 %ext01, i8* %gep01, align 1
98  store i8 %ext02, i8* %gep02, align 1
99  store i8 %ext03, i8* %gep03, align 1
100  store i8 %ext04, i8* %gep04, align 1
101  store i8 %ext05, i8* %gep05, align 1
102  store i8 %ext06, i8* %gep06, align 1
103  store i8 %ext07, i8* %gep07, align 1
104  store i8 %ext08, i8* %gep08, align 1
105  store i8 %ext09, i8* %gep09, align 1
106  store i8 %ext10, i8* %gep10, align 1
107  store i8 %ext11, i8* %gep11, align 1
108  store i8 %ext12, i8* %gep12, align 1
109  store i8 %ext13, i8* %gep13, align 1
110  store i8 %ext14, i8* %gep14, align 1
111  store i8 %ext15, i8* %gep15, align 1
112  ret void
113}
114
115; PR34217 - https://bugs.llvm.org/show_bug.cgi?id=34217
116
117define void @extract_vector_store_32_consecutive_bytes(<4 x i64> %v, i8* %ptr) #0 {
118; CHECK-LABEL: extract_vector_store_32_consecutive_bytes:
119; CHECK:       # %bb.0:
120; CHECK-NEXT:    vmovups %ymm0, (%rdi)
121; CHECK-NEXT:    vzeroupper
122; CHECK-NEXT:    retq
123  %bc = bitcast <4 x i64> %v to <32 x i8>
124  %ext00 = extractelement <32 x i8> %bc, i32 0
125  %ext01 = extractelement <32 x i8> %bc, i32 1
126  %ext02 = extractelement <32 x i8> %bc, i32 2
127  %ext03 = extractelement <32 x i8> %bc, i32 3
128  %ext04 = extractelement <32 x i8> %bc, i32 4
129  %ext05 = extractelement <32 x i8> %bc, i32 5
130  %ext06 = extractelement <32 x i8> %bc, i32 6
131  %ext07 = extractelement <32 x i8> %bc, i32 7
132  %ext08 = extractelement <32 x i8> %bc, i32 8
133  %ext09 = extractelement <32 x i8> %bc, i32 9
134  %ext10 = extractelement <32 x i8> %bc, i32 10
135  %ext11 = extractelement <32 x i8> %bc, i32 11
136  %ext12 = extractelement <32 x i8> %bc, i32 12
137  %ext13 = extractelement <32 x i8> %bc, i32 13
138  %ext14 = extractelement <32 x i8> %bc, i32 14
139  %ext15 = extractelement <32 x i8> %bc, i32 15
140  %ext16 = extractelement <32 x i8> %bc, i32 16
141  %ext17 = extractelement <32 x i8> %bc, i32 17
142  %ext18 = extractelement <32 x i8> %bc, i32 18
143  %ext19 = extractelement <32 x i8> %bc, i32 19
144  %ext20 = extractelement <32 x i8> %bc, i32 20
145  %ext21 = extractelement <32 x i8> %bc, i32 21
146  %ext22 = extractelement <32 x i8> %bc, i32 22
147  %ext23 = extractelement <32 x i8> %bc, i32 23
148  %ext24 = extractelement <32 x i8> %bc, i32 24
149  %ext25 = extractelement <32 x i8> %bc, i32 25
150  %ext26 = extractelement <32 x i8> %bc, i32 26
151  %ext27 = extractelement <32 x i8> %bc, i32 27
152  %ext28 = extractelement <32 x i8> %bc, i32 28
153  %ext29 = extractelement <32 x i8> %bc, i32 29
154  %ext30 = extractelement <32 x i8> %bc, i32 30
155  %ext31 = extractelement <32 x i8> %bc, i32 31
156  %gep00 = getelementptr inbounds i8, i8* %ptr, i64 0
157  %gep01 = getelementptr inbounds i8, i8* %ptr, i64 1
158  %gep02 = getelementptr inbounds i8, i8* %ptr, i64 2
159  %gep03 = getelementptr inbounds i8, i8* %ptr, i64 3
160  %gep04 = getelementptr inbounds i8, i8* %ptr, i64 4
161  %gep05 = getelementptr inbounds i8, i8* %ptr, i64 5
162  %gep06 = getelementptr inbounds i8, i8* %ptr, i64 6
163  %gep07 = getelementptr inbounds i8, i8* %ptr, i64 7
164  %gep08 = getelementptr inbounds i8, i8* %ptr, i64 8
165  %gep09 = getelementptr inbounds i8, i8* %ptr, i64 9
166  %gep10 = getelementptr inbounds i8, i8* %ptr, i64 10
167  %gep11 = getelementptr inbounds i8, i8* %ptr, i64 11
168  %gep12 = getelementptr inbounds i8, i8* %ptr, i64 12
169  %gep13 = getelementptr inbounds i8, i8* %ptr, i64 13
170  %gep14 = getelementptr inbounds i8, i8* %ptr, i64 14
171  %gep15 = getelementptr inbounds i8, i8* %ptr, i64 15
172  %gep16 = getelementptr inbounds i8, i8* %ptr, i64 16
173  %gep17 = getelementptr inbounds i8, i8* %ptr, i64 17
174  %gep18 = getelementptr inbounds i8, i8* %ptr, i64 18
175  %gep19 = getelementptr inbounds i8, i8* %ptr, i64 19
176  %gep20 = getelementptr inbounds i8, i8* %ptr, i64 20
177  %gep21 = getelementptr inbounds i8, i8* %ptr, i64 21
178  %gep22 = getelementptr inbounds i8, i8* %ptr, i64 22
179  %gep23 = getelementptr inbounds i8, i8* %ptr, i64 23
180  %gep24 = getelementptr inbounds i8, i8* %ptr, i64 24
181  %gep25 = getelementptr inbounds i8, i8* %ptr, i64 25
182  %gep26 = getelementptr inbounds i8, i8* %ptr, i64 26
183  %gep27 = getelementptr inbounds i8, i8* %ptr, i64 27
184  %gep28 = getelementptr inbounds i8, i8* %ptr, i64 28
185  %gep29 = getelementptr inbounds i8, i8* %ptr, i64 29
186  %gep30 = getelementptr inbounds i8, i8* %ptr, i64 30
187  %gep31 = getelementptr inbounds i8, i8* %ptr, i64 31
188  store i8 %ext00, i8* %gep00, align 1
189  store i8 %ext01, i8* %gep01, align 1
190  store i8 %ext02, i8* %gep02, align 1
191  store i8 %ext03, i8* %gep03, align 1
192  store i8 %ext04, i8* %gep04, align 1
193  store i8 %ext05, i8* %gep05, align 1
194  store i8 %ext06, i8* %gep06, align 1
195  store i8 %ext07, i8* %gep07, align 1
196  store i8 %ext08, i8* %gep08, align 1
197  store i8 %ext09, i8* %gep09, align 1
198  store i8 %ext10, i8* %gep10, align 1
199  store i8 %ext11, i8* %gep11, align 1
200  store i8 %ext12, i8* %gep12, align 1
201  store i8 %ext13, i8* %gep13, align 1
202  store i8 %ext14, i8* %gep14, align 1
203  store i8 %ext15, i8* %gep15, align 1
204  store i8 %ext16, i8* %gep16, align 1
205  store i8 %ext17, i8* %gep17, align 1
206  store i8 %ext18, i8* %gep18, align 1
207  store i8 %ext19, i8* %gep19, align 1
208  store i8 %ext20, i8* %gep20, align 1
209  store i8 %ext21, i8* %gep21, align 1
210  store i8 %ext22, i8* %gep22, align 1
211  store i8 %ext23, i8* %gep23, align 1
212  store i8 %ext24, i8* %gep24, align 1
213  store i8 %ext25, i8* %gep25, align 1
214  store i8 %ext26, i8* %gep26, align 1
215  store i8 %ext27, i8* %gep27, align 1
216  store i8 %ext28, i8* %gep28, align 1
217  store i8 %ext29, i8* %gep29, align 1
218  store i8 %ext30, i8* %gep30, align 1
219  store i8 %ext31, i8* %gep31, align 1
220  ret void
221}
222
223; https://bugs.llvm.org/show_bug.cgi?id=43446
224define void @pr43446_0(i64 %x) {
225; CHECK-LABEL: pr43446_0:
226; CHECK:       # %bb.0:
227; CHECK-NEXT:    movb $1, (%rdi)
228; CHECK-NEXT:    retq
229  %a = inttoptr i64 %x to i8*
230  store i8 -2, i8* %a, align 1
231  %b = inttoptr i64 %x to i1*
232  store i1 true, i1* %b, align 1
233  ret void
234}
235define void @pr43446_1(i8* %a) {
236; CHECK-LABEL: pr43446_1:
237; CHECK:       # %bb.0:
238; CHECK-NEXT:    movb $1, (%rdi)
239; CHECK-NEXT:    retq
240  store i8 -2, i8* %a, align 1
241  %b = bitcast i8* %a to i1*
242  store i1 true, i1* %b, align 1
243  ret void
244}
245
246define void @rotate16_in_place(i8* %p) {
247; CHECK-LABEL: rotate16_in_place:
248; CHECK:       # %bb.0:
249; CHECK-NEXT:    rolw $8, (%rdi)
250; CHECK-NEXT:    retq
251  %p0 = getelementptr i8, i8* %p, i64 0
252  %p1 = getelementptr i8, i8* %p, i64 1
253  %i0 = load i8, i8* %p0, align 1
254  %i1 = load i8, i8* %p1, align 1
255  store i8 %i1, i8* %p0, align 1
256  store i8 %i0, i8* %p1, align 1
257  ret void
258}
259
260define void @rotate16(i8* %p, i8* %q) {
261; CHECK-LABEL: rotate16:
262; CHECK:       # %bb.0:
263; CHECK-NEXT:    movzwl (%rdi), %eax
264; CHECK-NEXT:    rolw $8, %ax
265; CHECK-NEXT:    movw %ax, (%rsi)
266; CHECK-NEXT:    retq
267  %p0 = getelementptr i8, i8* %p, i64 0
268  %p1 = getelementptr i8, i8* %p, i64 1
269  %q0 = getelementptr i8, i8* %q, i64 0
270  %q1 = getelementptr i8, i8* %q, i64 1
271  %i0 = load i8, i8* %p0, align 1
272  %i1 = load i8, i8* %p1, align 1
273  store i8 %i1, i8* %q0, align 1
274  store i8 %i0, i8* %q1, align 1
275  ret void
276}
277
278define void @rotate32_in_place(i16* %p) {
279; CHECK-LABEL: rotate32_in_place:
280; CHECK:       # %bb.0:
281; CHECK-NEXT:    roll $16, (%rdi)
282; CHECK-NEXT:    retq
283  %p0 = getelementptr i16, i16* %p, i64 0
284  %p1 = getelementptr i16, i16* %p, i64 1
285  %i0 = load i16, i16* %p0, align 2
286  %i1 = load i16, i16* %p1, align 2
287  store i16 %i1, i16* %p0, align 2
288  store i16 %i0, i16* %p1, align 2
289  ret void
290}
291
292define void @rotate32(i16* %p) {
293; CHECK-LABEL: rotate32:
294; CHECK:       # %bb.0:
295; CHECK-NEXT:    movl (%rdi), %eax
296; CHECK-NEXT:    roll $16, %eax
297; CHECK-NEXT:    movl %eax, 84(%rdi)
298; CHECK-NEXT:    retq
299  %p0 = getelementptr i16, i16* %p, i64 0
300  %p1 = getelementptr i16, i16* %p, i64 1
301  %p42 = getelementptr i16, i16* %p, i64 42
302  %p43 = getelementptr i16, i16* %p, i64 43
303  %i0 = load i16, i16* %p0, align 2
304  %i1 = load i16, i16* %p1, align 2
305  store i16 %i1, i16* %p42, align 2
306  store i16 %i0, i16* %p43, align 2
307  ret void
308}
309
310define void @rotate64_in_place(i32* %p) {
311; CHECK-LABEL: rotate64_in_place:
312; CHECK:       # %bb.0:
313; CHECK-NEXT:    rolq $32, (%rdi)
314; CHECK-NEXT:    retq
315  %p0 = getelementptr i32, i32* %p, i64 0
316  %p1 = getelementptr i32, i32* %p, i64 1
317  %i0 = load i32, i32* %p0, align 4
318  %i1 = load i32, i32* %p1, align 4
319  store i32 %i1, i32* %p0, align 4
320  store i32 %i0, i32* %p1, align 4
321  ret void
322}
323
324define void @rotate64(i32* %p) {
325; CHECK-LABEL: rotate64:
326; CHECK:       # %bb.0:
327; CHECK-NEXT:    movq (%rdi), %rax
328; CHECK-NEXT:    rolq $32, %rax
329; CHECK-NEXT:    movq %rax, 8(%rdi)
330; CHECK-NEXT:    retq
331  %p0 = getelementptr i32, i32* %p, i64 0
332  %p1 = getelementptr i32, i32* %p, i64 1
333  %p2 = getelementptr i32, i32* %p, i64 2
334  %p3 = getelementptr i32, i32* %p, i64 3
335  %i0 = load i32, i32* %p0, align 4
336  %i1 = load i32, i32* %p1, align 4
337  store i32 %i1, i32* %p2, align 4
338  store i32 %i0, i32* %p3, align 4
339  ret void
340}
341
342define void @rotate64_iterate(i16* %p) {
343; CHECK-LABEL: rotate64_iterate:
344; CHECK:       # %bb.0:
345; CHECK-NEXT:    movq (%rdi), %rax
346; CHECK-NEXT:    rolq $32, %rax
347; CHECK-NEXT:    movq %rax, 84(%rdi)
348; CHECK-NEXT:    retq
349  %p0 = getelementptr i16, i16* %p, i64 0
350  %p1 = getelementptr i16, i16* %p, i64 1
351  %p2 = getelementptr i16, i16* %p, i64 2
352  %p3 = getelementptr i16, i16* %p, i64 3
353  %p42 = getelementptr i16, i16* %p, i64 42
354  %p43 = getelementptr i16, i16* %p, i64 43
355  %p44 = getelementptr i16, i16* %p, i64 44
356  %p45 = getelementptr i16, i16* %p, i64 45
357  %i0 = load i16, i16* %p0, align 2
358  %i1 = load i16, i16* %p1, align 2
359  %i2 = load i16, i16* %p2, align 2
360  %i3 = load i16, i16* %p3, align 2
361  store i16 %i2, i16* %p42, align 2
362  store i16 %i3, i16* %p43, align 2
363  store i16 %i0, i16* %p44, align 2
364  store i16 %i1, i16* %p45, align 2
365  ret void
366}
367
368; TODO: recognize this as 2 rotates?
369
370define void @rotate32_consecutive(i16* %p) {
371; CHECK-LABEL: rotate32_consecutive:
372; CHECK:       # %bb.0:
373; CHECK-NEXT:    movzwl (%rdi), %eax
374; CHECK-NEXT:    movzwl 2(%rdi), %ecx
375; CHECK-NEXT:    movzwl 4(%rdi), %edx
376; CHECK-NEXT:    movzwl 6(%rdi), %esi
377; CHECK-NEXT:    movw %cx, 84(%rdi)
378; CHECK-NEXT:    movw %ax, 86(%rdi)
379; CHECK-NEXT:    movw %si, 88(%rdi)
380; CHECK-NEXT:    movw %dx, 90(%rdi)
381; CHECK-NEXT:    retq
382  %p0 = getelementptr i16, i16* %p, i64 0
383  %p1 = getelementptr i16, i16* %p, i64 1
384  %p2 = getelementptr i16, i16* %p, i64 2
385  %p3 = getelementptr i16, i16* %p, i64 3
386  %p42 = getelementptr i16, i16* %p, i64 42
387  %p43 = getelementptr i16, i16* %p, i64 43
388  %p44 = getelementptr i16, i16* %p, i64 44
389  %p45 = getelementptr i16, i16* %p, i64 45
390  %i0 = load i16, i16* %p0, align 2
391  %i1 = load i16, i16* %p1, align 2
392  %i2 = load i16, i16* %p2, align 2
393  %i3 = load i16, i16* %p3, align 2
394  store i16 %i1, i16* %p42, align 2
395  store i16 %i0, i16* %p43, align 2
396  store i16 %i3, i16* %p44, align 2
397  store i16 %i2, i16* %p45, align 2
398  ret void
399}
400
401; Same as above, but now the stores are not all consecutive.
402
403define void @rotate32_twice(i16* %p) {
404; CHECK-LABEL: rotate32_twice:
405; CHECK:       # %bb.0:
406; CHECK-NEXT:    movl (%rdi), %eax
407; CHECK-NEXT:    movl 4(%rdi), %ecx
408; CHECK-NEXT:    roll $16, %eax
409; CHECK-NEXT:    roll $16, %ecx
410; CHECK-NEXT:    movl %eax, 84(%rdi)
411; CHECK-NEXT:    movl %ecx, 108(%rdi)
412; CHECK-NEXT:    retq
413  %p0 = getelementptr i16, i16* %p, i64 0
414  %p1 = getelementptr i16, i16* %p, i64 1
415  %p2 = getelementptr i16, i16* %p, i64 2
416  %p3 = getelementptr i16, i16* %p, i64 3
417  %p42 = getelementptr i16, i16* %p, i64 42
418  %p43 = getelementptr i16, i16* %p, i64 43
419  %p54 = getelementptr i16, i16* %p, i64 54
420  %p55 = getelementptr i16, i16* %p, i64 55
421  %i0 = load i16, i16* %p0, align 2
422  %i1 = load i16, i16* %p1, align 2
423  %i2 = load i16, i16* %p2, align 2
424  %i3 = load i16, i16* %p3, align 2
425  store i16 %i1, i16* %p42, align 2
426  store i16 %i0, i16* %p43, align 2
427  store i16 %i3, i16* %p54, align 2
428  store i16 %i2, i16* %p55, align 2
429  ret void
430}
431
432define void @trunc_i16_to_i8(i16 %x, i8* %p) {
433; CHECK-LABEL: trunc_i16_to_i8:
434; CHECK:       # %bb.0:
435; CHECK-NEXT:    movw %di, (%rsi)
436; CHECK-NEXT:    retq
437  %t1 = trunc i16 %x to i8
438  %sh = lshr i16 %x, 8
439  %t2 = trunc i16 %sh to i8
440  store i8 %t1, i8* %p, align 1
441  %p1 = getelementptr inbounds i8, i8* %p, i64 1
442  store i8 %t2, i8* %p1, align 1
443  ret void
444}
445
446define void @trunc_i32_to_i8(i32 %x, i8* %p) {
447; CHECK-LABEL: trunc_i32_to_i8:
448; CHECK:       # %bb.0:
449; CHECK-NEXT:    movl %edi, (%rsi)
450; CHECK-NEXT:    retq
451  %t1 = trunc i32 %x to i8
452  %sh1 = lshr i32 %x, 8
453  %t2 = trunc i32 %sh1 to i8
454  %sh2 = lshr i32 %x, 16
455  %t3 = trunc i32 %sh2 to i8
456  %sh3 = lshr i32 %x, 24
457  %t4 = trunc i32 %sh3 to i8
458  store i8 %t1, i8* %p, align 1
459  %p1 = getelementptr inbounds i8, i8* %p, i64 1
460  store i8 %t2, i8* %p1, align 1
461  %p2 = getelementptr inbounds i8, i8* %p, i64 2
462  store i8 %t3, i8* %p2, align 1
463  %p3 = getelementptr inbounds i8, i8* %p, i64 3
464  store i8 %t4, i8* %p3, align 1
465  ret void
466}
467
468define void @trunc_i32_to_i16(i32 %x, i16* %p) {
469; CHECK-LABEL: trunc_i32_to_i16:
470; CHECK:       # %bb.0:
471; CHECK-NEXT:    movl %edi, (%rsi)
472; CHECK-NEXT:    retq
473  %t1 = trunc i32 %x to i16
474  %sh = lshr i32 %x, 16
475  %t2 = trunc i32 %sh to i16
476  store i16 %t1, i16* %p, align 2
477  %p1 = getelementptr inbounds i16, i16* %p, i64 1
478  store i16 %t2, i16* %p1, align 2
479  ret void
480}
481
482define void @be_i32_to_i16(i32 %x, i16* %p0) {
483; CHECK-LABEL: be_i32_to_i16:
484; CHECK:       # %bb.0:
485; CHECK-NEXT:    rorl $16, %edi
486; CHECK-NEXT:    movl %edi, (%rsi)
487; CHECK-NEXT:    retq
488  %sh1 = lshr i32 %x, 16
489  %t0 = trunc i32 %x to i16
490  %t1 = trunc i32 %sh1 to i16
491  %p1 = getelementptr inbounds i16, i16* %p0, i64 1
492  store i16 %t0, i16* %p1, align 2
493  store i16 %t1, i16* %p0, align 2
494  ret void
495}
496
497define void @be_i32_to_i16_order(i32 %x, i16* %p0) {
498; CHECK-LABEL: be_i32_to_i16_order:
499; CHECK:       # %bb.0:
500; CHECK-NEXT:    rorl $16, %edi
501; CHECK-NEXT:    movl %edi, (%rsi)
502; CHECK-NEXT:    retq
503  %sh1 = lshr i32 %x, 16
504  %t0 = trunc i32 %x to i16
505  %t1 = trunc i32 %sh1 to i16
506  %p1 = getelementptr inbounds i16, i16* %p0, i64 1
507  store i16 %t1, i16* %p0, align 2
508  store i16 %t0, i16* %p1, align 2
509  ret void
510}
511
512define void @trunc_i64_to_i8(i64 %x, i8* %p) {
513; CHECK-LABEL: trunc_i64_to_i8:
514; CHECK:       # %bb.0:
515; CHECK-NEXT:    movq %rdi, (%rsi)
516; CHECK-NEXT:    retq
517  %t1 = trunc i64 %x to i8
518  %sh1 = lshr i64 %x, 8
519  %t2 = trunc i64 %sh1 to i8
520  %sh2 = lshr i64 %x, 16
521  %t3 = trunc i64 %sh2 to i8
522  %sh3 = lshr i64 %x, 24
523  %t4 = trunc i64 %sh3 to i8
524  %sh4 = lshr i64 %x, 32
525  %t5 = trunc i64 %sh4 to i8
526  %sh5 = lshr i64 %x, 40
527  %t6 = trunc i64 %sh5 to i8
528  %sh6 = lshr i64 %x, 48
529  %t7 = trunc i64 %sh6 to i8
530  %sh7 = lshr i64 %x, 56
531  %t8 = trunc i64 %sh7 to i8
532  store i8 %t1, i8* %p, align 1
533  %p1 = getelementptr inbounds i8, i8* %p, i64 1
534  store i8 %t2, i8* %p1, align 1
535  %p2 = getelementptr inbounds i8, i8* %p, i64 2
536  store i8 %t3, i8* %p2, align 1
537  %p3 = getelementptr inbounds i8, i8* %p, i64 3
538  store i8 %t4, i8* %p3, align 1
539  %p4 = getelementptr inbounds i8, i8* %p, i64 4
540  store i8 %t5, i8* %p4, align 1
541  %p5 = getelementptr inbounds i8, i8* %p, i64 5
542  store i8 %t6, i8* %p5, align 1
543  %p6 = getelementptr inbounds i8, i8* %p, i64 6
544  store i8 %t7, i8* %p6, align 1
545  %p7 = getelementptr inbounds i8, i8* %p, i64 7
546  store i8 %t8, i8* %p7, align 1
547  ret void
548}
549
550define void @trunc_i64_to_i16(i64 %x, i16* %p) {
551; CHECK-LABEL: trunc_i64_to_i16:
552; CHECK:       # %bb.0:
553; CHECK-NEXT:    movq %rdi, (%rsi)
554; CHECK-NEXT:    retq
555  %t1 = trunc i64 %x to i16
556  %sh1 = lshr i64 %x, 16
557  %t2 = trunc i64 %sh1 to i16
558  %sh2 = lshr i64 %x, 32
559  %t3 = trunc i64 %sh2 to i16
560  %sh3 = lshr i64 %x, 48
561  %t4 = trunc i64 %sh3 to i16
562  store i16 %t1, i16* %p, align 2
563  %p1 = getelementptr inbounds i16, i16* %p, i64 1
564  store i16 %t2, i16* %p1, align 2
565  %p2 = getelementptr inbounds i16, i16* %p, i64 2
566  store i16 %t3, i16* %p2, align 2
567  %p3 = getelementptr inbounds i16, i16* %p, i64 3
568  store i16 %t4, i16* %p3, align 2
569  ret void
570}
571
572define void @trunc_i64_to_i32(i64 %x, i32* %p) {
573; CHECK-LABEL: trunc_i64_to_i32:
574; CHECK:       # %bb.0:
575; CHECK-NEXT:    movq %rdi, (%rsi)
576; CHECK-NEXT:    retq
577  %t1 = trunc i64 %x to i32
578  %sh = lshr i64 %x, 32
579  %t2 = trunc i64 %sh to i32
580  store i32 %t1, i32* %p, align 4
581  %p1 = getelementptr inbounds i32, i32* %p, i64 1
582  store i32 %t2, i32* %p1, align 4
583  ret void
584}
585
586define void @be_i64_to_i32(i64 %x, i32* %p0) {
587; CHECK-LABEL: be_i64_to_i32:
588; CHECK:       # %bb.0:
589; CHECK-NEXT:    rorq $32, %rdi
590; CHECK-NEXT:    movq %rdi, (%rsi)
591; CHECK-NEXT:    retq
592  %sh1 = lshr i64 %x, 32
593  %t0 = trunc i64 %x to i32
594  %t1 = trunc i64 %sh1 to i32
595  %p1 = getelementptr inbounds i32, i32* %p0, i64 1
596  store i32 %t0, i32* %p1, align 4
597  store i32 %t1, i32* %p0, align 4
598  ret void
599}
600
601define void @be_i64_to_i32_order(i64 %x, i32* %p0) {
602; CHECK-LABEL: be_i64_to_i32_order:
603; CHECK:       # %bb.0:
604; CHECK-NEXT:    rorq $32, %rdi
605; CHECK-NEXT:    movq %rdi, (%rsi)
606; CHECK-NEXT:    retq
607  %sh1 = lshr i64 %x, 32
608  %t0 = trunc i64 %x to i32
609  %t1 = trunc i64 %sh1 to i32
610  %p1 = getelementptr inbounds i32, i32* %p0, i64 1
611  store i32 %t1, i32* %p0, align 4
612  store i32 %t0, i32* %p1, align 4
613  ret void
614}
615