diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-07 11:10:06 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-07 11:10:06 +0000 |
commit | 29e873ddb6b21c4a934926a0cf7809e98ac1fff0 (patch) | |
tree | 62117d26b18e30c45cad7338dcc4e750b9918d7b /test | |
parent | e0bbf7288c00c377a97a9d4bf5fb0bf20c44cd1c (diff) | |
download | llvm-29e873ddb6b21c4a934926a0cf7809e98ac1fff0.tar.gz llvm-29e873ddb6b21c4a934926a0cf7809e98ac1fff0.tar.bz2 llvm-29e873ddb6b21c4a934926a0cf7809e98ac1fff0.tar.xz |
[SystemZ] Optimize floating-point comparisons with zero
This follows the same lines as the integer code. In the end it seemed
easier to have a second 4-bit mask in TSFlags to specify the compare-like
CC values. That eats one more TSFlags bit than adding a CCHasUnordered
would have done, but it feels more concise.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187883 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/CodeGen/SystemZ/fp-cmp-04.ll | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/test/CodeGen/SystemZ/fp-cmp-04.ll b/test/CodeGen/SystemZ/fp-cmp-04.ll new file mode 100644 index 0000000000..8d842164fa --- /dev/null +++ b/test/CodeGen/SystemZ/fp-cmp-04.ll @@ -0,0 +1,348 @@ +; Test that floating-point compares are ommitted if CC already has the +; right value. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s + +declare float @llvm.fabs.f32(float %f) + +; Test addition followed by EQ, which can use the CC result of the addition. +define float @f1(float %a, float %b, float *%dest) { +; CHECK-LABEL: f1: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: je .L{{.*}} +; CHECK: br %r14 +entry: + %res = fadd float %a, %b + %cmp = fcmp oeq float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; ...and again with LT. +define float @f2(float %a, float %b, float *%dest) { +; CHECK-LABEL: f2: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + %res = fadd float %a, %b + %cmp = fcmp olt float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; ...and again with GT. +define float @f3(float %a, float %b, float *%dest) { +; CHECK-LABEL: f3: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: jh .L{{.*}} +; CHECK: br %r14 +entry: + %res = fadd float %a, %b + %cmp = fcmp ogt float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; ...and again with UEQ. +define float @f4(float %a, float %b, float *%dest) { +; CHECK-LABEL: f4: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: jnlh .L{{.*}} +; CHECK: br %r14 +entry: + %res = fadd float %a, %b + %cmp = fcmp ueq float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; Subtraction also provides a zero-based CC value. +define float @f5(float %a, float %b, float *%dest) { +; CHECK-LABEL: f5: +; CHECK: seb %f0, 0(%r2) +; CHECK-NEXT: jnhe .L{{.*}} +; CHECK: br %r14 +entry: + %cur = load float *%dest + %res = fsub float %a, %cur + %cmp = fcmp ult float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test the result of LOAD POSITIVE. +define float @f6(float %dummy, float %a, float *%dest) { +; CHECK-LABEL: f6: +; CHECK: lpebr %f0, %f2 +; CHECK-NEXT: jh .L{{.*}} +; CHECK: br %r14 +entry: + %res = call float @llvm.fabs.f32(float %a) + %cmp = fcmp ogt float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %res, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test the result of LOAD NEGATIVE. +define float @f7(float %dummy, float %a, float *%dest) { +; CHECK-LABEL: f7: +; CHECK: lnebr %f0, %f2 +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + %abs = call float @llvm.fabs.f32(float %a) + %res = fsub float -0.0, %abs + %cmp = fcmp olt float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %res, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test the result of LOAD COMPLEMENT. +define float @f8(float %dummy, float %a, float *%dest) { +; CHECK-LABEL: f8: +; CHECK: lcebr %f0, %f2 +; CHECK-NEXT: jle .L{{.*}} +; CHECK: br %r14 +entry: + %res = fsub float -0.0, %a + %cmp = fcmp ole float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %res, float *%dest + br label %exit + +exit: + ret float %res +} + +; Multiplication (for example) does not modify CC. +define float @f9(float %a, float %b, float *%dest) { +; CHECK-LABEL: f9: +; CHECK: meebr %f0, %f2 +; CHECK-NEXT: ltebr %f0, %f0 +; CHECK-NEXT: jlh .L{{.*}} +; CHECK: br %r14 +entry: + %res = fmul float %a, %b + %cmp = fcmp one float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test a combination involving a CC-setting instruction followed by +; a non-CC-setting instruction. +define float @f10(float %a, float %b, float %c, float *%dest) { +; CHECK-LABEL: f10: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: debr %f0, %f4 +; CHECK-NEXT: ltebr %f0, %f0 +; CHECK-NEXT: jne .L{{.*}} +; CHECK: br %r14 +entry: + %add = fadd float %a, %b + %res = fdiv float %add, %c + %cmp = fcmp une float %res, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test a case where CC is set based on a different register from the +; compare input. +define float @f11(float %a, float %b, float %c, float *%dest1, float *%dest2) { +; CHECK-LABEL: f11: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: sebr %f4, %f0 +; CHECK-NEXT: ste %f4, 0(%r2) +; CHECK-NEXT: ltebr %f0, %f0 +; CHECK-NEXT: je .L{{.*}} +; CHECK: br %r14 +entry: + %add = fadd float %a, %b + %sub = fsub float %c, %add + store float %sub, float *%dest1 + %cmp = fcmp oeq float %add, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %sub, float *%dest2 + br label %exit + +exit: + ret float %add +} + +; Test that LER gets converted to LTEBR where useful. +define float @f12(float %dummy, float %val, float *%dest) { +; CHECK-LABEL: f12: +; CHECK: ltebr %f0, %f2 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %f0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + call void asm sideeffect "blah $0", "{f0}"(float %val) + %cmp = fcmp olt float %val, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %val, float *%dest + br label %exit + +exit: + ret float %val +} + +; Test that LDR gets converted to LTDBR where useful. +define double @f13(double %dummy, double %val, double *%dest) { +; CHECK-LABEL: f13: +; CHECK: ltdbr %f0, %f2 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %f0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + call void asm sideeffect "blah $0", "{f0}"(double %val) + %cmp = fcmp olt double %val, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store double %val, double *%dest + br label %exit + +exit: + ret double %val +} + +; Test that LXR gets converted to LTXBR where useful. +define void @f14(fp128 *%ptr1, fp128 *%ptr2) { +; CHECK-LABEL: f14: +; CHECK: ltxbr +; CHECK-NEXT: dxbr +; CHECK-NEXT: std +; CHECK-NEXT: std +; CHECK-NEXT: mxbr +; CHECK-NEXT: std +; CHECK-NEXT: std +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + %val1 = load fp128 *%ptr1 + %val2 = load fp128 *%ptr2 + %div = fdiv fp128 %val1, %val2 + store fp128 %div, fp128 *%ptr1 + %mul = fmul fp128 %val1, %val2 + store fp128 %mul, fp128 *%ptr2 + %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000 + br i1 %cmp, label %exit, label %store + +store: + call void asm sideeffect "blah", ""() + br label %exit + +exit: + ret void +} + +; Test a case where it is the source rather than destination of LER that +; we need. +define float @f15(float %val, float %dummy, float *%dest) { +; CHECK-LABEL: f15: +; CHECK: ltebr %f2, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %f2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + call void asm sideeffect "blah $0", "{f2}"(float %val) + %cmp = fcmp olt float %val, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %val, float *%dest + br label %exit + +exit: + ret float %val +} + +; Test a case where it is the source rather than destination of LDR that +; we need. +define double @f16(double %val, double %dummy, double *%dest) { +; CHECK-LABEL: f16: +; CHECK: ltdbr %f2, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %f2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + call void asm sideeffect "blah $0", "{f2}"(double %val) + %cmp = fcmp olt double %val, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store double %val, double *%dest + br label %exit + +exit: + ret double %val +} |