1; Test memcmp using CLC. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5declare signext i32 @memcmp(i8 *%src1, i8 *%src2, i64 %size) 6 7; Zero-length comparisons should be optimized away. 8define 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. 17define 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. 29define 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 38store: 39 store i32 0, i32 *%dest 40 br label %exit 41 42exit: 43 ret void 44} 45 46; Check a case where the result is tested for inequality. 47define 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 52entry: 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 57store: 58 store i32 0, i32 *%dest 59 br label %exit 60 61exit: 62 ret void 63} 64 65; Check a case where the result is tested via slt. 66define 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 71entry: 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 76store: 77 store i32 0, i32 *%dest 78 br label %exit 79 80exit: 81 ret void 82} 83 84; Check a case where the result is tested for sgt. 85define 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 90entry: 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 95store: 96 store i32 0, i32 *%dest 97 br label %exit 98 99exit: 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. 106define 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 114entry: 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 119store: 120 store i32 0, i32 *%dest 121 br label %exit 122 123exit: 124 ret i32 %res 125} 126 127; 257 bytes is too big for a single CLC. For now expect a call instead. 128define 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} 135