1; Test memcmp using CLC, with i64 results.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5declare i64 @memcmp(i8 *%src1, i8 *%src2, i64 %size)
6
7; Zero-length comparisons should be optimized away.
8define i64 @f1(i8 *%src1, i8 *%src2) {
9; CHECK-LABEL: f1:
10; CHECK: lghi %r2, 0
11; CHECK: br %r14
12  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 0)
13  ret i64 %res
14}
15
16; Check a case where the result is used as an integer.
17define i64 @f2(i8 *%src1, i8 *%src2) {
18; CHECK-LABEL: f2:
19; CHECK: clc 0(2,%r2), 0(%r3)
20; CHECK: ipm [[REG:%r[0-5]]]
21; CHECK: srl [[REG]], 28
22; CHECK: rll [[REG]], [[REG]], 31
23; CHECK: lgfr %r2, [[REG]]
24; CHECK: br %r14
25  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 2)
26  ret i64 %res
27}
28
29; Check a case where the result is tested for equality.
30define void @f3(i8 *%src1, i8 *%src2, i64 *%dest) {
31; CHECK-LABEL: f3:
32; CHECK: clc 0(3,%r2), 0(%r3)
33; CHECK-NEXT: je {{\..*}}
34; CHECK: br %r14
35  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 3)
36  %cmp = icmp eq i64 %res, 0
37  br i1 %cmp, label %exit, label %store
38
39store:
40  store i64 0, i64 *%dest
41  br label %exit
42
43exit:
44  ret void
45}
46
47; Check a case where the result is tested for inequality.
48define void @f4(i8 *%src1, i8 *%src2, i64 *%dest) {
49; CHECK-LABEL: f4:
50; CHECK: clc 0(4,%r2), 0(%r3)
51; CHECK-NEXT: jlh {{\..*}}
52; CHECK: br %r14
53entry:
54  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 4)
55  %cmp = icmp ne i64 %res, 0
56  br i1 %cmp, label %exit, label %store
57
58store:
59  store i64 0, i64 *%dest
60  br label %exit
61
62exit:
63  ret void
64}
65
66; Check a case where the result is tested via slt.
67define void @f5(i8 *%src1, i8 *%src2, i64 *%dest) {
68; CHECK-LABEL: f5:
69; CHECK: clc 0(5,%r2), 0(%r3)
70; CHECK-NEXT: jl {{\..*}}
71; CHECK: br %r14
72entry:
73  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 5)
74  %cmp = icmp slt i64 %res, 0
75  br i1 %cmp, label %exit, label %store
76
77store:
78  store i64 0, i64 *%dest
79  br label %exit
80
81exit:
82  ret void
83}
84
85; Check a case where the result is tested for sgt.
86define void @f6(i8 *%src1, i8 *%src2, i64 *%dest) {
87; CHECK-LABEL: f6:
88; CHECK: clc 0(6,%r2), 0(%r3)
89; CHECK-NEXT: jh {{\..*}}
90; CHECK: br %r14
91entry:
92  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 6)
93  %cmp = icmp sgt i64 %res, 0
94  br i1 %cmp, label %exit, label %store
95
96store:
97  store i64 0, i64 *%dest
98  br label %exit
99
100exit:
101  ret void
102}
103
104; Check the upper end of the CLC range.  Here the result is used both as
105; an integer and for branching.
106define i64 @f7(i8 *%src1, i8 *%src2, i64 *%dest) {
107; CHECK-LABEL: f7:
108; CHECK: clc 0(256,%r2), 0(%r3)
109; CHECK: ipm [[REG:%r[0-5]]]
110; CHECK: srl [[REG]], 28
111; CHECK: rll [[REG]], [[REG]], 31
112; CHECK: lgfr %r2, [[REG]]
113; CHECK: jl {{.L*}}
114; CHECK: br %r14
115entry:
116  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 256)
117  %cmp = icmp slt i64 %res, 0
118  br i1 %cmp, label %exit, label %store
119
120store:
121  store i64 0, i64 *%dest
122  br label %exit
123
124exit:
125  ret i64 %res
126}
127
128; 257 bytes needs two CLCs.
129define i64 @f8(i8 *%src1, i8 *%src2) {
130; CHECK-LABEL: f8:
131; CHECK: clc 0(256,%r2), 0(%r3)
132; CHECK: jlh [[LABEL:\..*]]
133; CHECK: clc 256(1,%r2), 256(%r3)
134; CHECK: [[LABEL]]:
135; CHECK: ipm [[REG:%r[0-5]]]
136; CHECK: br %r14
137  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 257)
138  ret i64 %res
139}
140