479 lines · plain
1; Test that floating-point compares are omitted if CC already has the2; right value.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as | FileCheck %s5 6declare float @llvm.fabs.f32(float %f)7 8; Test addition followed by EQ, which can use the CC result of the addition.9define float @f1(float %a, float %b, ptr %dest) {10; CHECK-LABEL: f1:11; CHECK: aebr %f0, %f212; CHECK-NEXT: ber %r1413; CHECK: br %r1414entry:15 %res = fadd float %a, %b16 %cmp = fcmp oeq float %res, 0.017 br i1 %cmp, label %exit, label %store18 19store:20 store float %b, ptr %dest21 br label %exit22 23exit:24 ret float %res25}26 27; ...and again with LT.28define float @f2(float %a, float %b, ptr %dest) {29; CHECK-LABEL: f2:30; CHECK: aebr %f0, %f231; CHECK-NEXT: blr %r1432; CHECK: br %r1433entry:34 %res = fadd float %a, %b35 %cmp = fcmp olt float %res, 0.036 br i1 %cmp, label %exit, label %store37 38store:39 store float %b, ptr %dest40 br label %exit41 42exit:43 ret float %res44}45 46; ...and again with GT.47define float @f3(float %a, float %b, ptr %dest) {48; CHECK-LABEL: f3:49; CHECK: aebr %f0, %f250; CHECK-NEXT: bhr %r1451; CHECK: br %r1452entry:53 %res = fadd float %a, %b54 %cmp = fcmp ogt float %res, 0.055 br i1 %cmp, label %exit, label %store56 57store:58 store float %b, ptr %dest59 br label %exit60 61exit:62 ret float %res63}64 65; ...and again with UEQ.66define float @f4(float %a, float %b, ptr %dest) {67; CHECK-LABEL: f4:68; CHECK: aebr %f0, %f269; CHECK-NEXT: bnlhr %r1470; CHECK: br %r1471entry:72 %res = fadd float %a, %b73 %cmp = fcmp ueq float %res, 0.074 br i1 %cmp, label %exit, label %store75 76store:77 store float %b, ptr %dest78 br label %exit79 80exit:81 ret float %res82}83 84; Subtraction also provides a zero-based CC value.85define float @f5(float %a, float %b, ptr %dest) {86; CHECK-LABEL: f5:87; CHECK: seb %f0, 0(%r2)88; CHECK-NEXT: bnher %r1489; CHECK: br %r1490entry:91 %cur = load float, ptr %dest92 %res = fsub float %a, %cur93 %cmp = fcmp ult float %res, 0.094 br i1 %cmp, label %exit, label %store95 96store:97 store float %b, ptr %dest98 br label %exit99 100exit:101 ret float %res102}103 104; Test the result of LOAD POSITIVE.105define float @f6(float %dummy, float %a, ptr %dest) {106; CHECK-LABEL: f6:107; CHECK: lpebr %f0, %f2108; CHECK-NEXT: bhr %r14109; CHECK: br %r14110entry:111 %res = call float @llvm.fabs.f32(float %a)112 %cmp = fcmp ogt float %res, 0.0113 br i1 %cmp, label %exit, label %store114 115store:116 store float %res, ptr %dest117 br label %exit118 119exit:120 ret float %res121}122 123; Test the result of LOAD NEGATIVE.124define float @f7(float %dummy, float %a, ptr %dest) {125; CHECK-LABEL: f7:126; CHECK: lnebr %f0, %f2127; CHECK-NEXT: blr %r14128; CHECK: br %r14129entry:130 %abs = call float @llvm.fabs.f32(float %a)131 %res = fneg float %abs132 %cmp = fcmp olt float %res, 0.0133 br i1 %cmp, label %exit, label %store134 135store:136 store float %res, ptr %dest137 br label %exit138 139exit:140 ret float %res141}142 143; Test the result of LOAD COMPLEMENT.144define float @f8(float %dummy, float %a, ptr %dest) {145; CHECK-LABEL: f8:146; CHECK: lcebr %f0, %f2147; CHECK-NEXT: bler %r14148; CHECK: br %r14149entry:150 %res = fneg float %a151 %cmp = fcmp ole float %res, 0.0152 br i1 %cmp, label %exit, label %store153 154store:155 store float %res, ptr %dest156 br label %exit157 158exit:159 ret float %res160}161 162; Multiplication (for example) does not modify CC.163define float @f9(float %a, float %b, ptr %dest) {164; CHECK-LABEL: f9:165; CHECK: meebr %f0, %f2166; CHECK-NEXT: ltebr %f1, %f0167; CHECK-NEXT: blhr %r14168; CHECK: br %r14169entry:170 %res = fmul float %a, %b171 %cmp = fcmp one float %res, 0.0172 br i1 %cmp, label %exit, label %store173 174store:175 store float %b, ptr %dest176 br label %exit177 178exit:179 ret float %res180}181 182; Test a combination involving a CC-setting instruction followed by183; a non-CC-setting instruction.184define float @f10(float %a, float %b, float %c, ptr %dest) {185; CHECK-LABEL: f10:186; CHECK: aebr %f0, %f2187; CHECK-NEXT: debr %f0, %f4188; CHECK-NEXT: ltebr %f1, %f0189; CHECK-NEXT: bner %r14190; CHECK: br %r14191entry:192 %add = fadd float %a, %b193 %res = fdiv float %add, %c194 %cmp = fcmp une float %res, 0.0195 br i1 %cmp, label %exit, label %store196 197store:198 store float %b, ptr %dest199 br label %exit200 201exit:202 ret float %res203}204 205; Test a case where CC is set based on a different register from the206; compare input.207define float @f11(float %a, float %b, float %c, ptr %dest1, ptr %dest2) {208; CHECK-LABEL: f11:209; CHECK: aebr %f0, %f2210; CHECK-NEXT: sebr %f4, %f0211; CHECK-DAG: ste %f4, 0(%r2)212; CHECK-DAG: ltebr %f1, %f0213; CHECK-NEXT: ber %r14214; CHECK: br %r14215entry:216 %add = fadd float %a, %b217 %sub = fsub float %c, %add218 store float %sub, ptr %dest1219 %cmp = fcmp oeq float %add, 0.0220 br i1 %cmp, label %exit, label %store221 222store:223 store float %sub, ptr %dest2224 br label %exit225 226exit:227 ret float %add228}229 230define half @f12_half(half %dummy, half %val, ptr %dest) {231; CHECK-LABEL: f12_half:232; CHECK: ler %f8, %f2233; CHECK-NEXT: ler %f0, %f2234; CHECK-NEXT: #APP235; CHECK-NEXT: blah %f0236; CHECK-NEXT: #NO_APP237; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT238; CHECK-NEXT: ltebr %f1, %f0239; CHECK-NEXT: jl .LBB11_2240; CHECK-NEXT:# %bb.1:241; CHECK-NEXT: lgdr %r0, %f8242; CHECK-NEXT: srlg %r0, %r0, 48243; CHECK-NEXT: sth %r0, 0(%r13)244; CHECK-NEXT:.LBB11_2:245; CHECK-NEXT: ler %f0, %f8246; CHECK-NEXT: ld %f8, 160(%r15)247; CHECK-NEXT: lmg %r13, %r15, 272(%r15)248; CHECK-NEXT: br %r14249entry:250 call void asm sideeffect "blah $0", "{f0}"(half %val)251 %cmp = fcmp olt half %val, 0.0252 br i1 %cmp, label %exit, label %store253 254store:255 store half %val, ptr %dest256 br label %exit257 258exit:259 ret half %val260}261 262; %val in %f2 must be preserved during comparison and also copied to %f0.263define float @f12(float %dummy, float %val, ptr %dest) {264; CHECK-LABEL: f12:265; CHECK: ler %f0, %f2266; CHECK-NEXT: ltebr %f1, %f2267; CHECK-NEXT: #APP268; CHECK-NEXT: blah %f0269; CHECK-NEXT: #NO_APP270; CHECK-NEXT: blr %r14271; CHECK: br %r14272entry:273 call void asm sideeffect "blah $0", "{f0}"(float %val)274 %cmp = fcmp olt float %val, 0.0275 br i1 %cmp, label %exit, label %store276 277store:278 store float %val, ptr %dest279 br label %exit280 281exit:282 ret float %val283}284 285; Same for double.286define double @f13(double %dummy, double %val, ptr %dest) {287; CHECK-LABEL: f13:288; CHECK: ldr %f0, %f2289; CHECK-NEXT: ltdbr %f1, %f2290; CHECK-NEXT: #APP291; CHECK-NEXT: blah %f0292; CHECK-NEXT: #NO_APP293; CHECK-NEXT: blr %r14294; CHECK: br %r14295entry:296 call void asm sideeffect "blah $0", "{f0}"(double %val)297 %cmp = fcmp olt double %val, 0.0298 br i1 %cmp, label %exit, label %store299 300store:301 store double %val, ptr %dest302 br label %exit303 304exit:305 ret double %val306}307 308; LXR cannot be converted to LTXBR as its input is live after it.309define void @f14(ptr %ptr1, ptr %ptr2) {310; CHECK-LABEL: f14:311; CHECK: lxr312; CHECK-NEXT: dxbr313; CHECK-NEXT: std314; CHECK-NEXT: std315; CHECK-NEXT: mxbr316; CHECK-NEXT: ltxbr317; CHECK-NEXT: std318; CHECK-NEXT: std319; CHECK-NEXT: blr %r14320; CHECK: br %r14321entry:322 %val1 = load fp128, ptr %ptr1323 %val2 = load fp128, ptr %ptr2324 %div = fdiv fp128 %val1, %val2325 store fp128 %div, ptr %ptr1326 %mul = fmul fp128 %val1, %val2327 store fp128 %mul, ptr %ptr2328 %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000329 br i1 %cmp, label %exit, label %store330 331store:332 call void asm sideeffect "blah", ""()333 br label %exit334 335exit:336 ret void337}338 339define half @f15_half(half %val, half %dummy, ptr %dest) {340; CHECK-LABEL: f15_half:341; CHECK: ler %f8, %f0342; CHECK-NEXT: ler %f2, %f0343; CHECK-NEXT: #APP344; CHECK-NEXT: blah %f2345; CHECK-NEXT: #NO_APP346; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT347; CHECK-NEXT: ltebr %f1, %f0348; CHECK-NEXT: jl .LBB15_2349; CHECK-NEXT:# %bb.1:350; CHECK-NEXT: lgdr %r0, %f8351; CHECK-NEXT: srlg %r0, %r0, 48352; CHECK-NEXT: sth %r0, 0(%r13)353; CHECK-NEXT:.LBB15_2:354; CHECK-NEXT: ler %f0, %f8355; CHECK-NEXT: ld %f8, 160(%r15)356; CHECK-NEXT: lmg %r13, %r15, 272(%r15)357; CHECK-NEXT: br %r14358entry:359 call void asm sideeffect "blah $0", "{f2}"(half %val)360 %cmp = fcmp olt half %val, 0.0361 br i1 %cmp, label %exit, label %store362 363store:364 store half %val, ptr %dest365 br label %exit366 367exit:368 ret half %val369}370 371define float @f15(float %val, float %dummy, ptr %dest) {372; CHECK-LABEL: f15:373; CHECK: ltebr %f1, %f0374; CHECK-NEXT: ler %f2, %f0375; CHECK-NEXT: #APP376; CHECK-NEXT: blah %f2377; CHECK-NEXT: #NO_APP378; CHECK-NEXT: blr %r14379; CHECK: br %r14380entry:381 call void asm sideeffect "blah $0", "{f2}"(float %val)382 %cmp = fcmp olt float %val, 0.0383 br i1 %cmp, label %exit, label %store384 385store:386 store float %val, ptr %dest387 br label %exit388 389exit:390 ret float %val391}392 393define double @f16(double %val, double %dummy, ptr %dest) {394; CHECK-LABEL: f16:395; CHECK: ltdbr %f1, %f0396; CHECK: ldr %f2, %f0397; CHECK-NEXT: #APP398; CHECK-NEXT: blah %f2399; CHECK-NEXT: #NO_APP400; CHECK-NEXT: blr %r14401; CHECK: br %r14402entry:403 call void asm sideeffect "blah $0", "{f2}"(double %val)404 %cmp = fcmp olt double %val, 0.0405 br i1 %cmp, label %exit, label %store406 407store:408 store double %val, ptr %dest409 br label %exit410 411exit:412 ret double %val413}414 415; Repeat f2 with a comparison against -0.416define float @f17(float %a, float %b, ptr %dest) {417; CHECK-LABEL: f17:418; CHECK: aebr %f0, %f2419; CHECK-NEXT: blr %r14420; CHECK: br %r14421entry:422 %res = fadd float %a, %b423 %cmp = fcmp olt float %res, -0.0424 br i1 %cmp, label %exit, label %store425 426store:427 store float %b, ptr %dest428 br label %exit429 430exit:431 ret float %res432}433 434; Test another form of f7 in which the condition is based on the unnegated435; result. This is what InstCombine would produce.436define float @f18(float %dummy, float %a, ptr %dest) {437; CHECK-LABEL: f18:438; CHECK: # %bb.0: # %entry439; CHECK-NEXT: lnebr %f0, %f2440; CHECK-NEXT: blr %r14441; CHECK-NEXT: .LBB19_1: # %store442; CHECK-NEXT: ste %f0, 0(%r2)443; CHECK-NEXT: br %r14444entry:445 %abs = call float @llvm.fabs.f32(float %a)446 %res = fneg float %abs447 %cmp = fcmp ogt float %abs, 0.0448 br i1 %cmp, label %exit, label %store449 450store:451 store float %res, ptr %dest452 br label %exit453 454exit:455 ret float %res456}457 458; Similarly for f8.459define float @f19(float %dummy, float %a, ptr %dest) {460; CHECK-LABEL: f19:461; CHECK: # %bb.0: # %entry462; CHECK-NEXT: lcebr %f0, %f2463; CHECK-NEXT: bler %r14464; CHECK-NEXT: .LBB20_1: # %store465; CHECK-NEXT: ste %f0, 0(%r2)466; CHECK-NEXT: br %r14467entry:468 %res = fneg float %a469 %cmp = fcmp oge float %a, 0.0470 br i1 %cmp, label %exit, label %store471 472store:473 store float %res, ptr %dest474 br label %exit475 476exit:477 ret float %res478}479