1 ; Test 8-bit atomic min/max operations. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK 4 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1 5 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2 6 7 ; Check signed minimum. 8 ; - CHECK is for the main loop. 9 ; - CHECK-SHIFT1 makes sure that the negated shift count used by the second 10 ; RLL is set up correctly. The negation is independent of the NILL and L 11 ; tested in CHECK. 12 ; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word 13 ; before being used, and that the low bits are set to 1. This sequence is 14 ; independent of the other loop prologue instructions. 15 define i8 @f1(i8 *%src, i8 %b) { 16 ; CHECK-LABEL: f1: 17 ; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 18 ; CHECK: nill %r2, 65532 19 ; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 20 ; CHECK: [[LOOP:\.[^:]*]]: 21 ; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 22 ; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]] 23 ; CHECK: risbg [[ROT]], %r3, 32, 39, 0 24 ; CHECK: [[KEEP]]: 25 ; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 26 ; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 27 ; CHECK: jl [[LOOP]] 28 ; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 29 ; CHECK: br %r14 30 ; 31 ; CHECK-SHIFT1-LABEL: f1: 32 ; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 33 ; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 34 ; CHECK-SHIFT1: rll 35 ; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 36 ; CHECK-SHIFT1: rll 37 ; CHECK-SHIFT1: br %r14 38 ; 39 ; CHECK-SHIFT2-LABEL: f1: 40 ; CHECK-SHIFT2: sll %r3, 24 41 ; CHECK-SHIFT2: rll 42 ; CHECK-SHIFT2: crjle {{%r[0-9]+}}, %r3 43 ; CHECK-SHIFT2: rll 44 ; CHECK-SHIFT2: rll 45 ; CHECK-SHIFT2: br %r14 46 %res = atomicrmw min i8 *%src, i8 %b seq_cst 47 ret i8 %res 48 } 49 50 ; Check signed maximum. 51 define i8 @f2(i8 *%src, i8 %b) { 52 ; CHECK-LABEL: f2: 53 ; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 54 ; CHECK: nill %r2, 65532 55 ; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 56 ; CHECK: [[LOOP:\.[^:]*]]: 57 ; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 58 ; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]] 59 ; CHECK: risbg [[ROT]], %r3, 32, 39, 0 60 ; CHECK: [[KEEP]]: 61 ; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 62 ; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 63 ; CHECK: jl [[LOOP]] 64 ; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 65 ; CHECK: br %r14 66 ; 67 ; CHECK-SHIFT1-LABEL: f2: 68 ; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 69 ; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 70 ; CHECK-SHIFT1: rll 71 ; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 72 ; CHECK-SHIFT1: rll 73 ; CHECK-SHIFT1: br %r14 74 ; 75 ; CHECK-SHIFT2-LABEL: f2: 76 ; CHECK-SHIFT2: sll %r3, 24 77 ; CHECK-SHIFT2: rll 78 ; CHECK-SHIFT2: crjhe {{%r[0-9]+}}, %r3 79 ; CHECK-SHIFT2: rll 80 ; CHECK-SHIFT2: rll 81 ; CHECK-SHIFT2: br %r14 82 %res = atomicrmw max i8 *%src, i8 %b seq_cst 83 ret i8 %res 84 } 85 86 ; Check unsigned minimum. 87 define i8 @f3(i8 *%src, i8 %b) { 88 ; CHECK-LABEL: f3: 89 ; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 90 ; CHECK: nill %r2, 65532 91 ; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 92 ; CHECK: [[LOOP:\.[^:]*]]: 93 ; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 94 ; CHECK: clr [[ROT]], %r3 95 ; CHECK: jle [[KEEP:\..*]] 96 ; CHECK: risbg [[ROT]], %r3, 32, 39, 0 97 ; CHECK: [[KEEP]]: 98 ; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 99 ; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 100 ; CHECK: jl [[LOOP]] 101 ; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 102 ; CHECK: br %r14 103 ; 104 ; CHECK-SHIFT1-LABEL: f3: 105 ; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 106 ; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 107 ; CHECK-SHIFT1: rll 108 ; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 109 ; CHECK-SHIFT1: rll 110 ; CHECK-SHIFT1: br %r14 111 ; 112 ; CHECK-SHIFT2-LABEL: f3: 113 ; CHECK-SHIFT2: sll %r3, 24 114 ; CHECK-SHIFT2: rll 115 ; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3 116 ; CHECK-SHIFT2: rll 117 ; CHECK-SHIFT2: rll 118 ; CHECK-SHIFT2: br %r14 119 %res = atomicrmw umin i8 *%src, i8 %b seq_cst 120 ret i8 %res 121 } 122 123 ; Check unsigned maximum. 124 define i8 @f4(i8 *%src, i8 %b) { 125 ; CHECK-LABEL: f4: 126 ; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 127 ; CHECK: nill %r2, 65532 128 ; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 129 ; CHECK: [[LOOP:\.[^:]*]]: 130 ; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 131 ; CHECK: clr [[ROT]], %r3 132 ; CHECK: jhe [[KEEP:\..*]] 133 ; CHECK: risbg [[ROT]], %r3, 32, 39, 0 134 ; CHECK: [[KEEP]]: 135 ; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 136 ; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 137 ; CHECK: jl [[LOOP]] 138 ; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 139 ; CHECK: br %r14 140 ; 141 ; CHECK-SHIFT1-LABEL: f4: 142 ; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 143 ; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 144 ; CHECK-SHIFT1: rll 145 ; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 146 ; CHECK-SHIFT1: rll 147 ; CHECK-SHIFT1: br %r14 148 ; 149 ; CHECK-SHIFT2-LABEL: f4: 150 ; CHECK-SHIFT2: sll %r3, 24 151 ; CHECK-SHIFT2: rll 152 ; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3 153 ; CHECK-SHIFT2: rll 154 ; CHECK-SHIFT2: rll 155 ; CHECK-SHIFT2: br %r14 156 %res = atomicrmw umax i8 *%src, i8 %b seq_cst 157 ret i8 %res 158 } 159 160 ; Check the lowest useful signed minimum value. We need to load 0x81000000 161 ; into the source register. 162 define i8 @f5(i8 *%src) { 163 ; CHECK-LABEL: f5: 164 ; CHECK: llilh [[SRC2:%r[0-9]+]], 33024 165 ; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]] 166 ; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 167 ; CHECK: br %r14 168 ; 169 ; CHECK-SHIFT1-LABEL: f5: 170 ; CHECK-SHIFT1: br %r14 171 ; CHECK-SHIFT2-LABEL: f5: 172 ; CHECK-SHIFT2: br %r14 173 %res = atomicrmw min i8 *%src, i8 -127 seq_cst 174 ret i8 %res 175 } 176 177 ; Check the highest useful signed maximum value. We need to load 0x7e000000 178 ; into the source register. 179 define i8 @f6(i8 *%src) { 180 ; CHECK-LABEL: f6: 181 ; CHECK: llilh [[SRC2:%r[0-9]+]], 32256 182 ; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]] 183 ; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 184 ; CHECK: br %r14 185 ; 186 ; CHECK-SHIFT1-LABEL: f6: 187 ; CHECK-SHIFT1: br %r14 188 ; CHECK-SHIFT2-LABEL: f6: 189 ; CHECK-SHIFT2: br %r14 190 %res = atomicrmw max i8 *%src, i8 126 seq_cst 191 ret i8 %res 192 } 193 194 ; Check the lowest useful unsigned minimum value. We need to load 0x01000000 195 ; into the source register. 196 define i8 @f7(i8 *%src) { 197 ; CHECK-LABEL: f7: 198 ; CHECK: llilh [[SRC2:%r[0-9]+]], 256 199 ; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]] 200 ; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 201 ; CHECK: br %r14 202 ; 203 ; CHECK-SHIFT1-LABEL: f7: 204 ; CHECK-SHIFT1: br %r14 205 ; CHECK-SHIFT2-LABEL: f7: 206 ; CHECK-SHIFT2: br %r14 207 %res = atomicrmw umin i8 *%src, i8 1 seq_cst 208 ret i8 %res 209 } 210 211 ; Check the highest useful unsigned maximum value. We need to load 0xfe000000 212 ; into the source register. 213 define i8 @f8(i8 *%src) { 214 ; CHECK-LABEL: f8: 215 ; CHECK: llilh [[SRC2:%r[0-9]+]], 65024 216 ; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]] 217 ; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 218 ; CHECK: br %r14 219 ; 220 ; CHECK-SHIFT1-LABEL: f8: 221 ; CHECK-SHIFT1: br %r14 222 ; CHECK-SHIFT2-LABEL: f8: 223 ; CHECK-SHIFT2: br %r14 224 %res = atomicrmw umax i8 *%src, i8 254 seq_cst 225 ret i8 %res 226 } 227