1; Test 32-bit signed comparison in which the second operand is sign-extended
2; from an i16 memory value.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5
6; Check the low end of the CH range.
7define void @f1(i32 %lhs, i16 *%src, i32 *%dst) {
8; CHECK-LABEL: f1:
9; CHECK: ch %r2, 0(%r3)
10; CHECK: br %r14
11  %half = load i16 , i16 *%src
12  %rhs = sext i16 %half to i32
13  %cond = icmp slt i32 %lhs, %rhs
14  %res = select i1 %cond, i32 100, i32 200
15  store i32 %res, i32 *%dst
16  ret void
17}
18
19; Check the high end of the aligned CH range.
20define void @f2(i32 %lhs, i16 *%src, i32 *%dst) {
21; CHECK-LABEL: f2:
22; CHECK: ch %r2, 4094(%r3)
23; CHECK: br %r14
24  %ptr = getelementptr i16, i16 *%src, i64 2047
25  %half = load i16 , i16 *%ptr
26  %rhs = sext i16 %half to i32
27  %cond = icmp slt i32 %lhs, %rhs
28  %res = select i1 %cond, i32 100, i32 200
29  store i32 %res, i32 *%dst
30  ret void
31}
32
33; Check the next halfword up, which should use CHY instead of CH.
34define void @f3(i32 %lhs, i16 *%src, i32 *%dst) {
35; CHECK-LABEL: f3:
36; CHECK: chy %r2, 4096(%r3)
37; CHECK: br %r14
38  %ptr = getelementptr i16, i16 *%src, i64 2048
39  %half = load i16 , i16 *%ptr
40  %rhs = sext i16 %half to i32
41  %cond = icmp slt i32 %lhs, %rhs
42  %res = select i1 %cond, i32 100, i32 200
43  store i32 %res, i32 *%dst
44  ret void
45}
46
47; Check the high end of the aligned CHY range.
48define void @f4(i32 %lhs, i16 *%src, i32 *%dst) {
49; CHECK-LABEL: f4:
50; CHECK: chy %r2, 524286(%r3)
51; CHECK: br %r14
52  %ptr = getelementptr i16, i16 *%src, i64 262143
53  %half = load i16 , i16 *%ptr
54  %rhs = sext i16 %half to i32
55  %cond = icmp slt i32 %lhs, %rhs
56  %res = select i1 %cond, i32 100, i32 200
57  store i32 %res, i32 *%dst
58  ret void
59}
60
61; Check the next halfword up, which needs separate address logic.
62; Other sequences besides this one would be OK.
63define void @f5(i32 %lhs, i16 *%src, i32 *%dst) {
64; CHECK-LABEL: f5:
65; CHECK: agfi %r3, 524288
66; CHECK: ch %r2, 0(%r3)
67; CHECK: br %r14
68  %ptr = getelementptr i16, i16 *%src, i64 262144
69  %half = load i16 , i16 *%ptr
70  %rhs = sext i16 %half to i32
71  %cond = icmp slt i32 %lhs, %rhs
72  %res = select i1 %cond, i32 100, i32 200
73  store i32 %res, i32 *%dst
74  ret void
75}
76
77; Check the high end of the negative aligned CHY range.
78define void @f6(i32 %lhs, i16 *%src, i32 *%dst) {
79; CHECK-LABEL: f6:
80; CHECK: chy %r2, -2(%r3)
81; CHECK: br %r14
82  %ptr = getelementptr i16, i16 *%src, i64 -1
83  %half = load i16 , i16 *%ptr
84  %rhs = sext i16 %half to i32
85  %cond = icmp slt i32 %lhs, %rhs
86  %res = select i1 %cond, i32 100, i32 200
87  store i32 %res, i32 *%dst
88  ret void
89}
90
91; Check the low end of the CHY range.
92define void @f7(i32 %lhs, i16 *%src, i32 *%dst) {
93; CHECK-LABEL: f7:
94; CHECK: chy %r2, -524288(%r3)
95; CHECK: br %r14
96  %ptr = getelementptr i16, i16 *%src, i64 -262144
97  %half = load i16 , i16 *%ptr
98  %rhs = sext i16 %half to i32
99  %cond = icmp slt i32 %lhs, %rhs
100  %res = select i1 %cond, i32 100, i32 200
101  store i32 %res, i32 *%dst
102  ret void
103}
104
105; Check the next halfword down, which needs separate address logic.
106; Other sequences besides this one would be OK.
107define void @f8(i32 %lhs, i16 *%src, i32 *%dst) {
108; CHECK-LABEL: f8:
109; CHECK: agfi %r3, -524290
110; CHECK: ch %r2, 0(%r3)
111; CHECK: br %r14
112  %ptr = getelementptr i16, i16 *%src, i64 -262145
113  %half = load i16 , i16 *%ptr
114  %rhs = sext i16 %half to i32
115  %cond = icmp slt i32 %lhs, %rhs
116  %res = select i1 %cond, i32 100, i32 200
117  store i32 %res, i32 *%dst
118  ret void
119}
120
121; Check that CH allows an index.
122define void @f9(i32 %lhs, i64 %base, i64 %index, i32 *%dst) {
123; CHECK-LABEL: f9:
124; CHECK: ch %r2, 4094({{%r4,%r3|%r3,%r4}})
125; CHECK: br %r14
126  %add1 = add i64 %base, %index
127  %add2 = add i64 %add1, 4094
128  %ptr = inttoptr i64 %add2 to i16 *
129  %half = load i16 , i16 *%ptr
130  %rhs = sext i16 %half to i32
131  %cond = icmp slt i32 %lhs, %rhs
132  %res = select i1 %cond, i32 100, i32 200
133  store i32 %res, i32 *%dst
134  ret void
135}
136
137; Check that CHY allows an index.
138define void @f10(i32 %lhs, i64 %base, i64 %index, i32 *%dst) {
139; CHECK-LABEL: f10:
140; CHECK: chy %r2, 4096({{%r4,%r3|%r3,%r4}})
141; CHECK: br %r14
142  %add1 = add i64 %base, %index
143  %add2 = add i64 %add1, 4096
144  %ptr = inttoptr i64 %add2 to i16 *
145  %half = load i16 , i16 *%ptr
146  %rhs = sext i16 %half to i32
147  %cond = icmp slt i32 %lhs, %rhs
148  %res = select i1 %cond, i32 100, i32 200
149  store i32 %res, i32 *%dst
150  ret void
151}
152
153; Check the comparison can be reversed if that allows CH to be used.
154define double @f11(double %a, double %b, i32 %rhs, i16 *%src) {
155; CHECK-LABEL: f11:
156; CHECK: ch %r2, 0(%r3)
157; CHECK-NEXT: jh {{\.L.*}}
158; CHECK: ldr %f0, %f2
159; CHECK: br %r14
160  %half = load i16 , i16 *%src
161  %lhs = sext i16 %half to i32
162  %cond = icmp slt i32 %lhs, %rhs
163  %res = select i1 %cond, double %a, double %b
164  ret double %res
165}
166