1; Test that floating-point compares are omitted if CC already has the 2; right value. 3; 4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as | FileCheck %s 5 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, %f2 12; CHECK-NEXT: ber %r14 13; CHECK: br %r14 14entry: 15 %res = fadd float %a, %b 16 %cmp = fcmp oeq float %res, 0.0 17 br i1 %cmp, label %exit, label %store 18 19store: 20 store float %b, ptr %dest 21 br label %exit 22 23exit: 24 ret float %res 25} 26 27; ...and again with LT. 28define float @f2(float %a, float %b, ptr %dest) { 29; CHECK-LABEL: f2: 30; CHECK: aebr %f0, %f2 31; CHECK-NEXT: blr %r14 32; CHECK: br %r14 33entry: 34 %res = fadd float %a, %b 35 %cmp = fcmp olt float %res, 0.0 36 br i1 %cmp, label %exit, label %store 37 38store: 39 store float %b, ptr %dest 40 br label %exit 41 42exit: 43 ret float %res 44} 45 46; ...and again with GT. 47define float @f3(float %a, float %b, ptr %dest) { 48; CHECK-LABEL: f3: 49; CHECK: aebr %f0, %f2 50; CHECK-NEXT: bhr %r14 51; CHECK: br %r14 52entry: 53 %res = fadd float %a, %b 54 %cmp = fcmp ogt float %res, 0.0 55 br i1 %cmp, label %exit, label %store 56 57store: 58 store float %b, ptr %dest 59 br label %exit 60 61exit: 62 ret float %res 63} 64 65; ...and again with UEQ. 66define float @f4(float %a, float %b, ptr %dest) { 67; CHECK-LABEL: f4: 68; CHECK: aebr %f0, %f2 69; CHECK-NEXT: bnlhr %r14 70; CHECK: br %r14 71entry: 72 %res = fadd float %a, %b 73 %cmp = fcmp ueq float %res, 0.0 74 br i1 %cmp, label %exit, label %store 75 76store: 77 store float %b, ptr %dest 78 br label %exit 79 80exit: 81 ret float %res 82} 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 %r14 89; CHECK: br %r14 90entry: 91 %cur = load float, ptr %dest 92 %res = fsub float %a, %cur 93 %cmp = fcmp ult float %res, 0.0 94 br i1 %cmp, label %exit, label %store 95 96store: 97 store float %b, ptr %dest 98 br label %exit 99 100exit: 101 ret float %res 102} 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, %f2 108; CHECK-NEXT: bhr %r14 109; CHECK: br %r14 110entry: 111 %res = call float @llvm.fabs.f32(float %a) 112 %cmp = fcmp ogt float %res, 0.0 113 br i1 %cmp, label %exit, label %store 114 115store: 116 store float %res, ptr %dest 117 br label %exit 118 119exit: 120 ret float %res 121} 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, %f2 127; CHECK-NEXT: blr %r14 128; CHECK: br %r14 129entry: 130 %abs = call float @llvm.fabs.f32(float %a) 131 %res = fneg float %abs 132 %cmp = fcmp olt float %res, 0.0 133 br i1 %cmp, label %exit, label %store 134 135store: 136 store float %res, ptr %dest 137 br label %exit 138 139exit: 140 ret float %res 141} 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, %f2 147; CHECK-NEXT: bler %r14 148; CHECK: br %r14 149entry: 150 %res = fneg float %a 151 %cmp = fcmp ole float %res, 0.0 152 br i1 %cmp, label %exit, label %store 153 154store: 155 store float %res, ptr %dest 156 br label %exit 157 158exit: 159 ret float %res 160} 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, %f2 166; CHECK-NEXT: ltebr %f1, %f0 167; CHECK-NEXT: blhr %r14 168; CHECK: br %r14 169entry: 170 %res = fmul float %a, %b 171 %cmp = fcmp one float %res, 0.0 172 br i1 %cmp, label %exit, label %store 173 174store: 175 store float %b, ptr %dest 176 br label %exit 177 178exit: 179 ret float %res 180} 181 182; Test a combination involving a CC-setting instruction followed by 183; a non-CC-setting instruction. 184define float @f10(float %a, float %b, float %c, ptr %dest) { 185; CHECK-LABEL: f10: 186; CHECK: aebr %f0, %f2 187; CHECK-NEXT: debr %f0, %f4 188; CHECK-NEXT: ltebr %f1, %f0 189; CHECK-NEXT: bner %r14 190; CHECK: br %r14 191entry: 192 %add = fadd float %a, %b 193 %res = fdiv float %add, %c 194 %cmp = fcmp une float %res, 0.0 195 br i1 %cmp, label %exit, label %store 196 197store: 198 store float %b, ptr %dest 199 br label %exit 200 201exit: 202 ret float %res 203} 204 205; Test a case where CC is set based on a different register from the 206; compare input. 207define float @f11(float %a, float %b, float %c, ptr %dest1, ptr %dest2) { 208; CHECK-LABEL: f11: 209; CHECK: aebr %f0, %f2 210; CHECK-NEXT: sebr %f4, %f0 211; CHECK-DAG: ste %f4, 0(%r2) 212; CHECK-DAG: ltebr %f1, %f0 213; CHECK-NEXT: ber %r14 214; CHECK: br %r14 215entry: 216 %add = fadd float %a, %b 217 %sub = fsub float %c, %add 218 store float %sub, ptr %dest1 219 %cmp = fcmp oeq float %add, 0.0 220 br i1 %cmp, label %exit, label %store 221 222store: 223 store float %sub, ptr %dest2 224 br label %exit 225 226exit: 227 ret float %add 228} 229 230; %val in %f2 must be preserved during comparison and also copied to %f0. 231define float @f12(float %dummy, float %val, ptr %dest) { 232; CHECK-LABEL: f12: 233; CHECK: ler %f0, %f2 234; CHECK-NEXT: ltebr %f1, %f2 235; CHECK-NEXT: #APP 236; CHECK-NEXT: blah %f0 237; CHECK-NEXT: #NO_APP 238; CHECK-NEXT: blr %r14 239; CHECK: br %r14 240entry: 241 call void asm sideeffect "blah $0", "{f0}"(float %val) 242 %cmp = fcmp olt float %val, 0.0 243 br i1 %cmp, label %exit, label %store 244 245store: 246 store float %val, ptr %dest 247 br label %exit 248 249exit: 250 ret float %val 251} 252 253; Same for double. 254define double @f13(double %dummy, double %val, ptr %dest) { 255; CHECK-LABEL: f13: 256; CHECK: ldr %f0, %f2 257; CHECK-NEXT: ltdbr %f1, %f2 258; CHECK-NEXT: #APP 259; CHECK-NEXT: blah %f0 260; CHECK-NEXT: #NO_APP 261; CHECK-NEXT: blr %r14 262; CHECK: br %r14 263entry: 264 call void asm sideeffect "blah $0", "{f0}"(double %val) 265 %cmp = fcmp olt double %val, 0.0 266 br i1 %cmp, label %exit, label %store 267 268store: 269 store double %val, ptr %dest 270 br label %exit 271 272exit: 273 ret double %val 274} 275 276; LXR cannot be converted to LTXBR as its input is live after it. 277define void @f14(ptr %ptr1, ptr %ptr2) { 278; CHECK-LABEL: f14: 279; CHECK: lxr 280; CHECK-NEXT: dxbr 281; CHECK-NEXT: std 282; CHECK-NEXT: std 283; CHECK-NEXT: mxbr 284; CHECK-NEXT: ltxbr 285; CHECK-NEXT: std 286; CHECK-NEXT: std 287; CHECK-NEXT: blr %r14 288; CHECK: br %r14 289entry: 290 %val1 = load fp128, ptr %ptr1 291 %val2 = load fp128, ptr %ptr2 292 %div = fdiv fp128 %val1, %val2 293 store fp128 %div, ptr %ptr1 294 %mul = fmul fp128 %val1, %val2 295 store fp128 %mul, ptr %ptr2 296 %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000 297 br i1 %cmp, label %exit, label %store 298 299store: 300 call void asm sideeffect "blah", ""() 301 br label %exit 302 303exit: 304 ret void 305} 306 307define float @f15(float %val, float %dummy, ptr %dest) { 308; CHECK-LABEL: f15: 309; CHECK: ltebr %f1, %f0 310; CHECK-NEXT: ler %f2, %f0 311; CHECK-NEXT: #APP 312; CHECK-NEXT: blah %f2 313; CHECK-NEXT: #NO_APP 314; CHECK-NEXT: blr %r14 315; CHECK: br %r14 316entry: 317 call void asm sideeffect "blah $0", "{f2}"(float %val) 318 %cmp = fcmp olt float %val, 0.0 319 br i1 %cmp, label %exit, label %store 320 321store: 322 store float %val, ptr %dest 323 br label %exit 324 325exit: 326 ret float %val 327} 328 329define double @f16(double %val, double %dummy, ptr %dest) { 330; CHECK-LABEL: f16: 331; CHECK: ltdbr %f1, %f0 332; CHECK: ldr %f2, %f0 333; CHECK-NEXT: #APP 334; CHECK-NEXT: blah %f2 335; CHECK-NEXT: #NO_APP 336; CHECK-NEXT: blr %r14 337; CHECK: br %r14 338entry: 339 call void asm sideeffect "blah $0", "{f2}"(double %val) 340 %cmp = fcmp olt double %val, 0.0 341 br i1 %cmp, label %exit, label %store 342 343store: 344 store double %val, ptr %dest 345 br label %exit 346 347exit: 348 ret double %val 349} 350 351; Repeat f2 with a comparison against -0. 352define float @f17(float %a, float %b, ptr %dest) { 353; CHECK-LABEL: f17: 354; CHECK: aebr %f0, %f2 355; CHECK-NEXT: blr %r14 356; CHECK: br %r14 357entry: 358 %res = fadd float %a, %b 359 %cmp = fcmp olt float %res, -0.0 360 br i1 %cmp, label %exit, label %store 361 362store: 363 store float %b, ptr %dest 364 br label %exit 365 366exit: 367 ret float %res 368} 369 370; Test another form of f7 in which the condition is based on the unnegated 371; result. This is what InstCombine would produce. 372define float @f18(float %dummy, float %a, ptr %dest) { 373; CHECK-LABEL: f18: 374; CHECK: # %bb.0: # %entry 375; CHECK-NEXT: lnebr %f0, %f2 376; CHECK-NEXT: blr %r14 377; CHECK-NEXT: .LBB17_1: # %store 378; CHECK-NEXT: ste %f0, 0(%r2) 379; CHECK-NEXT: br %r14 380entry: 381 %abs = call float @llvm.fabs.f32(float %a) 382 %res = fneg float %abs 383 %cmp = fcmp ogt float %abs, 0.0 384 br i1 %cmp, label %exit, label %store 385 386store: 387 store float %res, ptr %dest 388 br label %exit 389 390exit: 391 ret float %res 392} 393 394; Similarly for f8. 395define float @f19(float %dummy, float %a, ptr %dest) { 396; CHECK-LABEL: f19: 397; CHECK: # %bb.0: # %entry 398; CHECK-NEXT: lcebr %f0, %f2 399; CHECK-NEXT: bler %r14 400; CHECK-NEXT: .LBB18_1: # %store 401; CHECK-NEXT: ste %f0, 0(%r2) 402; CHECK-NEXT: br %r14 403entry: 404 %res = fneg float %a 405 %cmp = fcmp oge float %a, 0.0 406 br i1 %cmp, label %exit, label %store 407 408store: 409 store float %res, ptr %dest 410 br label %exit 411 412exit: 413 ret float %res 414} 415