436 lines · plain
1; Test 32-bit floating-point strict comparison. The tests assume a z102; 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 %s6; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 \7; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-VECTOR %s8 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, %f215; CHECK-SCALAR-NEXT: ber %r1416; CHECK-SCALAR: lgr %r2, %r317; CHECK-VECTOR-NEXT: locgrne %r2, %r318; CHECK: br %r1419 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(20 float %f1, float %f2,21 metadata !"oeq",22 metadata !"fpexcept.strict") #023 %res = select i1 %cond, i64 %a, i64 %b24 ret i64 %res25}26 27; Check the low end of the CEB range.28define i64 @f2(i64 %a, i64 %b, float %f1, ptr %ptr) #0 {29; CHECK-LABEL: f2:30; CHECK: ceb %f0, 0(%r4)31; CHECK-SCALAR-NEXT: ber %r1432; CHECK-SCALAR: lgr %r2, %r333; CHECK-VECTOR-NEXT: locgrne %r2, %r334; CHECK: br %r1435 %f2 = load float, ptr %ptr36 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(37 float %f1, float %f2,38 metadata !"oeq",39 metadata !"fpexcept.strict") #040 %res = select i1 %cond, i64 %a, i64 %b41 ret i64 %res42}43 44; Check the high end of the aligned CEB range.45define i64 @f3(i64 %a, i64 %b, float %f1, ptr %base) #0 {46; CHECK-LABEL: f3:47; CHECK: ceb %f0, 4092(%r4)48; CHECK-SCALAR-NEXT: ber %r1449; CHECK-SCALAR: lgr %r2, %r350; CHECK-VECTOR-NEXT: locgrne %r2, %r351; CHECK: br %r1452 %ptr = getelementptr float, ptr %base, i64 102353 %f2 = load float, ptr %ptr54 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(55 float %f1, float %f2,56 metadata !"oeq",57 metadata !"fpexcept.strict") #058 %res = select i1 %cond, i64 %a, i64 %b59 ret i64 %res60}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, ptr %base) #0 {65; CHECK-LABEL: f4:66; CHECK: aghi %r4, 409667; CHECK: ceb %f0, 0(%r4)68; CHECK-SCALAR-NEXT: ber %r1469; CHECK-SCALAR: lgr %r2, %r370; CHECK-VECTOR-NEXT: locgrne %r2, %r371; CHECK: br %r1472 %ptr = getelementptr float, ptr %base, i64 102473 %f2 = load float, ptr %ptr74 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(75 float %f1, float %f2,76 metadata !"oeq",77 metadata !"fpexcept.strict") #078 %res = select i1 %cond, i64 %a, i64 %b79 ret i64 %res80}81 82; Check negative displacements, which also need separate address logic.83define i64 @f5(i64 %a, i64 %b, float %f1, ptr %base) #0 {84; CHECK-LABEL: f5:85; CHECK: aghi %r4, -486; CHECK: ceb %f0, 0(%r4)87; CHECK-SCALAR-NEXT: ber %r1488; CHECK-SCALAR: lgr %r2, %r389; CHECK-VECTOR-NEXT: locgrne %r2, %r390; CHECK: br %r1491 %ptr = getelementptr float, ptr %base, i64 -192 %f2 = load float, ptr %ptr93 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(94 float %f1, float %f2,95 metadata !"oeq",96 metadata !"fpexcept.strict") #097 %res = select i1 %cond, i64 %a, i64 %b98 ret i64 %res99}100 101; Check that CEB allows indices.102define i64 @f6(i64 %a, i64 %b, float %f1, ptr %base, i64 %index) #0 {103; CHECK-LABEL: f6:104; CHECK: sllg %r1, %r5, 2105; CHECK: ceb %f0, 400(%r1,%r4)106; CHECK-SCALAR-NEXT: ber %r14107; CHECK-SCALAR: lgr %r2, %r3108; CHECK-VECTOR-NEXT: locgrne %r2, %r3109; CHECK: br %r14110 %ptr1 = getelementptr float, ptr %base, i64 %index111 %ptr2 = getelementptr float, ptr %ptr1, i64 100112 %f2 = load float, ptr %ptr2113 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(114 float %f1, float %f2,115 metadata !"oeq",116 metadata !"fpexcept.strict") #0117 %res = select i1 %cond, i64 %a, i64 %b118 ret i64 %res119}120 121; Check that comparisons of spilled values can use CEB rather than CEBR.122define float @f7(ptr %ptr0) #0 {123; CHECK-LABEL: f7:124; CHECK: brasl %r14, foo@PLT125; CHECK-SCALAR: ceb {{%f[0-9]+}}, 16{{[04]}}(%r15)126; CHECK: br %r14127 %ptr1 = getelementptr float, ptr %ptr0, i64 2128 %ptr2 = getelementptr float, ptr %ptr0, i64 4129 %ptr3 = getelementptr float, ptr %ptr0, i64 6130 %ptr4 = getelementptr float, ptr %ptr0, i64 8131 %ptr5 = getelementptr float, ptr %ptr0, i64 10132 %ptr6 = getelementptr float, ptr %ptr0, i64 12133 %ptr7 = getelementptr float, ptr %ptr0, i64 14134 %ptr8 = getelementptr float, ptr %ptr0, i64 16135 %ptr9 = getelementptr float, ptr %ptr0, i64 18136 %ptr10 = getelementptr float, ptr %ptr0, i64 20137 138 %val0 = load float, ptr %ptr0139 %val1 = load float, ptr %ptr1140 %val2 = load float, ptr %ptr2141 %val3 = load float, ptr %ptr3142 %val4 = load float, ptr %ptr4143 %val5 = load float, ptr %ptr5144 %val6 = load float, ptr %ptr6145 %val7 = load float, ptr %ptr7146 %val8 = load float, ptr %ptr8147 %val9 = load float, ptr %ptr9148 %val10 = load float, ptr %ptr10149 150 %ret = call float @foo() #0151 152 %cmp0 = call i1 @llvm.experimental.constrained.fcmp.f32(153 float %ret, float %val0,154 metadata !"olt",155 metadata !"fpexcept.strict") #0156 %cmp1 = call i1 @llvm.experimental.constrained.fcmp.f32(157 float %ret, float %val1,158 metadata !"olt",159 metadata !"fpexcept.strict") #0160 %cmp2 = call i1 @llvm.experimental.constrained.fcmp.f32(161 float %ret, float %val2,162 metadata !"olt",163 metadata !"fpexcept.strict") #0164 %cmp3 = call i1 @llvm.experimental.constrained.fcmp.f32(165 float %ret, float %val3,166 metadata !"olt",167 metadata !"fpexcept.strict") #0168 %cmp4 = call i1 @llvm.experimental.constrained.fcmp.f32(169 float %ret, float %val4,170 metadata !"olt",171 metadata !"fpexcept.strict") #0172 %cmp5 = call i1 @llvm.experimental.constrained.fcmp.f32(173 float %ret, float %val5,174 metadata !"olt",175 metadata !"fpexcept.strict") #0176 %cmp6 = call i1 @llvm.experimental.constrained.fcmp.f32(177 float %ret, float %val6,178 metadata !"olt",179 metadata !"fpexcept.strict") #0180 %cmp7 = call i1 @llvm.experimental.constrained.fcmp.f32(181 float %ret, float %val7,182 metadata !"olt",183 metadata !"fpexcept.strict") #0184 %cmp8 = call i1 @llvm.experimental.constrained.fcmp.f32(185 float %ret, float %val8,186 metadata !"olt",187 metadata !"fpexcept.strict") #0188 %cmp9 = call i1 @llvm.experimental.constrained.fcmp.f32(189 float %ret, float %val9,190 metadata !"olt",191 metadata !"fpexcept.strict") #0192 %cmp10 = call i1 @llvm.experimental.constrained.fcmp.f32(193 float %ret, float %val10,194 metadata !"olt",195 metadata !"fpexcept.strict") #0196 197 %sel0 = select i1 %cmp0, float %ret, float 0.0198 %sel1 = select i1 %cmp1, float %sel0, float 1.0199 %sel2 = select i1 %cmp2, float %sel1, float 2.0200 %sel3 = select i1 %cmp3, float %sel2, float 3.0201 %sel4 = select i1 %cmp4, float %sel3, float 4.0202 %sel5 = select i1 %cmp5, float %sel4, float 5.0203 %sel6 = select i1 %cmp6, float %sel5, float 6.0204 %sel7 = select i1 %cmp7, float %sel6, float 7.0205 %sel8 = select i1 %cmp8, float %sel7, float 8.0206 %sel9 = select i1 %cmp9, float %sel8, float 9.0207 %sel10 = select i1 %cmp10, float %sel9, float 10.0208 209 ret float %sel10210}211 212; Check comparison with zero.213define i64 @f8(i64 %a, i64 %b, float %f) #0 {214; CHECK-LABEL: f8:215; CHECK: ltebr %f0, %f0216; CHECK-SCALAR-NEXT: ber %r14217; CHECK-SCALAR: lgr %r2, %r3218; CHECK-VECTOR-NEXT: locgrne %r2, %r3219; CHECK: br %r14220 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(221 float %f, float 0.0,222 metadata !"oeq",223 metadata !"fpexcept.strict") #0224 %res = select i1 %cond, i64 %a, i64 %b225 ret i64 %res226}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, ptr %ptr) #0 {231; CHECK-LABEL: f9:232; CHECK: ceb %f0, 0(%r4)233; CHECK-SCALAR-NEXT: ber %r14234; CHECK-SCALAR: lgr %r2, %r3235; CHECK-VECTOR-NEXT: locgrne %r2, %r3236; CHECK: br %r14237 %f1 = load float, ptr %ptr238 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(239 float %f1, float %f2,240 metadata !"oeq",241 metadata !"fpexcept.strict") #0242 %res = select i1 %cond, i64 %a, i64 %b243 ret i64 %res244}245 246; ...then one.247define i64 @f10(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {248; CHECK-LABEL: f10:249; CHECK: ceb %f0, 0(%r4)250; CHECK-SCALAR-NEXT: blhr %r14251; CHECK-SCALAR: lgr %r2, %r3252; CHECK-VECTOR-NEXT: locgrnlh %r2, %r3253; CHECK: br %r14254 %f1 = load float, ptr %ptr255 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(256 float %f1, float %f2,257 metadata !"one",258 metadata !"fpexcept.strict") #0259 %res = select i1 %cond, i64 %a, i64 %b260 ret i64 %res261}262 263; ...then olt.264define i64 @f11(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {265; CHECK-LABEL: f11:266; CHECK: ceb %f0, 0(%r4)267; CHECK-SCALAR-NEXT: bhr %r14268; CHECK-SCALAR: lgr %r2, %r3269; CHECK-VECTOR-NEXT: locgrnh %r2, %r3270; CHECK: br %r14271 %f1 = load float, ptr %ptr272 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(273 float %f1, float %f2,274 metadata !"olt",275 metadata !"fpexcept.strict") #0276 %res = select i1 %cond, i64 %a, i64 %b277 ret i64 %res278}279 280; ...then ole.281define i64 @f12(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {282; CHECK-LABEL: f12:283; CHECK: ceb %f0, 0(%r4)284; CHECK-SCALAR-NEXT: bher %r14285; CHECK-SCALAR: lgr %r2, %r3286; CHECK-VECTOR-NEXT: locgrnhe %r2, %r3287; CHECK: br %r14288 %f1 = load float, ptr %ptr289 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(290 float %f1, float %f2,291 metadata !"ole",292 metadata !"fpexcept.strict") #0293 %res = select i1 %cond, i64 %a, i64 %b294 ret i64 %res295}296 297; ...then oge.298define i64 @f13(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {299; CHECK-LABEL: f13:300; CHECK: ceb %f0, 0(%r4)301; CHECK-SCALAR-NEXT: bler %r14302; CHECK-SCALAR: lgr %r2, %r3303; CHECK-VECTOR-NEXT: locgrnle %r2, %r3304; CHECK: br %r14305 %f1 = load float, ptr %ptr306 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(307 float %f1, float %f2,308 metadata !"oge",309 metadata !"fpexcept.strict") #0310 %res = select i1 %cond, i64 %a, i64 %b311 ret i64 %res312}313 314; ...then ogt.315define i64 @f14(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {316; CHECK-LABEL: f14:317; CHECK: ceb %f0, 0(%r4)318; CHECK-SCALAR-NEXT: blr %r14319; CHECK-SCALAR: lgr %r2, %r3320; CHECK-VECTOR-NEXT: locgrnl %r2, %r3321; CHECK: br %r14322 %f1 = load float, ptr %ptr323 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(324 float %f1, float %f2,325 metadata !"ogt",326 metadata !"fpexcept.strict") #0327 %res = select i1 %cond, i64 %a, i64 %b328 ret i64 %res329}330 331; ...then ueq.332define i64 @f15(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {333; CHECK-LABEL: f15:334; CHECK: ceb %f0, 0(%r4)335; CHECK-SCALAR-NEXT: bnlhr %r14336; CHECK-SCALAR: lgr %r2, %r3337; CHECK-VECTOR-NEXT: locgrlh %r2, %r3338; CHECK: br %r14339 %f1 = load float, ptr %ptr340 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(341 float %f1, float %f2,342 metadata !"ueq",343 metadata !"fpexcept.strict") #0344 %res = select i1 %cond, i64 %a, i64 %b345 ret i64 %res346}347 348; ...then une.349define i64 @f16(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {350; CHECK-LABEL: f16:351; CHECK: ceb %f0, 0(%r4)352; CHECK-SCALAR-NEXT: bner %r14353; CHECK-SCALAR: lgr %r2, %r3354; CHECK-VECTOR-NEXT: locgre %r2, %r3355; CHECK: br %r14356 %f1 = load float, ptr %ptr357 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(358 float %f1, float %f2,359 metadata !"une",360 metadata !"fpexcept.strict") #0361 %res = select i1 %cond, i64 %a, i64 %b362 ret i64 %res363}364 365; ...then ult.366define i64 @f17(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {367; CHECK-LABEL: f17:368; CHECK: ceb %f0, 0(%r4)369; CHECK-SCALAR-NEXT: bnler %r14370; CHECK-SCALAR: lgr %r2, %r3371; CHECK-VECTOR-NEXT: locgrle %r2, %r3372; CHECK: br %r14373 %f1 = load float, ptr %ptr374 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(375 float %f1, float %f2,376 metadata !"ult",377 metadata !"fpexcept.strict") #0378 %res = select i1 %cond, i64 %a, i64 %b379 ret i64 %res380}381 382; ...then ule.383define i64 @f18(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {384; CHECK-LABEL: f18:385; CHECK: ceb %f0, 0(%r4)386; CHECK-SCALAR-NEXT: bnlr %r14387; CHECK-SCALAR: lgr %r2, %r3388; CHECK-VECTOR-NEXT: locgrl %r2, %r3389; CHECK: br %r14390 %f1 = load float, ptr %ptr391 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(392 float %f1, float %f2,393 metadata !"ule",394 metadata !"fpexcept.strict") #0395 %res = select i1 %cond, i64 %a, i64 %b396 ret i64 %res397}398 399; ...then uge.400define i64 @f19(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {401; CHECK-LABEL: f19:402; CHECK: ceb %f0, 0(%r4)403; CHECK-SCALAR-NEXT: bnhr %r14404; CHECK-SCALAR: lgr %r2, %r3405; CHECK-VECTOR-NEXT: locgrh %r2, %r3406; CHECK: br %r14407 %f1 = load float, ptr %ptr408 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(409 float %f1, float %f2,410 metadata !"uge",411 metadata !"fpexcept.strict") #0412 %res = select i1 %cond, i64 %a, i64 %b413 ret i64 %res414}415 416; ...then ugt.417define i64 @f20(i64 %a, i64 %b, float %f2, ptr %ptr) #0 {418; CHECK-LABEL: f20:419; CHECK: ceb %f0, 0(%r4)420; CHECK-SCALAR-NEXT: bnher %r14421; CHECK-SCALAR: lgr %r2, %r3422; CHECK-VECTOR-NEXT: locgrhe %r2, %r3423; CHECK: br %r14424 %f1 = load float, ptr %ptr425 %cond = call i1 @llvm.experimental.constrained.fcmp.f32(426 float %f1, float %f2,427 metadata !"ugt",428 metadata !"fpexcept.strict") #0429 %res = select i1 %cond, i64 %a, i64 %b430 ret i64 %res431}432 433attributes #0 = { strictfp }434 435declare i1 @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata)436