1; Test all condition-code masks that are relevant for CRJ.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5declare i32 @foo()
6@g1 = global i16 0
7
8define void @f1(i32 %target) {
9; CHECK-LABEL: f1:
10; CHECK: .cfi_def_cfa_offset
11; CHECK: .L[[LABEL:.*]]:
12; CHECK: crje %r2, {{%r[0-9]+}}, .L[[LABEL]]
13  br label %loop
14loop:
15  %val = call i32 @foo()
16  %cond = icmp eq i32 %val, %target
17  br i1 %cond, label %loop, label %exit
18exit:
19  ret void
20}
21
22define void @f2(i32 %target) {
23; CHECK-LABEL: f2:
24; CHECK: .cfi_def_cfa_offset
25; CHECK: .L[[LABEL:.*]]:
26; CHECK: crjlh %r2, {{%r[0-9]+}}, .L[[LABEL]]
27  br label %loop
28loop:
29  %val = call i32 @foo()
30  %cond = icmp ne i32 %val, %target
31  br i1 %cond, label %loop, label %exit
32exit:
33  ret void
34}
35
36define void @f3(i32 %target) {
37; CHECK-LABEL: f3:
38; CHECK: .cfi_def_cfa_offset
39; CHECK: .L[[LABEL:.*]]:
40; CHECK: crjle %r2, {{%r[0-9]+}}, .L[[LABEL]]
41  br label %loop
42loop:
43  %val = call i32 @foo()
44  %cond = icmp sle i32 %val, %target
45  br i1 %cond, label %loop, label %exit
46exit:
47  ret void
48}
49
50define void @f4(i32 %target) {
51; CHECK-LABEL: f4:
52; CHECK: .cfi_def_cfa_offset
53; CHECK: .L[[LABEL:.*]]:
54; CHECK: crjl %r2, {{%r[0-9]+}}, .L[[LABEL]]
55  br label %loop
56loop:
57  %val = call i32 @foo()
58  %cond = icmp slt i32 %val, %target
59  br i1 %cond, label %loop, label %exit
60exit:
61  ret void
62}
63
64define void @f5(i32 %target) {
65; CHECK-LABEL: f5:
66; CHECK: .cfi_def_cfa_offset
67; CHECK: .L[[LABEL:.*]]:
68; CHECK: crjh %r2, {{%r[0-9]+}}, .L[[LABEL]]
69  br label %loop
70loop:
71  %val = call i32 @foo()
72  %cond = icmp sgt i32 %val, %target
73  br i1 %cond, label %loop, label %exit
74exit:
75  ret void
76}
77
78define void @f6(i32 %target) {
79; CHECK-LABEL: f6:
80; CHECK: .cfi_def_cfa_offset
81; CHECK: .L[[LABEL:.*]]:
82; CHECK: crjhe %r2, {{%r[0-9]+}}, .L[[LABEL]]
83  br label %loop
84loop:
85  %val = call i32 @foo()
86  %cond = icmp sge i32 %val, %target
87  br i1 %cond, label %loop, label %exit
88exit:
89  ret void
90}
91
92; Check that CRJ is used for checking equality with a zero-extending
93; character load.
94define void @f7(i8 *%targetptr) {
95; CHECK-LABEL: f7:
96; CHECK: .cfi_def_cfa_offset
97; CHECK: .L[[LABEL:.*]]:
98; CHECK: llc [[REG:%r[0-5]]],
99; CHECK: crje %r2, [[REG]], .L[[LABEL]]
100  br label %loop
101loop:
102  %val = call i32 @foo()
103  %byte = load i8 *%targetptr
104  %target = zext i8 %byte to i32
105  %cond = icmp eq i32 %val, %target
106  br i1 %cond, label %loop, label %exit
107exit:
108  ret void
109}
110
111; ...and zero-extending i16 loads.
112define void @f8(i16 *%targetptr) {
113; CHECK-LABEL: f8:
114; CHECK: .cfi_def_cfa_offset
115; CHECK: .L[[LABEL:.*]]:
116; CHECK: llh [[REG:%r[0-5]]],
117; CHECK: crje %r2, [[REG]], .L[[LABEL]]
118  br label %loop
119loop:
120  %val = call i32 @foo()
121  %half = load i16 *%targetptr
122  %target = zext i16 %half to i32
123  %cond = icmp eq i32 %val, %target
124  br i1 %cond, label %loop, label %exit
125exit:
126  ret void
127}
128
129; ...unless the address is a global.
130define void @f9(i16 *%targetptr) {
131; CHECK-LABEL: f9:
132; CHECK: .cfi_def_cfa_offset
133; CHECK: .L[[LABEL:.*]]:
134; CHECK: clhrl %r2, g1
135; CHECK: je .L[[LABEL]]
136  br label %loop
137loop:
138  %val = call i32 @foo()
139  %half = load i16 *@g1
140  %target = zext i16 %half to i32
141  %cond = icmp eq i32 %val, %target
142  br i1 %cond, label %loop, label %exit
143exit:
144  ret void
145}
146
147; Check that CRJ is used for checking order between two zero-extending
148; byte loads, even if the original comparison was unsigned.
149define void @f10(i8 *%targetptr1) {
150; CHECK-LABEL: f10:
151; CHECK: .cfi_def_cfa_offset
152; CHECK: .L[[LABEL:.*]]:
153; CHECK-DAG: llc [[REG1:%r[0-5]]], 0(
154; CHECK-DAG: llc [[REG2:%r[0-5]]], 1(
155; CHECK: crjl [[REG1]], [[REG2]], .L[[LABEL]]
156  br label %loop
157loop:
158  %val = call i32 @foo()
159  %targetptr2 = getelementptr i8 *%targetptr1, i64 1
160  %byte1 = load i8 *%targetptr1
161  %byte2 = load i8 *%targetptr2
162  %ext1 = zext i8 %byte1 to i32
163  %ext2 = zext i8 %byte2 to i32
164  %cond = icmp ult i32 %ext1, %ext2
165  br i1 %cond, label %loop, label %exit
166exit:
167  ret void
168}
169
170; ...likewise halfword loads.
171define void @f11(i16 *%targetptr1) {
172; CHECK-LABEL: f11:
173; CHECK: .cfi_def_cfa_offset
174; CHECK: .L[[LABEL:.*]]:
175; CHECK-DAG: llh [[REG1:%r[0-5]]], 0(
176; CHECK-DAG: llh [[REG2:%r[0-5]]], 2(
177; CHECK: crjl [[REG1]], [[REG2]], .L[[LABEL]]
178  br label %loop
179loop:
180  %val = call i32 @foo()
181  %targetptr2 = getelementptr i16 *%targetptr1, i64 1
182  %half1 = load i16 *%targetptr1
183  %half2 = load i16 *%targetptr2
184  %ext1 = zext i16 %half1 to i32
185  %ext2 = zext i16 %half2 to i32
186  %cond = icmp ult i32 %ext1, %ext2
187  br i1 %cond, label %loop, label %exit
188exit:
189  ret void
190}
191