1; Test 32-bit floating-point strict 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: cebr %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.fcmp.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 CEB range. 28define i64 @f2(i64 %a, i64 %b, float %f1, float *%ptr) #0 { 29; CHECK-LABEL: f2: 30; CHECK: ceb %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.fcmp.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 CEB range. 45define i64 @f3(i64 %a, i64 %b, float %f1, float *%base) #0 { 46; CHECK-LABEL: f3: 47; CHECK: ceb %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.fcmp.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: ceb %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.fcmp.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: ceb %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.fcmp.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 CEB 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: ceb %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.fcmp.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 CEB rather than CEBR. 122define float @f7(float *%ptr0) #0 { 123; CHECK-LABEL: f7: 124; CHECK: brasl %r14, foo@PLT 125; CHECK-SCALAR: ceb {{%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.fcmp.f32( 153 float %ret, float %val0, 154 metadata !"olt", 155 metadata !"fpexcept.strict") #0 156 %cmp1 = call i1 @llvm.experimental.constrained.fcmp.f32( 157 float %ret, float %val1, 158 metadata !"olt", 159 metadata !"fpexcept.strict") #0 160 %cmp2 = call i1 @llvm.experimental.constrained.fcmp.f32( 161 float %ret, float %val2, 162 metadata !"olt", 163 metadata !"fpexcept.strict") #0 164 %cmp3 = call i1 @llvm.experimental.constrained.fcmp.f32( 165 float %ret, float %val3, 166 metadata !"olt", 167 metadata !"fpexcept.strict") #0 168 %cmp4 = call i1 @llvm.experimental.constrained.fcmp.f32( 169 float %ret, float %val4, 170 metadata !"olt", 171 metadata !"fpexcept.strict") #0 172 %cmp5 = call i1 @llvm.experimental.constrained.fcmp.f32( 173 float %ret, float %val5, 174 metadata !"olt", 175 metadata !"fpexcept.strict") #0 176 %cmp6 = call i1 @llvm.experimental.constrained.fcmp.f32( 177 float %ret, float %val6, 178 metadata !"olt", 179 metadata !"fpexcept.strict") #0 180 %cmp7 = call i1 @llvm.experimental.constrained.fcmp.f32( 181 float %ret, float %val7, 182 metadata !"olt", 183 metadata !"fpexcept.strict") #0 184 %cmp8 = call i1 @llvm.experimental.constrained.fcmp.f32( 185 float %ret, float %val8, 186 metadata !"olt", 187 metadata !"fpexcept.strict") #0 188 %cmp9 = call i1 @llvm.experimental.constrained.fcmp.f32( 189 float %ret, float %val9, 190 metadata !"olt", 191 metadata !"fpexcept.strict") #0 192 %cmp10 = call i1 @llvm.experimental.constrained.fcmp.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. 213define i64 @f8(i64 %a, i64 %b, float %f) #0 { 214; CHECK-LABEL: f8: 215; CHECK: ltebr %f0, %f0 216; CHECK-SCALAR-NEXT: ber %r14 217; CHECK-SCALAR: lgr %r2, %r3 218; CHECK-VECTOR-NEXT: locgrne %r2, %r3 219; CHECK: br %r14 220 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 221 float %f, float 0.0, 222 metadata !"oeq", 223 metadata !"fpexcept.strict") #0 224 %res = select i1 %cond, i64 %a, i64 %b 225 ret i64 %res 226} 227 228; Check the comparison can be reversed if that allows CEB to be used, 229; first with oeq. 230define i64 @f9(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 231; CHECK-LABEL: f9: 232; CHECK: ceb %f0, 0(%r4) 233; CHECK-SCALAR-NEXT: ber %r14 234; CHECK-SCALAR: lgr %r2, %r3 235; CHECK-VECTOR-NEXT: locgrne %r2, %r3 236; CHECK: br %r14 237 %f1 = load float, float *%ptr 238 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 239 float %f1, float %f2, 240 metadata !"oeq", 241 metadata !"fpexcept.strict") #0 242 %res = select i1 %cond, i64 %a, i64 %b 243 ret i64 %res 244} 245 246; ...then one. 247define i64 @f10(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 248; CHECK-LABEL: f10: 249; CHECK: ceb %f0, 0(%r4) 250; CHECK-SCALAR-NEXT: blhr %r14 251; CHECK-SCALAR: lgr %r2, %r3 252; CHECK-VECTOR-NEXT: locgrnlh %r2, %r3 253; CHECK: br %r14 254 %f1 = load float, float *%ptr 255 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 256 float %f1, float %f2, 257 metadata !"one", 258 metadata !"fpexcept.strict") #0 259 %res = select i1 %cond, i64 %a, i64 %b 260 ret i64 %res 261} 262 263; ...then olt. 264define i64 @f11(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 265; CHECK-LABEL: f11: 266; CHECK: ceb %f0, 0(%r4) 267; CHECK-SCALAR-NEXT: bhr %r14 268; CHECK-SCALAR: lgr %r2, %r3 269; CHECK-VECTOR-NEXT: locgrnh %r2, %r3 270; CHECK: br %r14 271 %f1 = load float, float *%ptr 272 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 273 float %f1, float %f2, 274 metadata !"olt", 275 metadata !"fpexcept.strict") #0 276 %res = select i1 %cond, i64 %a, i64 %b 277 ret i64 %res 278} 279 280; ...then ole. 281define i64 @f12(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 282; CHECK-LABEL: f12: 283; CHECK: ceb %f0, 0(%r4) 284; CHECK-SCALAR-NEXT: bher %r14 285; CHECK-SCALAR: lgr %r2, %r3 286; CHECK-VECTOR-NEXT: locgrnhe %r2, %r3 287; CHECK: br %r14 288 %f1 = load float, float *%ptr 289 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 290 float %f1, float %f2, 291 metadata !"ole", 292 metadata !"fpexcept.strict") #0 293 %res = select i1 %cond, i64 %a, i64 %b 294 ret i64 %res 295} 296 297; ...then oge. 298define i64 @f13(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 299; CHECK-LABEL: f13: 300; CHECK: ceb %f0, 0(%r4) 301; CHECK-SCALAR-NEXT: bler %r14 302; CHECK-SCALAR: lgr %r2, %r3 303; CHECK-VECTOR-NEXT: locgrnle %r2, %r3 304; CHECK: br %r14 305 %f1 = load float, float *%ptr 306 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 307 float %f1, float %f2, 308 metadata !"oge", 309 metadata !"fpexcept.strict") #0 310 %res = select i1 %cond, i64 %a, i64 %b 311 ret i64 %res 312} 313 314; ...then ogt. 315define i64 @f14(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 316; CHECK-LABEL: f14: 317; CHECK: ceb %f0, 0(%r4) 318; CHECK-SCALAR-NEXT: blr %r14 319; CHECK-SCALAR: lgr %r2, %r3 320; CHECK-VECTOR-NEXT: locgrnl %r2, %r3 321; CHECK: br %r14 322 %f1 = load float, float *%ptr 323 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 324 float %f1, float %f2, 325 metadata !"ogt", 326 metadata !"fpexcept.strict") #0 327 %res = select i1 %cond, i64 %a, i64 %b 328 ret i64 %res 329} 330 331; ...then ueq. 332define i64 @f15(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 333; CHECK-LABEL: f15: 334; CHECK: ceb %f0, 0(%r4) 335; CHECK-SCALAR-NEXT: bnlhr %r14 336; CHECK-SCALAR: lgr %r2, %r3 337; CHECK-VECTOR-NEXT: locgrlh %r2, %r3 338; CHECK: br %r14 339 %f1 = load float, float *%ptr 340 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 341 float %f1, float %f2, 342 metadata !"ueq", 343 metadata !"fpexcept.strict") #0 344 %res = select i1 %cond, i64 %a, i64 %b 345 ret i64 %res 346} 347 348; ...then une. 349define i64 @f16(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 350; CHECK-LABEL: f16: 351; CHECK: ceb %f0, 0(%r4) 352; CHECK-SCALAR-NEXT: bner %r14 353; CHECK-SCALAR: lgr %r2, %r3 354; CHECK-VECTOR-NEXT: locgre %r2, %r3 355; CHECK: br %r14 356 %f1 = load float, float *%ptr 357 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 358 float %f1, float %f2, 359 metadata !"une", 360 metadata !"fpexcept.strict") #0 361 %res = select i1 %cond, i64 %a, i64 %b 362 ret i64 %res 363} 364 365; ...then ult. 366define i64 @f17(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 367; CHECK-LABEL: f17: 368; CHECK: ceb %f0, 0(%r4) 369; CHECK-SCALAR-NEXT: bnler %r14 370; CHECK-SCALAR: lgr %r2, %r3 371; CHECK-VECTOR-NEXT: locgrle %r2, %r3 372; CHECK: br %r14 373 %f1 = load float, float *%ptr 374 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 375 float %f1, float %f2, 376 metadata !"ult", 377 metadata !"fpexcept.strict") #0 378 %res = select i1 %cond, i64 %a, i64 %b 379 ret i64 %res 380} 381 382; ...then ule. 383define i64 @f18(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 384; CHECK-LABEL: f18: 385; CHECK: ceb %f0, 0(%r4) 386; CHECK-SCALAR-NEXT: bnlr %r14 387; CHECK-SCALAR: lgr %r2, %r3 388; CHECK-VECTOR-NEXT: locgrl %r2, %r3 389; CHECK: br %r14 390 %f1 = load float, float *%ptr 391 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 392 float %f1, float %f2, 393 metadata !"ule", 394 metadata !"fpexcept.strict") #0 395 %res = select i1 %cond, i64 %a, i64 %b 396 ret i64 %res 397} 398 399; ...then uge. 400define i64 @f19(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 401; CHECK-LABEL: f19: 402; CHECK: ceb %f0, 0(%r4) 403; CHECK-SCALAR-NEXT: bnhr %r14 404; CHECK-SCALAR: lgr %r2, %r3 405; CHECK-VECTOR-NEXT: locgrh %r2, %r3 406; CHECK: br %r14 407 %f1 = load float, float *%ptr 408 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 409 float %f1, float %f2, 410 metadata !"uge", 411 metadata !"fpexcept.strict") #0 412 %res = select i1 %cond, i64 %a, i64 %b 413 ret i64 %res 414} 415 416; ...then ugt. 417define i64 @f20(i64 %a, i64 %b, float %f2, float *%ptr) #0 { 418; CHECK-LABEL: f20: 419; CHECK: ceb %f0, 0(%r4) 420; CHECK-SCALAR-NEXT: bnher %r14 421; CHECK-SCALAR: lgr %r2, %r3 422; CHECK-VECTOR-NEXT: locgrhe %r2, %r3 423; CHECK: br %r14 424 %f1 = load float, float *%ptr 425 %cond = call i1 @llvm.experimental.constrained.fcmp.f32( 426 float %f1, float %f2, 427 metadata !"ugt", 428 metadata !"fpexcept.strict") #0 429 %res = select i1 %cond, i64 %a, i64 %b 430 ret i64 %res 431} 432 433attributes #0 = { strictfp } 434 435declare i1 @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata) 436