1 ; Test 64-bit comparison in which the second operand is a zero-extended i32. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 declare i64 @foo() 6 7 ; Check unsigned register comparison. 8 define double @f1(double %a, double %b, i64 %i1, i32 %unext) { 9 ; CHECK-LABEL: f1: 10 ; CHECK: clgfr %r2, %r3 11 ; CHECK-NEXT: jl 12 ; CHECK: ldr %f0, %f2 13 ; CHECK: br %r14 14 %i2 = zext i32 %unext to i64 15 %cond = icmp ult i64 %i1, %i2 16 %res = select i1 %cond, double %a, double %b 17 ret double %res 18 } 19 20 ; ...and again with a different representation. 21 define double @f2(double %a, double %b, i64 %i1, i64 %unext) { 22 ; CHECK-LABEL: f2: 23 ; CHECK: clgfr %r2, %r3 24 ; CHECK-NEXT: jl 25 ; CHECK: ldr %f0, %f2 26 ; CHECK: br %r14 27 %i2 = and i64 %unext, 4294967295 28 %cond = icmp ult i64 %i1, %i2 29 %res = select i1 %cond, double %a, double %b 30 ret double %res 31 } 32 33 ; Check signed register comparison, which can't use CLGFR. 34 define double @f3(double %a, double %b, i64 %i1, i32 %unext) { 35 ; CHECK-LABEL: f3: 36 ; CHECK-NOT: clgfr 37 ; CHECK: br %r14 38 %i2 = zext i32 %unext to i64 39 %cond = icmp slt i64 %i1, %i2 40 %res = select i1 %cond, double %a, double %b 41 ret double %res 42 } 43 44 ; ...and again with a different representation 45 define double @f4(double %a, double %b, i64 %i1, i64 %unext) { 46 ; CHECK-LABEL: f4: 47 ; CHECK-NOT: clgfr 48 ; CHECK: br %r14 49 %i2 = and i64 %unext, 4294967295 50 %cond = icmp slt i64 %i1, %i2 51 %res = select i1 %cond, double %a, double %b 52 ret double %res 53 } 54 55 ; Check register equality. 56 define double @f5(double %a, double %b, i64 %i1, i32 %unext) { 57 ; CHECK-LABEL: f5: 58 ; CHECK: clgfr %r2, %r3 59 ; CHECK-NEXT: je 60 ; CHECK: ldr %f0, %f2 61 ; CHECK: br %r14 62 %i2 = zext i32 %unext to i64 63 %cond = icmp eq i64 %i1, %i2 64 %res = select i1 %cond, double %a, double %b 65 ret double %res 66 } 67 68 ; ...and again with a different representation 69 define double @f6(double %a, double %b, i64 %i1, i64 %unext) { 70 ; CHECK-LABEL: f6: 71 ; CHECK: clgfr %r2, %r3 72 ; CHECK-NEXT: je 73 ; CHECK: ldr %f0, %f2 74 ; CHECK: br %r14 75 %i2 = and i64 %unext, 4294967295 76 %cond = icmp eq i64 %i1, %i2 77 %res = select i1 %cond, double %a, double %b 78 ret double %res 79 } 80 81 ; Check register inequality. 82 define double @f7(double %a, double %b, i64 %i1, i32 %unext) { 83 ; CHECK-LABEL: f7: 84 ; CHECK: clgfr %r2, %r3 85 ; CHECK-NEXT: jlh 86 ; CHECK: ldr %f0, %f2 87 ; CHECK: br %r14 88 %i2 = zext i32 %unext to i64 89 %cond = icmp ne i64 %i1, %i2 90 %res = select i1 %cond, double %a, double %b 91 ret double %res 92 } 93 94 ; ...and again with a different representation 95 define double @f8(double %a, double %b, i64 %i1, i64 %unext) { 96 ; CHECK-LABEL: f8: 97 ; CHECK: clgfr %r2, %r3 98 ; CHECK-NEXT: jlh 99 ; CHECK: ldr %f0, %f2 100 ; CHECK: br %r14 101 %i2 = and i64 %unext, 4294967295 102 %cond = icmp ne i64 %i1, %i2 103 %res = select i1 %cond, double %a, double %b 104 ret double %res 105 } 106 107 ; Check unsigned comparisonn with memory. 108 define double @f9(double %a, double %b, i64 %i1, i32 *%ptr) { 109 ; CHECK-LABEL: f9: 110 ; CHECK: clgf %r2, 0(%r3) 111 ; CHECK-NEXT: jl 112 ; CHECK: ldr %f0, %f2 113 ; CHECK: br %r14 114 %unext = load i32 *%ptr 115 %i2 = zext i32 %unext to i64 116 %cond = icmp ult i64 %i1, %i2 117 %res = select i1 %cond, double %a, double %b 118 ret double %res 119 } 120 121 ; Check signed comparison with memory. 122 define double @f10(double %a, double %b, i64 %i1, i32 *%ptr) { 123 ; CHECK-LABEL: f10: 124 ; CHECK-NOT: clgf 125 ; CHECK: br %r14 126 %unext = load i32 *%ptr 127 %i2 = zext i32 %unext to i64 128 %cond = icmp slt i64 %i1, %i2 129 %res = select i1 %cond, double %a, double %b 130 ret double %res 131 } 132 133 ; Check memory equality. 134 define double @f11(double %a, double %b, i64 %i1, i32 *%ptr) { 135 ; CHECK-LABEL: f11: 136 ; CHECK: clgf %r2, 0(%r3) 137 ; CHECK-NEXT: je 138 ; CHECK: ldr %f0, %f2 139 ; CHECK: br %r14 140 %unext = load i32 *%ptr 141 %i2 = zext i32 %unext to i64 142 %cond = icmp eq i64 %i1, %i2 143 %res = select i1 %cond, double %a, double %b 144 ret double %res 145 } 146 147 ; Check memory inequality. 148 define double @f12(double %a, double %b, i64 %i1, i32 *%ptr) { 149 ; CHECK-LABEL: f12: 150 ; CHECK: clgf %r2, 0(%r3) 151 ; CHECK-NEXT: jlh 152 ; CHECK: ldr %f0, %f2 153 ; CHECK: br %r14 154 %unext = load i32 *%ptr 155 %i2 = zext i32 %unext to i64 156 %cond = icmp ne i64 %i1, %i2 157 %res = select i1 %cond, double %a, double %b 158 ret double %res 159 } 160 161 ; Check the high end of the aligned CLGF range. 162 define double @f13(double %a, double %b, i64 %i1, i32 *%base) { 163 ; CHECK-LABEL: f13: 164 ; CHECK: clgf %r2, 524284(%r3) 165 ; CHECK-NEXT: jl 166 ; CHECK: ldr %f0, %f2 167 ; CHECK: br %r14 168 %ptr = getelementptr i32 *%base, i64 131071 169 %unext = load i32 *%ptr 170 %i2 = zext i32 %unext to i64 171 %cond = icmp ult i64 %i1, %i2 172 %res = select i1 %cond, double %a, double %b 173 ret double %res 174 } 175 176 ; Check the next word up, which needs separate address logic. 177 ; Other sequences besides this one would be OK. 178 define double @f14(double %a, double %b, i64 %i1, i32 *%base) { 179 ; CHECK-LABEL: f14: 180 ; CHECK: agfi %r3, 524288 181 ; CHECK: clgf %r2, 0(%r3) 182 ; CHECK-NEXT: jl 183 ; CHECK: ldr %f0, %f2 184 ; CHECK: br %r14 185 %ptr = getelementptr i32 *%base, i64 131072 186 %unext = load i32 *%ptr 187 %i2 = zext i32 %unext to i64 188 %cond = icmp ult i64 %i1, %i2 189 %res = select i1 %cond, double %a, double %b 190 ret double %res 191 } 192 193 ; Check the high end of the negative aligned CLGF range. 194 define double @f15(double %a, double %b, i64 %i1, i32 *%base) { 195 ; CHECK-LABEL: f15: 196 ; CHECK: clgf %r2, -4(%r3) 197 ; CHECK-NEXT: jl 198 ; CHECK: ldr %f0, %f2 199 ; CHECK: br %r14 200 %ptr = getelementptr i32 *%base, i64 -1 201 %unext = load i32 *%ptr 202 %i2 = zext i32 %unext to i64 203 %cond = icmp ult i64 %i1, %i2 204 %res = select i1 %cond, double %a, double %b 205 ret double %res 206 } 207 208 ; Check the low end of the CLGF range. 209 define double @f16(double %a, double %b, i64 %i1, i32 *%base) { 210 ; CHECK-LABEL: f16: 211 ; CHECK: clgf %r2, -524288(%r3) 212 ; CHECK-NEXT: jl 213 ; CHECK: ldr %f0, %f2 214 ; CHECK: br %r14 215 %ptr = getelementptr i32 *%base, i64 -131072 216 %unext = load i32 *%ptr 217 %i2 = zext i32 %unext to i64 218 %cond = icmp ult i64 %i1, %i2 219 %res = select i1 %cond, double %a, double %b 220 ret double %res 221 } 222 223 ; Check the next word down, which needs separate address logic. 224 ; Other sequences besides this one would be OK. 225 define double @f17(double %a, double %b, i64 %i1, i32 *%base) { 226 ; CHECK-LABEL: f17: 227 ; CHECK: agfi %r3, -524292 228 ; CHECK: clgf %r2, 0(%r3) 229 ; CHECK-NEXT: jl 230 ; CHECK: ldr %f0, %f2 231 ; CHECK: br %r14 232 %ptr = getelementptr i32 *%base, i64 -131073 233 %unext = load i32 *%ptr 234 %i2 = zext i32 %unext to i64 235 %cond = icmp ult i64 %i1, %i2 236 %res = select i1 %cond, double %a, double %b 237 ret double %res 238 } 239 240 ; Check that CLGF allows an index. 241 define double @f18(double %a, double %b, i64 %i1, i64 %base, i64 %index) { 242 ; CHECK-LABEL: f18: 243 ; CHECK: clgf %r2, 524284({{%r4,%r3|%r3,%r4}}) 244 ; CHECK-NEXT: jl 245 ; CHECK: ldr %f0, %f2 246 ; CHECK: br %r14 247 %add1 = add i64 %base, %index 248 %add2 = add i64 %add1, 524284 249 %ptr = inttoptr i64 %add2 to i32 * 250 %unext = load i32 *%ptr 251 %i2 = zext i32 %unext to i64 252 %cond = icmp ult i64 %i1, %i2 253 %res = select i1 %cond, double %a, double %b 254 ret double %res 255 } 256 257 ; Check that comparisons of spilled values can use CLGF rather than CLGFR. 258 define i64 @f19(i32 *%ptr0) { 259 ; CHECK-LABEL: f19: 260 ; CHECK: brasl %r14, foo@PLT 261 ; CHECK: clgf {{%r[0-9]+}}, 16{{[04]}}(%r15) 262 ; CHECK: br %r14 263 %ptr1 = getelementptr i32 *%ptr0, i64 2 264 %ptr2 = getelementptr i32 *%ptr0, i64 4 265 %ptr3 = getelementptr i32 *%ptr0, i64 6 266 %ptr4 = getelementptr i32 *%ptr0, i64 8 267 %ptr5 = getelementptr i32 *%ptr0, i64 10 268 %ptr6 = getelementptr i32 *%ptr0, i64 12 269 %ptr7 = getelementptr i32 *%ptr0, i64 14 270 %ptr8 = getelementptr i32 *%ptr0, i64 16 271 %ptr9 = getelementptr i32 *%ptr0, i64 18 272 273 %val0 = load i32 *%ptr0 274 %val1 = load i32 *%ptr1 275 %val2 = load i32 *%ptr2 276 %val3 = load i32 *%ptr3 277 %val4 = load i32 *%ptr4 278 %val5 = load i32 *%ptr5 279 %val6 = load i32 *%ptr6 280 %val7 = load i32 *%ptr7 281 %val8 = load i32 *%ptr8 282 %val9 = load i32 *%ptr9 283 284 %frob0 = add i32 %val0, 100 285 %frob1 = add i32 %val1, 100 286 %frob2 = add i32 %val2, 100 287 %frob3 = add i32 %val3, 100 288 %frob4 = add i32 %val4, 100 289 %frob5 = add i32 %val5, 100 290 %frob6 = add i32 %val6, 100 291 %frob7 = add i32 %val7, 100 292 %frob8 = add i32 %val8, 100 293 %frob9 = add i32 %val9, 100 294 295 store i32 %frob0, i32 *%ptr0 296 store i32 %frob1, i32 *%ptr1 297 store i32 %frob2, i32 *%ptr2 298 store i32 %frob3, i32 *%ptr3 299 store i32 %frob4, i32 *%ptr4 300 store i32 %frob5, i32 *%ptr5 301 store i32 %frob6, i32 *%ptr6 302 store i32 %frob7, i32 *%ptr7 303 store i32 %frob8, i32 *%ptr8 304 store i32 %frob9, i32 *%ptr9 305 306 %ret = call i64 @foo() 307 308 %ext0 = zext i32 %frob0 to i64 309 %ext1 = zext i32 %frob1 to i64 310 %ext2 = zext i32 %frob2 to i64 311 %ext3 = zext i32 %frob3 to i64 312 %ext4 = zext i32 %frob4 to i64 313 %ext5 = zext i32 %frob5 to i64 314 %ext6 = zext i32 %frob6 to i64 315 %ext7 = zext i32 %frob7 to i64 316 %ext8 = zext i32 %frob8 to i64 317 %ext9 = zext i32 %frob9 to i64 318 319 %cmp0 = icmp ult i64 %ret, %ext0 320 %cmp1 = icmp ult i64 %ret, %ext1 321 %cmp2 = icmp ult i64 %ret, %ext2 322 %cmp3 = icmp ult i64 %ret, %ext3 323 %cmp4 = icmp ult i64 %ret, %ext4 324 %cmp5 = icmp ult i64 %ret, %ext5 325 %cmp6 = icmp ult i64 %ret, %ext6 326 %cmp7 = icmp ult i64 %ret, %ext7 327 %cmp8 = icmp ult i64 %ret, %ext8 328 %cmp9 = icmp ult i64 %ret, %ext9 329 330 %sel0 = select i1 %cmp0, i64 %ret, i64 0 331 %sel1 = select i1 %cmp1, i64 %sel0, i64 1 332 %sel2 = select i1 %cmp2, i64 %sel1, i64 2 333 %sel3 = select i1 %cmp3, i64 %sel2, i64 3 334 %sel4 = select i1 %cmp4, i64 %sel3, i64 4 335 %sel5 = select i1 %cmp5, i64 %sel4, i64 5 336 %sel6 = select i1 %cmp6, i64 %sel5, i64 6 337 %sel7 = select i1 %cmp7, i64 %sel6, i64 7 338 %sel8 = select i1 %cmp8, i64 %sel7, i64 8 339 %sel9 = select i1 %cmp9, i64 %sel8, i64 9 340 341 ret i64 %sel9 342 } 343