1; Test the use of TM and TMY.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s
4
5@g = global i32 0
6
7; Check a simple branching use of TM.
8define void @f1(i8 *%src) {
9; CHECK-LABEL: f1:
10; CHECK: tm 0(%r2), 1
11; CHECK: je {{\.L.*}}
12; CHECK: br %r14
13entry:
14  %byte = load i8 *%src
15  %and = and i8 %byte, 1
16  %cmp = icmp eq i8 %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
28; Check that we do not fold across an aliasing store.
29define void @f2(i8 *%src) {
30; CHECK-LABEL: f2:
31; CHECK: llc [[REG:%r[0-5]]], 0(%r2)
32; CHECK: mvi 0(%r2), 0
33; CHECK: tmll [[REG]], 1
34; CHECK: je {{\.L.*}}
35; CHECK: br %r14
36entry:
37  %byte = load i8 *%src
38  store i8 0, i8 *%src
39  %and = and i8 %byte, 1
40  %cmp = icmp eq i8 %and, 0
41  br i1 %cmp, label %exit, label %store
42
43store:
44  store i32 1, i32 *@g
45  br label %exit
46
47exit:
48  ret void
49}
50
51; Check a simple select-based use of TM.
52define double @f3(i8 *%src, double %a, double %b) {
53; CHECK-LABEL: f3:
54; CHECK: tm 0(%r2), 1
55; CHECK: je {{\.L.*}}
56; CHECK: br %r14
57  %byte = load i8 *%src
58  %and = and i8 %byte, 1
59  %cmp = icmp eq i8 %and, 0
60  %res = select i1 %cmp, double %b, double %a
61  ret double %res
62}
63
64; Check that we do not fold across an aliasing store.
65define double @f4(i8 *%src, double %a, double %b) {
66; CHECK-LABEL: f4:
67; CHECK: tm 0(%r2), 1
68; CHECK: je {{\.L.*}}
69; CHECK: mvi 0(%r2), 0
70; CHECK: br %r14
71  %byte = load i8 *%src
72  %and = and i8 %byte, 1
73  %cmp = icmp eq i8 %and, 0
74  %res = select i1 %cmp, double %b, double %a
75  store i8 0, i8 *%src
76  ret double %res
77}
78
79; Check an inequality check.
80define double @f5(i8 *%src, double %a, double %b) {
81; CHECK-LABEL: f5:
82; CHECK: tm 0(%r2), 1
83; CHECK: jne {{\.L.*}}
84; CHECK: br %r14
85  %byte = load i8 *%src
86  %and = and i8 %byte, 1
87  %cmp = icmp ne i8 %and, 0
88  %res = select i1 %cmp, double %b, double %a
89  ret double %res
90}
91
92; Check that we can also use TM for equality comparisons with the mask.
93define double @f6(i8 *%src, double %a, double %b) {
94; CHECK-LABEL: f6:
95; CHECK: tm 0(%r2), 254
96; CHECK: jo {{\.L.*}}
97; CHECK: br %r14
98  %byte = load i8 *%src
99  %and = and i8 %byte, 254
100  %cmp = icmp eq i8 %and, 254
101  %res = select i1 %cmp, double %b, double %a
102  ret double %res
103}
104
105; Check inequality comparisons with the mask.
106define double @f7(i8 *%src, double %a, double %b) {
107; CHECK-LABEL: f7:
108; CHECK: tm 0(%r2), 254
109; CHECK: jno {{\.L.*}}
110; CHECK: br %r14
111  %byte = load i8 *%src
112  %and = and i8 %byte, 254
113  %cmp = icmp ne i8 %and, 254
114  %res = select i1 %cmp, double %b, double %a
115  ret double %res
116}
117
118; Check that we do not use the memory TM instruction when CC is being tested
119; for 2.
120define double @f8(i8 *%src, double %a, double %b) {
121; CHECK-LABEL: f8:
122; CHECK: llc [[REG:%r[0-5]]], 0(%r2)
123; CHECK: tmll [[REG]], 3
124; CHECK: jh {{\.L.*}}
125; CHECK: br %r14
126  %byte = load i8 *%src
127  %and = and i8 %byte, 3
128  %cmp = icmp eq i8 %and, 2
129  %res = select i1 %cmp, double %b, double %a
130  ret double %res
131}
132
133; ...likewise 1.
134define double @f9(i8 *%src, double %a, double %b) {
135; CHECK-LABEL: f9:
136; CHECK: llc [[REG:%r[0-5]]], 0(%r2)
137; CHECK: tmll [[REG]], 3
138; CHECK: jl {{\.L.*}}
139; CHECK: br %r14
140  %byte = load i8 *%src
141  %and = and i8 %byte, 3
142  %cmp = icmp eq i8 %and, 1
143  %res = select i1 %cmp, double %b, double %a
144  ret double %res
145}
146
147; Check the high end of the TM range.
148define double @f10(i8 *%src, double %a, double %b) {
149; CHECK-LABEL: f10:
150; CHECK: tm 4095(%r2), 1
151; CHECK: je {{\.L.*}}
152; CHECK: br %r14
153  %ptr = getelementptr i8 *%src, i64 4095
154  %byte = load i8 *%ptr
155  %and = and i8 %byte, 1
156  %cmp = icmp eq i8 %and, 0
157  %res = select i1 %cmp, double %b, double %a
158  ret double %res
159}
160
161; Check the low end of the positive TMY range.
162define double @f11(i8 *%src, double %a, double %b) {
163; CHECK-LABEL: f11:
164; CHECK: tmy 4096(%r2), 1
165; CHECK: je {{\.L.*}}
166; CHECK: br %r14
167  %ptr = getelementptr i8 *%src, i64 4096
168  %byte = load i8 *%ptr
169  %and = and i8 %byte, 1
170  %cmp = icmp eq i8 %and, 0
171  %res = select i1 %cmp, double %b, double %a
172  ret double %res
173}
174
175; Check the high end of the TMY range.
176define double @f12(i8 *%src, double %a, double %b) {
177; CHECK-LABEL: f12:
178; CHECK: tmy 524287(%r2), 1
179; CHECK: je {{\.L.*}}
180; CHECK: br %r14
181  %ptr = getelementptr i8 *%src, i64 524287
182  %byte = load i8 *%ptr
183  %and = and i8 %byte, 1
184  %cmp = icmp eq i8 %and, 0
185  %res = select i1 %cmp, double %b, double %a
186  ret double %res
187}
188
189; Check the next byte up, which needs separate address logic.
190define double @f13(i8 *%src, double %a, double %b) {
191; CHECK-LABEL: f13:
192; CHECK: agfi %r2, 524288
193; CHECK: tm 0(%r2), 1
194; CHECK: je {{\.L.*}}
195; CHECK: br %r14
196  %ptr = getelementptr i8 *%src, i64 524288
197  %byte = load i8 *%ptr
198  %and = and i8 %byte, 1
199  %cmp = icmp eq i8 %and, 0
200  %res = select i1 %cmp, double %b, double %a
201  ret double %res
202}
203
204; Check the low end of the TMY range.
205define double @f14(i8 *%src, double %a, double %b) {
206; CHECK-LABEL: f14:
207; CHECK: tmy -524288(%r2), 1
208; CHECK: je {{\.L.*}}
209; CHECK: br %r14
210  %ptr = getelementptr i8 *%src, i64 -524288
211  %byte = load i8 *%ptr
212  %and = and i8 %byte, 1
213  %cmp = icmp eq i8 %and, 0
214  %res = select i1 %cmp, double %b, double %a
215  ret double %res
216}
217
218; Check the next byte down, which needs separate address logic.
219define double @f15(i8 *%src, double %a, double %b) {
220; CHECK-LABEL: f15:
221; CHECK: agfi %r2, -524289
222; CHECK: tm 0(%r2), 1
223; CHECK: je {{\.L.*}}
224; CHECK: br %r14
225  %ptr = getelementptr i8 *%src, i64 -524289
226  %byte = load i8 *%ptr
227  %and = and i8 %byte, 1
228  %cmp = icmp eq i8 %and, 0
229  %res = select i1 %cmp, double %b, double %a
230  ret double %res
231}
232
233; Check that TM(Y) does not allow an index
234define double @f16(i8 *%src, i64 %index, double %a, double %b) {
235; CHECK-LABEL: f16:
236; CHECK: tm 0({{%r[1-5]}}), 1
237; CHECK: je {{\.L.*}}
238; CHECK: br %r14
239  %ptr = getelementptr i8 *%src, i64 %index
240  %byte = load i8 *%ptr
241  %and = and i8 %byte, 1
242  %cmp = icmp eq i8 %and, 0
243  %res = select i1 %cmp, double %b, double %a
244  ret double %res
245}
246