Home | History | Annotate | Download | only in SystemZ
      1 ; Test memcmp using CLC, with i32 results.
      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 [[REG:%r[0-5]]]
     21 ; CHECK: srl [[REG]], 28
     22 ; CHECK: rll %r2, [[REG]], 31
     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.
    105 define i32 @f7(i8 *%src1, i8 *%src2, i32 *%dest) {
    106 ; CHECK-LABEL: f7:
    107 ; CHECK: clc 0(256,%r2), 0(%r3)
    108 ; CHECK: ipm [[REG:%r[0-5]]]
    109 ; CHECK: srl [[REG]], 28
    110 ; CHECK: rll %r2, [[REG]], 31
    111 ; CHECK: jl {{.L*}}
    112 ; CHECK: br %r14
    113 entry:
    114   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 256)
    115   %cmp = icmp slt i32 %res, 0
    116   br i1 %cmp, label %exit, label %store
    117 
    118 store:
    119   store i32 0, i32 *%dest
    120   br label %exit
    121 
    122 exit:
    123   ret i32 %res
    124 }
    125 
    126 ; 257 bytes needs two CLCs.
    127 define i32 @f8(i8 *%src1, i8 *%src2) {
    128 ; CHECK-LABEL: f8:
    129 ; CHECK: clc 0(256,%r2), 0(%r3)
    130 ; CHECK: jlh [[LABEL:\..*]]
    131 ; CHECK: clc 256(1,%r2), 256(%r3)
    132 ; CHECK: [[LABEL]]:
    133 ; CHECK: ipm [[REG:%r[0-5]]]
    134 ; CHECK: br %r14
    135   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 257)
    136   ret i32 %res
    137 }
    138 
    139 ; Test a comparison of 258 bytes in which the CC result can be used directly.
    140 define void @f9(i8 *%src1, i8 *%src2, i32 *%dest) {
    141 ; CHECK-LABEL: f9:
    142 ; CHECK: clc 0(256,%r2), 0(%r3)
    143 ; CHECK: jlh [[LABEL:\..*]]
    144 ; CHECK: clc 256(1,%r2), 256(%r3)
    145 ; CHECK: [[LABEL]]:
    146 ; CHECK-NEXT: jl .L
    147 ; CHECK: br %r14
    148 entry:
    149   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 257)
    150   %cmp = icmp slt i32 %res, 0
    151   br i1 %cmp, label %exit, label %store
    152 
    153 store:
    154   store i32 0, i32 *%dest
    155   br label %exit
    156 
    157 exit:
    158   ret void
    159 }
    160 
    161 ; Test the largest size that can use two CLCs.
    162 define i32 @f10(i8 *%src1, i8 *%src2) {
    163 ; CHECK-LABEL: f10:
    164 ; CHECK: clc 0(256,%r2), 0(%r3)
    165 ; CHECK: jlh [[LABEL:\..*]]
    166 ; CHECK: clc 256(256,%r2), 256(%r3)
    167 ; CHECK: [[LABEL]]:
    168 ; CHECK: ipm [[REG:%r[0-5]]]
    169 ; CHECK: br %r14
    170   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 512)
    171   ret i32 %res
    172 }
    173 
    174 ; Test the smallest size that needs 3 CLCs.
    175 define i32 @f11(i8 *%src1, i8 *%src2) {
    176 ; CHECK-LABEL: f11:
    177 ; CHECK: clc 0(256,%r2), 0(%r3)
    178 ; CHECK: jlh [[LABEL:\..*]]
    179 ; CHECK: clc 256(256,%r2), 256(%r3)
    180 ; CHECK: jlh [[LABEL]]
    181 ; CHECK: clc 512(1,%r2), 512(%r3)
    182 ; CHECK: [[LABEL]]:
    183 ; CHECK: ipm [[REG:%r[0-5]]]
    184 ; CHECK: br %r14
    185   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 513)
    186   ret i32 %res
    187 }
    188 
    189 ; Test the largest size than can use 3 CLCs.
    190 define i32 @f12(i8 *%src1, i8 *%src2) {
    191 ; CHECK-LABEL: f12:
    192 ; CHECK: clc 0(256,%r2), 0(%r3)
    193 ; CHECK: jlh [[LABEL:\..*]]
    194 ; CHECK: clc 256(256,%r2), 256(%r3)
    195 ; CHECK: jlh [[LABEL]]
    196 ; CHECK: clc 512(256,%r2), 512(%r3)
    197 ; CHECK: [[LABEL]]:
    198 ; CHECK: ipm [[REG:%r[0-5]]]
    199 ; CHECK: br %r14
    200   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 768)
    201   ret i32 %res
    202 }
    203 
    204 ; The next size up uses a loop instead.  We leave the more complicated
    205 ; loop tests to memcpy-01.ll, which shares the same form.
    206 define i32 @f13(i8 *%src1, i8 *%src2) {
    207 ; CHECK-LABEL: f13:
    208 ; CHECK: lghi [[COUNT:%r[0-5]]], 3
    209 ; CHECK: [[LOOP:.L[^:]*]]:
    210 ; CHECK: clc 0(256,%r2), 0(%r3)
    211 ; CHECK: jlh [[LABEL:\..*]]
    212 ; CHECK-DAG: la %r2, 256(%r2)
    213 ; CHECK-DAG: la %r3, 256(%r3)
    214 ; CHECK: brctg [[COUNT]], [[LOOP]]
    215 ; CHECK: clc 0(1,%r2), 0(%r3)
    216 ; CHECK: [[LABEL]]:
    217 ; CHECK: ipm [[REG:%r[0-5]]]
    218 ; CHECK: br %r14
    219   %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 769)
    220   ret i32 %res
    221 }
    222