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