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, float *%dest) { 10; CHECK-LABEL: f1: 11; CHECK: aebr %f0, %f2 12; CHECK-NEXT: je .L{{.*}} 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, float *%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, float *%dest) { 29; CHECK-LABEL: f2: 30; CHECK: aebr %f0, %f2 31; CHECK-NEXT: jl .L{{.*}} 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, float *%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, float *%dest) { 48; CHECK-LABEL: f3: 49; CHECK: aebr %f0, %f2 50; CHECK-NEXT: jh .L{{.*}} 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, float *%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, float *%dest) { 67; CHECK-LABEL: f4: 68; CHECK: aebr %f0, %f2 69; CHECK-NEXT: jnlh .L{{.*}} 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, float *%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, float *%dest) { 86; CHECK-LABEL: f5: 87; CHECK: seb %f0, 0(%r2) 88; CHECK-NEXT: jnhe .L{{.*}} 89; CHECK: br %r14 90entry: 91 %cur = load float , float *%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, float *%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, float *%dest) { 106; CHECK-LABEL: f6: 107; CHECK: lpebr %f0, %f2 108; CHECK-NEXT: jh .L{{.*}} 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, float *%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, float *%dest) { 125; CHECK-LABEL: f7: 126; CHECK: lnebr %f0, %f2 127; CHECK-NEXT: jl .L{{.*}} 128; CHECK: br %r14 129entry: 130 %abs = call float @llvm.fabs.f32(float %a) 131 %res = fsub float -0.0, %abs 132 %cmp = fcmp olt float %res, 0.0 133 br i1 %cmp, label %exit, label %store 134 135store: 136 store float %res, float *%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, float *%dest) { 145; CHECK-LABEL: f8: 146; CHECK: lcebr %f0, %f2 147; CHECK-NEXT: jle .L{{.*}} 148; CHECK: br %r14 149entry: 150 %res = fsub float -0.0, %a 151 %cmp = fcmp ole float %res, 0.0 152 br i1 %cmp, label %exit, label %store 153 154store: 155 store float %res, float *%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, float *%dest) { 164; CHECK-LABEL: f9: 165; CHECK: meebr %f0, %f2 166; CHECK-NEXT: ltebr %f0, %f0 167; CHECK-NEXT: jlh .L{{.*}} 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, float *%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, float *%dest) { 185; CHECK-LABEL: f10: 186; CHECK: aebr %f0, %f2 187; CHECK-NEXT: debr %f0, %f4 188; CHECK-NEXT: ltebr %f0, %f0 189; CHECK-NEXT: jne .L{{.*}} 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, float *%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, float *%dest1, float *%dest2) { 208; CHECK-LABEL: f11: 209; CHECK: aebr %f0, %f2 210; CHECK-NEXT: sebr %f4, %f0 211; CHECK-NEXT: ste %f4, 0(%r2) 212; CHECK-NEXT: ltebr %f0, %f0 213; CHECK-NEXT: je .L{{.*}} 214; CHECK: br %r14 215entry: 216 %add = fadd float %a, %b 217 %sub = fsub float %c, %add 218 store float %sub, float *%dest1 219 %cmp = fcmp oeq float %add, 0.0 220 br i1 %cmp, label %exit, label %store 221 222store: 223 store float %sub, float *%dest2 224 br label %exit 225 226exit: 227 ret float %add 228} 229 230; Test that LER gets converted to LTEBR where useful. 231define float @f12(float %dummy, float %val, float *%dest) { 232; CHECK-LABEL: f12: 233; CHECK: ltebr %f0, %f2 234; CHECK-NEXT: #APP 235; CHECK-NEXT: blah %f0 236; CHECK-NEXT: #NO_APP 237; CHECK-NEXT: jl .L{{.*}} 238; CHECK: br %r14 239entry: 240 call void asm sideeffect "blah $0", "{f0}"(float %val) 241 %cmp = fcmp olt float %val, 0.0 242 br i1 %cmp, label %exit, label %store 243 244store: 245 store float %val, float *%dest 246 br label %exit 247 248exit: 249 ret float %val 250} 251 252; Test that LDR gets converted to LTDBR where useful. 253define double @f13(double %dummy, double %val, double *%dest) { 254; CHECK-LABEL: f13: 255; CHECK: ltdbr %f0, %f2 256; CHECK-NEXT: #APP 257; CHECK-NEXT: blah %f0 258; CHECK-NEXT: #NO_APP 259; CHECK-NEXT: jl .L{{.*}} 260; CHECK: br %r14 261entry: 262 call void asm sideeffect "blah $0", "{f0}"(double %val) 263 %cmp = fcmp olt double %val, 0.0 264 br i1 %cmp, label %exit, label %store 265 266store: 267 store double %val, double *%dest 268 br label %exit 269 270exit: 271 ret double %val 272} 273 274; Test that LXR gets converted to LTXBR where useful. 275define void @f14(fp128 *%ptr1, fp128 *%ptr2) { 276; CHECK-LABEL: f14: 277; CHECK: ltxbr 278; CHECK-NEXT: dxbr 279; CHECK-NEXT: std 280; CHECK-NEXT: std 281; CHECK-NEXT: mxbr 282; CHECK-NEXT: std 283; CHECK-NEXT: std 284; CHECK-NEXT: jl .L{{.*}} 285; CHECK: br %r14 286entry: 287 %val1 = load fp128 , fp128 *%ptr1 288 %val2 = load fp128 , fp128 *%ptr2 289 %div = fdiv fp128 %val1, %val2 290 store fp128 %div, fp128 *%ptr1 291 %mul = fmul fp128 %val1, %val2 292 store fp128 %mul, fp128 *%ptr2 293 %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000 294 br i1 %cmp, label %exit, label %store 295 296store: 297 call void asm sideeffect "blah", ""() 298 br label %exit 299 300exit: 301 ret void 302} 303 304; Test a case where it is the source rather than destination of LER that 305; we need. 306define float @f15(float %val, float %dummy, float *%dest) { 307; CHECK-LABEL: f15: 308; CHECK: ltebr %f2, %f0 309; CHECK-NEXT: #APP 310; CHECK-NEXT: blah %f2 311; CHECK-NEXT: #NO_APP 312; CHECK-NEXT: jl .L{{.*}} 313; CHECK: br %r14 314entry: 315 call void asm sideeffect "blah $0", "{f2}"(float %val) 316 %cmp = fcmp olt float %val, 0.0 317 br i1 %cmp, label %exit, label %store 318 319store: 320 store float %val, float *%dest 321 br label %exit 322 323exit: 324 ret float %val 325} 326 327; Test a case where it is the source rather than destination of LDR that 328; we need. 329define double @f16(double %val, double %dummy, double *%dest) { 330; CHECK-LABEL: f16: 331; CHECK: ltdbr %f2, %f0 332; CHECK-NEXT: #APP 333; CHECK-NEXT: blah %f2 334; CHECK-NEXT: #NO_APP 335; CHECK-NEXT: jl .L{{.*}} 336; CHECK: br %r14 337entry: 338 call void asm sideeffect "blah $0", "{f2}"(double %val) 339 %cmp = fcmp olt double %val, 0.0 340 br i1 %cmp, label %exit, label %store 341 342store: 343 store double %val, double *%dest 344 br label %exit 345 346exit: 347 ret double %val 348} 349 350; Repeat f2 with a comparison against -0. 351define float @f17(float %a, float %b, float *%dest) { 352; CHECK-LABEL: f17: 353; CHECK: aebr %f0, %f2 354; CHECK-NEXT: jl .L{{.*}} 355; CHECK: br %r14 356entry: 357 %res = fadd float %a, %b 358 %cmp = fcmp olt float %res, -0.0 359 br i1 %cmp, label %exit, label %store 360 361store: 362 store float %b, float *%dest 363 br label %exit 364 365exit: 366 ret float %res 367} 368 369; Test another form of f7 in which the condition is based on the unnegated 370; result. This is what InstCombine would produce. 371define float @f18(float %dummy, float %a, float *%dest) { 372; CHECK-LABEL: f18: 373; CHECK: lnebr %f0, %f2 374; CHECK-NEXT: jl .L{{.*}} 375; CHECK: br %r14 376entry: 377 %abs = call float @llvm.fabs.f32(float %a) 378 %res = fsub float -0.0, %abs 379 %cmp = fcmp ogt float %abs, 0.0 380 br i1 %cmp, label %exit, label %store 381 382store: 383 store float %res, float *%dest 384 br label %exit 385 386exit: 387 ret float %res 388} 389 390; Similarly for f8. 391define float @f19(float %dummy, float %a, float *%dest) { 392; CHECK-LABEL: f19: 393; CHECK: lcebr %f0, %f2 394; CHECK-NEXT: jle .L{{.*}} 395; CHECK: br %r14 396entry: 397 %res = fsub float -0.0, %a 398 %cmp = fcmp oge float %a, 0.0 399 br i1 %cmp, label %exit, label %store 400 401store: 402 store float %res, float *%dest 403 br label %exit 404 405exit: 406 ret float %res 407} 408