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