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