1; Test insertions of memory into the low byte of an i32.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5; Check a plain insertion with (or (and ... -0xff) (zext (load ....))).
6; The whole sequence can be performed by IC.
7define i32 @f1(i32 %orig, i8 *%ptr) {
8; CHECK-LABEL: f1:
9; CHECK-NOT: ni
10; CHECK: ic %r2, 0(%r3)
11; CHECK: br %r14
12  %val = load i8 *%ptr
13  %ptr2 = zext i8 %val to i32
14  %ptr1 = and i32 %orig, -256
15  %or = or i32 %ptr1, %ptr2
16  ret i32 %or
17}
18
19; Like f1, but with the operands reversed.
20define i32 @f2(i32 %orig, i8 *%ptr) {
21; CHECK-LABEL: f2:
22; CHECK-NOT: ni
23; CHECK: ic %r2, 0(%r3)
24; CHECK: br %r14
25  %val = load i8 *%ptr
26  %ptr2 = zext i8 %val to i32
27  %ptr1 = and i32 %orig, -256
28  %or = or i32 %ptr2, %ptr1
29  ret i32 %or
30}
31
32; Check a case where more bits than lower 8 are masked out of the
33; register value.  We can use IC but must keep the original mask.
34define i32 @f3(i32 %orig, i8 *%ptr) {
35; CHECK-LABEL: f3:
36; CHECK: nill %r2, 65024
37; CHECK: ic %r2, 0(%r3)
38; CHECK: br %r14
39  %val = load i8 *%ptr
40  %ptr2 = zext i8 %val to i32
41  %ptr1 = and i32 %orig, -512
42  %or = or i32 %ptr1, %ptr2
43  ret i32 %or
44}
45
46; Like f3, but with the operands reversed.
47define i32 @f4(i32 %orig, i8 *%ptr) {
48; CHECK-LABEL: f4:
49; CHECK: nill %r2, 65024
50; CHECK: ic %r2, 0(%r3)
51; CHECK: br %r14
52  %val = load i8 *%ptr
53  %ptr2 = zext i8 %val to i32
54  %ptr1 = and i32 %orig, -512
55  %or = or i32 %ptr2, %ptr1
56  ret i32 %or
57}
58
59; Check a case where the low 8 bits are cleared by a shift left.
60define i32 @f5(i32 %orig, i8 *%ptr) {
61; CHECK-LABEL: f5:
62; CHECK: sll %r2, 8
63; CHECK: ic %r2, 0(%r3)
64; CHECK: br %r14
65  %val = load i8 *%ptr
66  %ptr2 = zext i8 %val to i32
67  %ptr1 = shl i32 %orig, 8
68  %or = or i32 %ptr1, %ptr2
69  ret i32 %or
70}
71
72; Like f5, but with the operands reversed.
73define i32 @f6(i32 %orig, i8 *%ptr) {
74; CHECK-LABEL: f6:
75; CHECK: sll %r2, 8
76; CHECK: ic %r2, 0(%r3)
77; CHECK: br %r14
78  %val = load i8 *%ptr
79  %ptr2 = zext i8 %val to i32
80  %ptr1 = shl i32 %orig, 8
81  %or = or i32 %ptr2, %ptr1
82  ret i32 %or
83}
84
85; Check insertions into a constant.
86define i32 @f7(i32 %orig, i8 *%ptr) {
87; CHECK-LABEL: f7:
88; CHECK: lhi %r2, 256
89; CHECK: ic %r2, 0(%r3)
90; CHECK: br %r14
91  %val = load i8 *%ptr
92  %ptr2 = zext i8 %val to i32
93  %or = or i32 %ptr2, 256
94  ret i32 %or
95}
96
97; Like f7, but with the operands reversed.
98define i32 @f8(i32 %orig, i8 *%ptr) {
99; CHECK-LABEL: f8:
100; CHECK: lhi %r2, 256
101; CHECK: ic %r2, 0(%r3)
102; CHECK: br %r14
103  %val = load i8 *%ptr
104  %ptr2 = zext i8 %val to i32
105  %or = or i32 256, %ptr2
106  ret i32 %or
107}
108
109; Check the high end of the IC range.
110define i32 @f9(i32 %orig, i8 *%src) {
111; CHECK-LABEL: f9:
112; CHECK: ic %r2, 4095(%r3)
113; CHECK: br %r14
114  %ptr = getelementptr i8 *%src, i64 4095
115  %val = load i8 *%ptr
116  %src2 = zext i8 %val to i32
117  %src1 = and i32 %orig, -256
118  %or = or i32 %src2, %src1
119  ret i32 %or
120}
121
122; Check the next byte up, which should use ICY instead of IC.
123define i32 @f10(i32 %orig, i8 *%src) {
124; CHECK-LABEL: f10:
125; CHECK: icy %r2, 4096(%r3)
126; CHECK: br %r14
127  %ptr = getelementptr i8 *%src, i64 4096
128  %val = load i8 *%ptr
129  %src2 = zext i8 %val to i32
130  %src1 = and i32 %orig, -256
131  %or = or i32 %src2, %src1
132  ret i32 %or
133}
134
135; Check the high end of the ICY range.
136define i32 @f11(i32 %orig, i8 *%src) {
137; CHECK-LABEL: f11:
138; CHECK: icy %r2, 524287(%r3)
139; CHECK: br %r14
140  %ptr = getelementptr i8 *%src, i64 524287
141  %val = load i8 *%ptr
142  %src2 = zext i8 %val to i32
143  %src1 = and i32 %orig, -256
144  %or = or i32 %src2, %src1
145  ret i32 %or
146}
147
148; Check the next byte up, which needs separate address logic.
149; Other sequences besides this one would be OK.
150define i32 @f12(i32 %orig, i8 *%src) {
151; CHECK-LABEL: f12:
152; CHECK: agfi %r3, 524288
153; CHECK: ic %r2, 0(%r3)
154; CHECK: br %r14
155  %ptr = getelementptr i8 *%src, i64 524288
156  %val = load i8 *%ptr
157  %src2 = zext i8 %val to i32
158  %src1 = and i32 %orig, -256
159  %or = or i32 %src2, %src1
160  ret i32 %or
161}
162
163; Check the high end of the negative ICY range.
164define i32 @f13(i32 %orig, i8 *%src) {
165; CHECK-LABEL: f13:
166; CHECK: icy %r2, -1(%r3)
167; CHECK: br %r14
168  %ptr = getelementptr i8 *%src, i64 -1
169  %val = load i8 *%ptr
170  %src2 = zext i8 %val to i32
171  %src1 = and i32 %orig, -256
172  %or = or i32 %src2, %src1
173  ret i32 %or
174}
175
176; Check the low end of the ICY range.
177define i32 @f14(i32 %orig, i8 *%src) {
178; CHECK-LABEL: f14:
179; CHECK: icy %r2, -524288(%r3)
180; CHECK: br %r14
181  %ptr = getelementptr i8 *%src, i64 -524288
182  %val = load i8 *%ptr
183  %src2 = zext i8 %val to i32
184  %src1 = and i32 %orig, -256
185  %or = or i32 %src2, %src1
186  ret i32 %or
187}
188
189; Check the next byte down, which needs separate address logic.
190; Other sequences besides this one would be OK.
191define i32 @f15(i32 %orig, i8 *%src) {
192; CHECK-LABEL: f15:
193; CHECK: agfi %r3, -524289
194; CHECK: ic %r2, 0(%r3)
195; CHECK: br %r14
196  %ptr = getelementptr i8 *%src, i64 -524289
197  %val = load i8 *%ptr
198  %src2 = zext i8 %val to i32
199  %src1 = and i32 %orig, -256
200  %or = or i32 %src2, %src1
201  ret i32 %or
202}
203
204; Check that IC allows an index.
205define i32 @f16(i32 %orig, i8 *%src, i64 %index) {
206; CHECK-LABEL: f16:
207; CHECK: ic %r2, 4095({{%r4,%r3|%r3,%r4}})
208; CHECK: br %r14
209  %ptr1 = getelementptr i8 *%src, i64 %index
210  %ptr2 = getelementptr i8 *%ptr1, i64 4095
211  %val = load i8 *%ptr2
212  %src2 = zext i8 %val to i32
213  %src1 = and i32 %orig, -256
214  %or = or i32 %src2, %src1
215  ret i32 %or
216}
217
218; Check that ICY allows an index.
219define i32 @f17(i32 %orig, i8 *%src, i64 %index) {
220; CHECK-LABEL: f17:
221; CHECK: icy %r2, 4096({{%r4,%r3|%r3,%r4}})
222; CHECK: br %r14
223  %ptr1 = getelementptr i8 *%src, i64 %index
224  %ptr2 = getelementptr i8 *%ptr1, i64 4096
225  %val = load i8 *%ptr2
226  %src2 = zext i8 %val to i32
227  %src1 = and i32 %orig, -256
228  %or = or i32 %src2, %src1
229  ret i32 %or
230}
231