1; Test 32-bit floating-point signaling comparison. The tests assume a z10 2; implementation of select, using conditional branches rather than LOCGR. 3; 4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 \ 5; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-SCALAR %s 6; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 \ 7; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-VECTOR %s 8 9declare float @foo() 10 11; Check comparison with registers. 12define i64 @f1(i64 %a, i64 %b, float %f1, float %f2) #0 { 13; CHECK-LABEL: f1: 14; CHECK: kebr %f0, %f2 15; CHECK-SCALAR-NEXT: ber %r14 16; CHECK-SCALAR: lgr %r2, %r3 17; CHECK-VECTOR-NEXT: locgrne %r2, %r3 18; CHECK: br %r14 19 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 20 float %f1, float %f2, 21 metadata !"oeq", 22 metadata !"fpexcept.strict") #0 23 %res = select i1 %cond, i64 %a, i64 %b 24 ret i64 %res 25} 26 27; Check the low end of the KEB range. 28define i64 @f2(i64 %a, i64 %b, float %f1, float *%ptr) #0 { 29; CHECK-LABEL: f2: 30; CHECK: keb %f0, 0(%r4) 31; CHECK-SCALAR-NEXT: ber %r14 32; CHECK-SCALAR: lgr %r2, %r3 33; CHECK-VECTOR-NEXT: locgrne %r2, %r3 34; CHECK: br %r14 35 %f2 = load float, float *%ptr 36 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 37 float %f1, float %f2, 38 metadata !"oeq", 39 metadata !"fpexcept.strict") #0 40 %res = select i1 %cond, i64 %a, i64 %b 41 ret i64 %res 42} 43 44; Check the high end of the aligned KEB range. 45define i64 @f3(i64 %a, i64 %b, float %f1, float *%base) #0 { 46; CHECK-LABEL: f3: 47; CHECK: keb %f0, 4092(%r4) 48; CHECK-SCALAR-NEXT: ber %r14 49; CHECK-SCALAR: lgr %r2, %r3 50; CHECK-VECTOR-NEXT: locgrne %r2, %r3 51; CHECK: br %r14 52 %ptr = getelementptr float, float *%base, i64 1023 53 %f2 = load float, float *%ptr 54 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 55 float %f1, float %f2, 56 metadata !"oeq", 57 metadata !"fpexcept.strict") #0 58 %res = select i1 %cond, i64 %a, i64 %b 59 ret i64 %res 60} 61 62; Check the next word up, which needs separate address logic. 63; Other sequences besides this one would be OK. 64define i64 @f4(i64 %a, i64 %b, float %f1, float *%base) #0 { 65; CHECK-LABEL: f4: 66; CHECK: aghi %r4, 4096 67; CHECK: keb %f0, 0(%r4) 68; CHECK-SCALAR-NEXT: ber %r14 69; CHECK-SCALAR: lgr %r2, %r3 70; CHECK-VECTOR-NEXT: locgrne %r2, %r3 71; CHECK: br %r14 72 %ptr = getelementptr float, float *%base, i64 1024 73 %f2 = load float, float *%ptr 74 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 75 float %f1, float %f2, 76 metadata !"oeq", 77 metadata !"fpexcept.strict") #0 78 %res = select i1 %cond, i64 %a, i64 %b 79 ret i64 %res 80} 81 82; Check negative displacements, which also need separate address logic. 83define i64 @f5(i64 %a, i64 %b, float %f1, float *%base) #0 { 84; CHECK-LABEL: f5: 85; CHECK: aghi %r4, -4 86; CHECK: keb %f0, 0(%r4) 87; CHECK-SCALAR-NEXT: ber %r14 88; CHECK-SCALAR: lgr %r2, %r3 89; CHECK-VECTOR-NEXT: locgrne %r2, %r3 90; CHECK: br %r14 91 %ptr = getelementptr float, float *%base, i64 -1 92 %f2 = load float, float *%ptr 93 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 94 float %f1, float %f2, 95 metadata !"oeq", 96 metadata !"fpexcept.strict") #0 97 %res = select i1 %cond, i64 %a, i64 %b 98 ret i64 %res 99} 100 101; Check that KEB allows indices. 102define i64 @f6(i64 %a, i64 %b, float %f1, float *%base, i64 %index) #0 { 103; CHECK-LABEL: f6: 104; CHECK: sllg %r1, %r5, 2 105; CHECK: keb %f0, 400(%r1,%r4) 106; CHECK-SCALAR-NEXT: ber %r14 107; CHECK-SCALAR: lgr %r2, %r3 108; CHECK-VECTOR-NEXT: locgrne %r2, %r3 109; CHECK: br %r14 110 %ptr1 = getelementptr float, float *%base, i64 %index 111 %ptr2 = getelementptr float, float *%ptr1, i64 100 112 %f2 = load float, float *%ptr2 113 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 114 float %f1, float %f2, 115 metadata !"oeq", 116 metadata !"fpexcept.strict") #0 117 %res = select i1 %cond, i64 %a, i64 %b 118 ret i64 %res 119} 120 121; Check that comparisons of spilled values can use KEB rather than KEBR. 122define float @f7(float *%ptr0) #0 { 123; CHECK-LABEL: f7: 124; CHECK: brasl %r14, foo@PLT 125; CHECK-SCALAR: keb {{%f[0-9]+}}, 16{{[04]}}(%r15) 126; CHECK: br %r14 127 %ptr1 = getelementptr float, float *%ptr0, i64 2 128 %ptr2 = getelementptr float, float *%ptr0, i64 4 129 %ptr3 = getelementptr float, float *%ptr0, i64 6 130 %ptr4 = getelementptr float, float *%ptr0, i64 8 131 %ptr5 = getelementptr float, float *%ptr0, i64 10 132 %ptr6 = getelementptr float, float *%ptr0, i64 12 133 %ptr7 = getelementptr float, float *%ptr0, i64 14 134 %ptr8 = getelementptr float, float *%ptr0, i64 16 135 %ptr9 = getelementptr float, float *%ptr0, i64 18 136 %ptr10 = getelementptr float, float *%ptr0, i64 20 137 138 %val0 = load float, float *%ptr0 139 %val1 = load float, float *%ptr1 140 %val2 = load float, float *%ptr2 141 %val3 = load float, float *%ptr3 142 %val4 = load float, float *%ptr4 143 %val5 = load float, float *%ptr5 144 %val6 = load float, float *%ptr6 145 %val7 = load float, float *%ptr7 146 %val8 = load float, float *%ptr8 147 %val9 = load float, float *%ptr9 148 %val10 = load float, float *%ptr10 149 150 %ret = call float @foo() #0 151 152 %cmp0 = call i1 @llvm.experimental.constrained.fcmps.f32( 153 float %ret, float %val0, 154 metadata !"olt", 155 metadata !"fpexcept.strict") #0 156 %cmp1 = call i1 @llvm.experimental.constrained.fcmps.f32( 157 float %ret, float %val1, 158 metadata !"olt", 159 metadata !"fpexcept.strict") #0 160 %cmp2 = call i1 @llvm.experimental.constrained.fcmps.f32( 161 float %ret, float %val2, 162 metadata !"olt", 163 metadata !"fpexcept.strict") #0 164 %cmp3 = call i1 @llvm.experimental.constrained.fcmps.f32( 165 float %ret, float %val3, 166 metadata !"olt", 167 metadata !"fpexcept.strict") #0 168 %cmp4 = call i1 @llvm.experimental.constrained.fcmps.f32( 169 float %ret, float %val4, 170 metadata !"olt", 171 metadata !"fpexcept.strict") #0 172 %cmp5 = call i1 @llvm.experimental.constrained.fcmps.f32( 173 float %ret, float %val5, 174 metadata !"olt", 175 metadata !"fpexcept.strict") #0 176 %cmp6 = call i1 @llvm.experimental.constrained.fcmps.f32( 177 float %ret, float %val6, 178 metadata !"olt", 179 metadata !"fpexcept.strict") #0 180 %cmp7 = call i1 @llvm.experimental.constrained.fcmps.f32( 181 float %ret, float %val7, 182 metadata !"olt", 183 metadata !"fpexcept.strict") #0 184 %cmp8 = call i1 @llvm.experimental.constrained.fcmps.f32( 185 float %ret, float %val8, 186 metadata !"olt", 187 metadata !"fpexcept.strict") #0 188 %cmp9 = call i1 @llvm.experimental.constrained.fcmps.f32( 189 float %ret, float %val9, 190 metadata !"olt", 191 metadata !"fpexcept.strict") #0 192 %cmp10 = call i1 @llvm.experimental.constrained.fcmps.f32( 193 float %ret, float %val10, 194 metadata !"olt", 195 metadata !"fpexcept.strict") #0 196 197 %sel0 = select i1 %cmp0, float %ret, float 0.0 198 %sel1 = select i1 %cmp1, float %sel0, float 1.0 199 %sel2 = select i1 %cmp2, float %sel1, float 2.0 200 %sel3 = select i1 %cmp3, float %sel2, float 3.0 201 %sel4 = select i1 %cmp4, float %sel3, float 4.0 202 %sel5 = select i1 %cmp5, float %sel4, float 5.0 203 %sel6 = select i1 %cmp6, float %sel5, float 6.0 204 %sel7 = select i1 %cmp7, float %sel6, float 7.0 205 %sel8 = select i1 %cmp8, float %sel7, float 8.0 206 %sel9 = select i1 %cmp9, float %sel8, float 9.0 207 %sel10 = select i1 %cmp10, float %sel9, float 10.0 208 209 ret float %sel10 210} 211 212; Check comparison with zero - cannot use LOAD AND TEST. 213define i64 @f8(i64 %a, i64 %b, float %f) #0 { 214; CHECK-LABEL: f8: 215; CHECK: lzer [[REG:%f[0-9]+]] 216; CHECK-NEXT: kebr %f0, [[REG]] 217; CHECK-SCALAR-NEXT: ber %r14 218; CHECK-SCALAR: lgr %r2, %r3 219; CHECK-VECTOR-NEXT: locgrne %r2, %r3 220; CHECK: br %r14 221 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 222 float %f, float 0.0, 223 metadata !"oeq", 224 metadata !"fpexcept.strict") #0 225 %res = select i1 %cond, i64 %a, i64 %b 226 ret i64 %res 227} 228 229; Check the comparison can be reversed if that allows KEB to be used, 230; first with oeq. 231define i64 @f9(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 232; CHECK-LABEL: f9: 233; CHECK: keb %f0, 0(%r4) 234; CHECK-SCALAR-NEXT: ber %r14 235; CHECK-SCALAR: lgr %r2, %r3 236; CHECK-VECTOR-NEXT: locgrne %r2, %r3 237; CHECK: br %r14 238 %f1 = load float, float *%ptr 239 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 240 float %f1, float %f2, 241 metadata !"oeq", 242 metadata !"fpexcept.strict") #0 243 %res = select i1 %cond, i64 %a, i64 %b 244 ret i64 %res 245} 246 247; ...then one. 248define i64 @f10(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 249; CHECK-LABEL: f10: 250; CHECK: keb %f0, 0(%r4) 251; CHECK-SCALAR-NEXT: blhr %r14 252; CHECK-SCALAR: lgr %r2, %r3 253; CHECK-VECTOR-NEXT: locgrnlh %r2, %r3 254; CHECK: br %r14 255 %f1 = load float, float *%ptr 256 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 257 float %f1, float %f2, 258 metadata !"one", 259 metadata !"fpexcept.strict") #0 260 %res = select i1 %cond, i64 %a, i64 %b 261 ret i64 %res 262} 263 264; ...then olt. 265define i64 @f11(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 266; CHECK-LABEL: f11: 267; CHECK: keb %f0, 0(%r4) 268; CHECK-SCALAR-NEXT: bhr %r14 269; CHECK-SCALAR: lgr %r2, %r3 270; CHECK-VECTOR-NEXT: locgrnh %r2, %r3 271; CHECK: br %r14 272 %f1 = load float, float *%ptr 273 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 274 float %f1, float %f2, 275 metadata !"olt", 276 metadata !"fpexcept.strict") #0 277 %res = select i1 %cond, i64 %a, i64 %b 278 ret i64 %res 279} 280 281; ...then ole. 282define i64 @f12(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 283; CHECK-LABEL: f12: 284; CHECK: keb %f0, 0(%r4) 285; CHECK-SCALAR-NEXT: bher %r14 286; CHECK-SCALAR: lgr %r2, %r3 287; CHECK-VECTOR-NEXT: locgrnhe %r2, %r3 288; CHECK: br %r14 289 %f1 = load float, float *%ptr 290 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 291 float %f1, float %f2, 292 metadata !"ole", 293 metadata !"fpexcept.strict") #0 294 %res = select i1 %cond, i64 %a, i64 %b 295 ret i64 %res 296} 297 298; ...then oge. 299define i64 @f13(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 300; CHECK-LABEL: f13: 301; CHECK: keb %f0, 0(%r4) 302; CHECK-SCALAR-NEXT: bler %r14 303; CHECK-SCALAR: lgr %r2, %r3 304; CHECK-VECTOR-NEXT: locgrnle %r2, %r3 305; CHECK: br %r14 306 %f1 = load float, float *%ptr 307 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 308 float %f1, float %f2, 309 metadata !"oge", 310 metadata !"fpexcept.strict") #0 311 %res = select i1 %cond, i64 %a, i64 %b 312 ret i64 %res 313} 314 315; ...then ogt. 316define i64 @f14(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 317; CHECK-LABEL: f14: 318; CHECK: keb %f0, 0(%r4) 319; CHECK-SCALAR-NEXT: blr %r14 320; CHECK-SCALAR: lgr %r2, %r3 321; CHECK-VECTOR-NEXT: locgrnl %r2, %r3 322; CHECK: br %r14 323 %f1 = load float, float *%ptr 324 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 325 float %f1, float %f2, 326 metadata !"ogt", 327 metadata !"fpexcept.strict") #0 328 %res = select i1 %cond, i64 %a, i64 %b 329 ret i64 %res 330} 331 332; ...then ueq. 333define i64 @f15(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 334; CHECK-LABEL: f15: 335; CHECK: keb %f0, 0(%r4) 336; CHECK-SCALAR-NEXT: bnlhr %r14 337; CHECK-SCALAR: lgr %r2, %r3 338; CHECK-VECTOR-NEXT: locgrlh %r2, %r3 339; CHECK: br %r14 340 %f1 = load float, float *%ptr 341 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 342 float %f1, float %f2, 343 metadata !"ueq", 344 metadata !"fpexcept.strict") #0 345 %res = select i1 %cond, i64 %a, i64 %b 346 ret i64 %res 347} 348 349; ...then une. 350define i64 @f16(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 351; CHECK-LABEL: f16: 352; CHECK: keb %f0, 0(%r4) 353; CHECK-SCALAR-NEXT: bner %r14 354; CHECK-SCALAR: lgr %r2, %r3 355; CHECK-VECTOR-NEXT: locgre %r2, %r3 356; CHECK: br %r14 357 %f1 = load float, float *%ptr 358 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 359 float %f1, float %f2, 360 metadata !"une", 361 metadata !"fpexcept.strict") #0 362 %res = select i1 %cond, i64 %a, i64 %b 363 ret i64 %res 364} 365 366; ...then ult. 367define i64 @f17(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 368; CHECK-LABEL: f17: 369; CHECK: keb %f0, 0(%r4) 370; CHECK-SCALAR-NEXT: bnler %r14 371; CHECK-SCALAR: lgr %r2, %r3 372; CHECK-VECTOR-NEXT: locgrle %r2, %r3 373; CHECK: br %r14 374 %f1 = load float, float *%ptr 375 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 376 float %f1, float %f2, 377 metadata !"ult", 378 metadata !"fpexcept.strict") #0 379 %res = select i1 %cond, i64 %a, i64 %b 380 ret i64 %res 381} 382 383; ...then ule. 384define i64 @f18(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 385; CHECK-LABEL: f18: 386; CHECK: keb %f0, 0(%r4) 387; CHECK-SCALAR-NEXT: bnlr %r14 388; CHECK-SCALAR: lgr %r2, %r3 389; CHECK-VECTOR-NEXT: locgrl %r2, %r3 390; CHECK: br %r14 391 %f1 = load float, float *%ptr 392 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 393 float %f1, float %f2, 394 metadata !"ule", 395 metadata !"fpexcept.strict") #0 396 %res = select i1 %cond, i64 %a, i64 %b 397 ret i64 %res 398} 399 400; ...then uge. 401define i64 @f19(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 402; CHECK-LABEL: f19: 403; CHECK: keb %f0, 0(%r4) 404; CHECK-SCALAR-NEXT: bnhr %r14 405; CHECK-SCALAR: lgr %r2, %r3 406; CHECK-VECTOR-NEXT: locgrh %r2, %r3 407; CHECK: br %r14 408 %f1 = load float, float *%ptr 409 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 410 float %f1, float %f2, 411 metadata !"uge", 412 metadata !"fpexcept.strict") #0 413 %res = select i1 %cond, i64 %a, i64 %b 414 ret i64 %res 415} 416 417; ...then ugt. 418define i64 @f20(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 419; CHECK-LABEL: f20: 420; CHECK: keb %f0, 0(%r4) 421; CHECK-SCALAR-NEXT: bnher %r14 422; CHECK-SCALAR: lgr %r2, %r3 423; CHECK-VECTOR-NEXT: locgrhe %r2, %r3 424; CHECK: br %r14 425 %f1 = load float, float *%ptr 426 %cond = call i1 @llvm.experimental.constrained.fcmps.f32( 427 float %f1, float %f2, 428 metadata !"ugt", 429 metadata !"fpexcept.strict") #0 430 %res = select i1 %cond, i64 %a, i64 %b 431 ret i64 %res 432} 433 434attributes #0 = { strictfp } 435 436declare i1 @llvm.experimental.constrained.fcmps.f32(float, float, metadata, metadata) 437