1; Test the use of TEST UNDER MASK for 64-bit operations.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s
5
6@g = global i32 0
7
8; Check the lowest useful TMLL value.
9define void @f1(i64 %a) {
10; CHECK-LABEL: f1:
11; CHECK: tmll %r2, 1
12; CHECK: je {{\.L.*}}
13; CHECK: br %r14
14entry:
15  %and = and i64 %a, 1
16  %cmp = icmp eq i64 %and, 0
17  br i1 %cmp, label %exit, label %store
18
19store:
20  store i32 1, i32 *@g
21  br label %exit
22
23exit:
24  ret void
25}
26
27; Check the high end of the TMLL range.
28define void @f2(i64 %a) {
29; CHECK-LABEL: f2:
30; CHECK: tmll %r2, 65535
31; CHECK: jne {{\.L.*}}
32; CHECK: br %r14
33entry:
34  %and = and i64 %a, 65535
35  %cmp = icmp ne i64 %and, 0
36  br i1 %cmp, label %exit, label %store
37
38store:
39  store i32 1, i32 *@g
40  br label %exit
41
42exit:
43  ret void
44}
45
46; Check the lowest useful TMLH value, which is the next value up.
47define void @f3(i64 %a) {
48; CHECK-LABEL: f3:
49; CHECK: tmlh %r2, 1
50; CHECK: jne {{\.L.*}}
51; CHECK: br %r14
52entry:
53  %and = and i64 %a, 65536
54  %cmp = icmp ne i64 %and, 0
55  br i1 %cmp, label %exit, label %store
56
57store:
58  store i32 1, i32 *@g
59  br label %exit
60
61exit:
62  ret void
63}
64
65; Check the next value up again, which cannot use TM.
66define void @f4(i64 %a) {
67; CHECK-LABEL: f4:
68; CHECK-NOT: {{tm[lh].}}
69; CHECK: br %r14
70entry:
71  %and = and i64 %a, 4294901759
72  %cmp = icmp eq i64 %and, 0
73  br i1 %cmp, label %exit, label %store
74
75store:
76  store i32 1, i32 *@g
77  br label %exit
78
79exit:
80  ret void
81}
82
83; Check the high end of the TMLH range.
84define void @f5(i64 %a) {
85; CHECK-LABEL: f5:
86; CHECK: tmlh %r2, 65535
87; CHECK: je {{\.L.*}}
88; CHECK: br %r14
89entry:
90  %and = and i64 %a, 4294901760
91  %cmp = icmp eq i64 %and, 0
92  br i1 %cmp, label %exit, label %store
93
94store:
95  store i32 1, i32 *@g
96  br label %exit
97
98exit:
99  ret void
100}
101
102; Check the lowest useful TMHL value.
103define void @f6(i64 %a) {
104; CHECK-LABEL: f6:
105; CHECK: tmhl %r2, 1
106; CHECK: je {{\.L.*}}
107; CHECK: br %r14
108entry:
109  %and = and i64 %a, 4294967296
110  %cmp = icmp eq i64 %and, 0
111  br i1 %cmp, label %exit, label %store
112
113store:
114  store i32 1, i32 *@g
115  br label %exit
116
117exit:
118  ret void
119}
120
121; Check the next value up again, which cannot use TM.
122define void @f7(i64 %a) {
123; CHECK-LABEL: f7:
124; CHECK-NOT: {{tm[lh].}}
125; CHECK: br %r14
126entry:
127  %and = and i64 %a, 4294967297
128  %cmp = icmp ne i64 %and, 0
129  br i1 %cmp, label %exit, label %store
130
131store:
132  store i32 1, i32 *@g
133  br label %exit
134
135exit:
136  ret void
137}
138
139; Check the high end of the TMHL range.
140define void @f8(i64 %a) {
141; CHECK-LABEL: f8:
142; CHECK: tmhl %r2, 65535
143; CHECK: jne {{\.L.*}}
144; CHECK: br %r14
145entry:
146  %and = and i64 %a, 281470681743360
147  %cmp = icmp ne i64 %and, 0
148  br i1 %cmp, label %exit, label %store
149
150store:
151  store i32 1, i32 *@g
152  br label %exit
153
154exit:
155  ret void
156}
157
158; Check the lowest useful TMHH value.
159define void @f9(i64 %a) {
160; CHECK-LABEL: f9:
161; CHECK: tmhh %r2, 1
162; CHECK: jne {{\.L.*}}
163; CHECK: br %r14
164entry:
165  %and = and i64 %a, 281474976710656
166  %cmp = icmp ne i64 %and, 0
167  br i1 %cmp, label %exit, label %store
168
169store:
170  store i32 1, i32 *@g
171  br label %exit
172
173exit:
174  ret void
175}
176
177; Check the high end of the TMHH range.
178define void @f10(i64 %a) {
179; CHECK-LABEL: f10:
180; CHECK: tmhh %r2, 65535
181; CHECK: je {{\.L.*}}
182; CHECK: br %r14
183entry:
184  %and = and i64 %a, 18446462598732840960
185  %cmp = icmp eq i64 %and, 0
186  br i1 %cmp, label %exit, label %store
187
188store:
189  store i32 1, i32 *@g
190  br label %exit
191
192exit:
193  ret void
194}
195
196; Check that we can fold an SHL into a TMxx mask.
197define void @f11(i64 %a) {
198; CHECK-LABEL: f11:
199; CHECK: tmhl %r2, 32768
200; CHECK: jne {{\.L.*}}
201; CHECK: br %r14
202entry:
203  %shl = shl i64 %a, 1
204  %and = and i64 %shl, 281474976710656
205  %cmp = icmp ne i64 %and, 0
206  br i1 %cmp, label %exit, label %store
207
208store:
209  store i32 1, i32 *@g
210  br label %exit
211
212exit:
213  ret void
214}
215
216; Check that we can fold an SHR into a TMxx mask.
217define void @f12(i64 %a) {
218; CHECK-LABEL: f12:
219; CHECK: tmhh %r2, 256
220; CHECK: jne {{\.L.*}}
221; CHECK: br %r14
222entry:
223  %shr = lshr i64 %a, 56
224  %and = and i64 %shr, 1
225  %cmp = icmp ne i64 %and, 0
226  br i1 %cmp, label %exit, label %store
227
228store:
229  store i32 1, i32 *@g
230  br label %exit
231
232exit:
233  ret void
234}
235
236; Check a case where TMHH can be used to implement a ult comparison.
237define void @f13(i64 %a) {
238; CHECK-LABEL: f13:
239; CHECK: tmhh %r2, 49152
240; CHECK: jno {{\.L.*}}
241; CHECK: br %r14
242entry:
243  %cmp = icmp ult i64 %a, 13835058055282163712
244  br i1 %cmp, label %exit, label %store
245
246store:
247  store i32 1, i32 *@g
248  br label %exit
249
250exit:
251  ret void
252}
253
254; And again with ule.
255define void @f14(i64 %a) {
256; CHECK-LABEL: f14:
257; CHECK: tmhh %r2, 49152
258; CHECK: jno {{\.L.*}}
259; CHECK: br %r14
260entry:
261  %cmp = icmp ule i64 %a, 13835058055282163711
262  br i1 %cmp, label %exit, label %store
263
264store:
265  store i32 1, i32 *@g
266  br label %exit
267
268exit:
269  ret void
270}
271
272; And again with ugt.
273define void @f15(i64 %a) {
274; CHECK-LABEL: f15:
275; CHECK: tmhh %r2, 49152
276; CHECK: jo {{\.L.*}}
277; CHECK: br %r14
278entry:
279  %cmp = icmp ugt i64 %a, 13835058055282163711
280  br i1 %cmp, label %exit, label %store
281
282store:
283  store i32 1, i32 *@g
284  br label %exit
285
286exit:
287  ret void
288}
289
290; And again with uge.
291define void @f16(i64 %a) {
292; CHECK-LABEL: f16:
293; CHECK: tmhh %r2, 49152
294; CHECK: jo {{\.L.*}}
295; CHECK: br %r14
296entry:
297  %cmp = icmp uge i64 %a, 13835058055282163712
298  br i1 %cmp, label %exit, label %store
299
300store:
301  store i32 1, i32 *@g
302  br label %exit
303
304exit:
305  ret void
306}
307
308; Decrease the constant from f13 to make TMHH invalid.
309define void @f17(i64 %a) {
310; CHECK-LABEL: f17:
311; CHECK-NOT: tmhh
312; CHECK: llihh {{%r[0-5]}}, 49151
313; CHECK-NOT: tmhh
314; CHECK: br %r14
315entry:
316  %cmp = icmp ult i64 %a, 13834776580305453056
317  br i1 %cmp, label %exit, label %store
318
319store:
320  store i32 1, i32 *@g
321  br label %exit
322
323exit:
324  ret void
325}
326
327; Check that we don't use TMHH just to test the top bit.
328define void @f18(i64 %a) {
329; CHECK-LABEL: f18:
330; CHECK-NOT: tmhh
331; CHECK: cgijhe %r2, 0,
332; CHECK: br %r14
333entry:
334  %cmp = icmp ult i64 %a, 9223372036854775808
335  br i1 %cmp, label %exit, label %store
336
337store:
338  store i32 1, i32 *@g
339  br label %exit
340
341exit:
342  ret void
343}
344