diff options
author | Marcin Koscielnicki <koriakin@0x04.net> | 2016-07-10 14:41:22 +0000 |
---|---|---|
committer | Marcin Koscielnicki <koriakin@0x04.net> | 2016-07-10 14:41:22 +0000 |
commit | cf7cc724a728e73e1b2c3258b0adb08326c802c1 (patch) | |
tree | 78bafc61d804bc8e576ec0843b86d5d789fb81c9 /llvm/test/CodeGen/SystemZ | |
parent | 303326541bab361acc5c1324b0a743a16aa3bae2 (diff) | |
download | bcm5719-llvm-cf7cc724a728e73e1b2c3258b0adb08326c802c1.tar.gz bcm5719-llvm-cf7cc724a728e73e1b2c3258b0adb08326c802c1.zip |
[SystemZ] Utilize Test Data Class instructions.
This adds a new SystemZ-specific intrinsic, llvm.s390.tdc.f(32|64|128),
which maps straight to the test data class instructions. A new IR pass
is added to recognize instructions that can be converted to TDC and
perform the necessary replacements.
Differential Revision: http://reviews.llvm.org/D21949
llvm-svn: 275016
Diffstat (limited to 'llvm/test/CodeGen/SystemZ')
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-01.ll | 95 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-02.ll | 96 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-03.ll | 139 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-04.ll | 85 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-05.ll | 97 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/tdc-06.ll | 48 |
6 files changed, 560 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/SystemZ/tdc-01.ll b/llvm/test/CodeGen/SystemZ/tdc-01.ll new file mode 100644 index 00000000000..052d895b798 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-01.ll @@ -0,0 +1,95 @@ +; Test the Test Data Class instruction, selected manually via the intrinsic. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +declare i32 @llvm.s390.tdc.f32(float, i64) +declare i32 @llvm.s390.tdc.f64(double, i64) +declare i32 @llvm.s390.tdc.f128(fp128, i64) + +; Check using as i32 - f32 +define i32 @f1(float %x) { +; CHECK-LABEL: f1 +; CHECK: tceb %f0, 123 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 + %res = call i32 @llvm.s390.tdc.f32(float %x, i64 123) + ret i32 %res +} + +; Check using as i32 - f64 +define i32 @f2(double %x) { +; CHECK-LABEL: f2 +; CHECK: tcdb %f0, 123 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 + %res = call i32 @llvm.s390.tdc.f64(double %x, i64 123) + ret i32 %res +} + +; Check using as i32 - f128 +define i32 @f3(fp128 %x) { +; CHECK-LABEL: f3 +; CHECK: ld %f0, 0(%r2) +; CHECK: ld %f2, 8(%r2) +; CHECK: tcxb %f0, 123 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 + %res = call i32 @llvm.s390.tdc.f128(fp128 %x, i64 123) + ret i32 %res +} + +declare void @g() + +; Check branch +define void @f4(float %x) { +; CHECK-LABEL: f4 +; CHECK: tceb %f0, 123 +; CHECK: jgl g +; CHECK: br %r14 + %res = call i32 @llvm.s390.tdc.f32(float %x, i64 123) + %cond = icmp ne i32 %res, 0 + br i1 %cond, label %call, label %exit + +call: + tail call void @g() + br label %exit + +exit: + ret void +} + +; Check branch negated +define void @f5(float %x) { +; CHECK-LABEL: f5 +; CHECK: tceb %f0, 123 +; CHECK: jge g +; CHECK: br %r14 + %res = call i32 @llvm.s390.tdc.f32(float %x, i64 123) + %cond = icmp eq i32 %res, 0 + br i1 %cond, label %call, label %exit + +call: + tail call void @g() + br label %exit + +exit: + ret void +} + +; Check non-const mask +define void @f6(float %x, i64 %y) { +; CHECK-LABEL: f6 +; CHECK: tceb %f0, 0(%r2) +; CHECK: jge g +; CHECK: br %r14 + %res = call i32 @llvm.s390.tdc.f32(float %x, i64 %y) + %cond = icmp eq i32 %res, 0 + br i1 %cond, label %call, label %exit + +call: + tail call void @g() + br label %exit + +exit: + ret void +} diff --git a/llvm/test/CodeGen/SystemZ/tdc-02.ll b/llvm/test/CodeGen/SystemZ/tdc-02.ll new file mode 100644 index 00000000000..c0c4ac84349 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-02.ll @@ -0,0 +1,96 @@ +; Test the Test Data Class instruction logic operation folding. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +declare i32 @llvm.s390.tdc.f32(float, i64) +declare i32 @llvm.s390.tdc.f64(double, i64) +declare i32 @llvm.s390.tdc.f128(fp128, i64) + +; Check using or i1 +define i32 @f1(float %x) { +; CHECK-LABEL: f1 +; CHECK: tceb %f0, 7 +; CHECK-NEXT: ipm [[REG1:%r[0-9]+]] +; CHECK-NEXT: risbg %r2, [[REG1]], 63, 191, 36 + %a = call i32 @llvm.s390.tdc.f32(float %x, i64 3) + %b = call i32 @llvm.s390.tdc.f32(float %x, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp ne i32 %b, 0 + %res = or i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Check using and i1 +define i32 @f2(double %x) { +; CHECK-LABEL: f2 +; CHECK: tcdb %f0, 2 +; CHECK-NEXT: ipm [[REG1:%r[0-9]+]] +; CHECK-NEXT: risbg %r2, [[REG1]], 63, 191, 36 + %a = call i32 @llvm.s390.tdc.f64(double %x, i64 3) + %b = call i32 @llvm.s390.tdc.f64(double %x, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp ne i32 %b, 0 + %res = and i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Check using xor i1 +define i32 @f3(fp128 %x) { +; CHECK-LABEL: f3 +; CHECK: tcxb %f0, 5 +; CHECK-NEXT: ipm [[REG1:%r[0-9]+]] +; CHECK-NEXT: risbg %r2, [[REG1]], 63, 191, 36 + %a = call i32 @llvm.s390.tdc.f128(fp128 %x, i64 3) + %b = call i32 @llvm.s390.tdc.f128(fp128 %x, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp ne i32 %b, 0 + %res = xor i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Check using xor i1 - negated test +define i32 @f4(fp128 %x) { +; CHECK-LABEL: f4 +; CHECK: tcxb %f0, 4090 +; CHECK-NEXT: ipm [[REG1:%r[0-9]+]] +; CHECK-NEXT: risbg %r2, [[REG1]], 63, 191, 36 + %a = call i32 @llvm.s390.tdc.f128(fp128 %x, i64 3) + %b = call i32 @llvm.s390.tdc.f128(fp128 %x, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp eq i32 %b, 0 + %res = xor i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Check different first args +define i32 @f5(float %x, float %y) { +; CHECK-LABEL: f5 +; CHECK-NOT: tceb {{%f[0-9]+}}, 5 +; CHECK-DAG: tceb %f0, 3 +; CHECK-DAG: tceb %f2, 6 + %a = call i32 @llvm.s390.tdc.f32(float %x, i64 3) + %b = call i32 @llvm.s390.tdc.f32(float %y, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp ne i32 %b, 0 + %res = xor i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Non-const mask (not supported) +define i32 @f6(float %x, i64 %y) { +; CHECK-LABEL: f6 +; CHECK-DAG: tceb %f0, 0(%r2) +; CHECK-DAG: tceb %f0, 6 + %a = call i32 @llvm.s390.tdc.f32(float %x, i64 %y) + %b = call i32 @llvm.s390.tdc.f32(float %x, i64 6) + %a1 = icmp ne i32 %a, 0 + %b1 = icmp ne i32 %b, 0 + %res = xor i1 %a1, %b1 + %xres = zext i1 %res to i32 + ret i32 %xres +} diff --git a/llvm/test/CodeGen/SystemZ/tdc-03.ll b/llvm/test/CodeGen/SystemZ/tdc-03.ll new file mode 100644 index 00000000000..95708f1effc --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-03.ll @@ -0,0 +1,139 @@ +; Test the Test Data Class instruction logic operation conversion from +; compares. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) +declare fp128 @llvm.fabs.f128(fp128) + +; Compare with 0 (unworthy) +define i32 @f1(float %x) { +; CHECK-LABEL: f1 +; CHECK-NOT: tceb +; CHECK: ltebr {{%f[0-9]+}}, %f0 +; CHECK-NOT: tceb + %res = fcmp ugt float %x, 0.0 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with 0 (unworthy) +define i32 @f2(float %x) { +; CHECK-LABEL: f2 +; CHECK-NOT: tceb +; CHECK: lpebr {{%f[0-9]+}}, %f0 +; CHECK-NOT: tceb + %y = call float @llvm.fabs.f32(float %x) + %res = fcmp ugt float %y, 0.0 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare with inf (unworthy) +define i32 @f3(float %x) { +; CHECK-LABEL: f3 +; CHECK-NOT: tceb +; CHECK: ceb %f0, 0(%r{{[0-9]+}}) +; CHECK-NOT: tceb + %res = fcmp ult float %x, 0x7ff0000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with inf +define i32 @f4(float %x) { +; CHECK-LABEL: f4 +; CHECK: tceb %f0, 4047 + %y = call float @llvm.fabs.f32(float %x) + %res = fcmp ult float %y, 0x7ff0000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare with minnorm (unworthy) +define i32 @f5(float %x) { +; CHECK-LABEL: f5 +; CHECK-NOT: tceb +; CHECK: ceb %f0, 0(%r{{[0-9]+}}) +; CHECK-NOT: tceb + %res = fcmp ult float %x, 0x3810000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with minnorm +define i32 @f6(float %x) { +; CHECK-LABEL: f6 +; CHECK: tceb %f0, 3279 + %y = call float @llvm.fabs.f32(float %x) + %res = fcmp ult float %y, 0x3810000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with minnorm, unsupported condition +define i32 @f7(float %x) { +; CHECK-LABEL: f7 +; CHECK-NOT: tceb +; CHECK: lpdfr [[REG:%f[0-9]+]], %f0 +; CHECK: ceb [[REG]], 0(%r{{[0-9]+}}) +; CHECK-NOT: tceb + %y = call float @llvm.fabs.f32(float %x) + %res = fcmp ugt float %y, 0x3810000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with unsupported constant +define i32 @f8(float %x) { +; CHECK-LABEL: f8 +; CHECK-NOT: tceb +; CHECK: lpdfr [[REG:%f[0-9]+]], %f0 +; CHECK: ceb [[REG]], 0(%r{{[0-9]+}}) +; CHECK-NOT: tceb + %y = call float @llvm.fabs.f32(float %x) + %res = fcmp ult float %y, 0x3ff0000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with minnorm - double +define i32 @f9(double %x) { +; CHECK-LABEL: f9 +; CHECK: tcdb %f0, 3279 + %y = call double @llvm.fabs.f64(double %x) + %res = fcmp ult double %y, 0x0010000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs with minnorm - long double +define i32 @f10(fp128 %x) { +; CHECK-LABEL: f10 +; CHECK: tcxb %f0, 3279 + %y = call fp128 @llvm.fabs.f128(fp128 %x) + %res = fcmp ult fp128 %y, 0xL00000000000000000001000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs for one with inf - clang's isfinite +define i32 @f11(double %x) { +; CHECK-LABEL: f11 +; CHECK: tcdb %f0, 4032 + %y = call double @llvm.fabs.f64(double %x) + %res = fcmp one double %y, 0x7ff0000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare fabs for oeq with inf - clang's isinf +define i32 @f12(double %x) { +; CHECK-LABEL: f12 +; CHECK: tcdb %f0, 48 + %y = call double @llvm.fabs.f64(double %x) + %res = fcmp oeq double %y, 0x7ff0000000000000 + %xres = zext i1 %res to i32 + ret i32 %xres +} diff --git a/llvm/test/CodeGen/SystemZ/tdc-04.ll b/llvm/test/CodeGen/SystemZ/tdc-04.ll new file mode 100644 index 00000000000..929285b0ba8 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-04.ll @@ -0,0 +1,85 @@ +; Test the Test Data Class instruction logic operation conversion from +; signbit extraction. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; + +; Extract sign bit. +define i32 @f1(float %x) { +; CHECK-LABEL: f1 +; CHECK: tceb %f0, 1365 + %cast = bitcast float %x to i32 + %res = icmp slt i32 %cast, 0 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Extract negated sign bit. +define i32 @f2(float %x) { +; CHECK-LABEL: f2 +; CHECK: tceb %f0, 2730 + %cast = bitcast float %x to i32 + %res = icmp sgt i32 %cast, -1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Extract sign bit. +define i32 @f3(double %x) { +; CHECK-LABEL: f3 +; CHECK: tcdb %f0, 1365 + %cast = bitcast double %x to i64 + %res = icmp slt i64 %cast, 0 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Extract negated sign bit. +define i32 @f4(double %x) { +; CHECK-LABEL: f4 +; CHECK: tcdb %f0, 2730 + %cast = bitcast double %x to i64 + %res = icmp sgt i64 %cast, -1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Extract sign bit. +define i32 @f5(fp128 %x) { +; CHECK-LABEL: f5 +; CHECK: tcxb %f0, 1365 + %cast = bitcast fp128 %x to i128 + %res = icmp slt i128 %cast, 0 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Extract negated sign bit. +define i32 @f6(fp128 %x) { +; CHECK-LABEL: f6 +; CHECK: tcxb %f0, 2730 + %cast = bitcast fp128 %x to i128 + %res = icmp sgt i128 %cast, -1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Wrong const. +define i32 @f7(float %x) { +; CHECK-LABEL: f7 +; CHECK-NOT: tceb + %cast = bitcast float %x to i32 + %res = icmp slt i32 %cast, -1 + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Wrong pred. +define i32 @f8(float %x) { +; CHECK-LABEL: f8 +; CHECK-NOT: tceb + %cast = bitcast float %x to i32 + %res = icmp eq i32 %cast, 0 + %xres = zext i1 %res to i32 + ret i32 %xres +} diff --git a/llvm/test/CodeGen/SystemZ/tdc-05.ll b/llvm/test/CodeGen/SystemZ/tdc-05.ll new file mode 100644 index 00000000000..c639a9b7b47 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-05.ll @@ -0,0 +1,97 @@ +; Test the Test Data Class instruction logic operation conversion from +; compares, combined with signbit or other compares to ensure worthiness. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) +declare fp128 @llvm.fabs.f128(fp128) + +; Compare with 0, extract sign bit +define i32 @f1(float %x) { +; CHECK-LABEL: f1 +; CHECK: tceb %f0, 2047 + %cast = bitcast float %x to i32 + %sign = icmp slt i32 %cast, 0 + %fcmp = fcmp ugt float %x, 0.0 + %res = or i1 %sign, %fcmp + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare with inf, extract negated sign bit +define i32 @f2(float %x) { +; CHECK-LABEL: f2 +; CHECK: tceb %f0, 2698 + %cast = bitcast float %x to i32 + %sign = icmp sgt i32 %cast, -1 + %fcmp = fcmp ult float %x, 0x7ff0000000000000 + %res = and i1 %sign, %fcmp + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Compare with minnorm, extract negated sign bit +define i32 @f3(float %x) { +; CHECK-LABEL: f3 +; CHECK: tceb %f0, 2176 + %cast = bitcast float %x to i32 + %sign = icmp sgt i32 %cast, -1 + %fcmp = fcmp olt float %x, 0x3810000000000000 + %res = and i1 %sign, %fcmp + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Test float isnormal, from clang. +define i32 @f4(float %x) { +; CHECK-LABEL: f4 +; CHECK: tceb %f0, 768 + %y = call float @llvm.fabs.f32(float %x) + %ord = fcmp ord float %x, 0.0 + %a = fcmp ult float %y, 0x7ff0000000000000 + %b = fcmp uge float %y, 0x3810000000000000 + %c = and i1 %a, %b + %res = and i1 %ord, %c + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Check for negative 0. +define i32 @f5(float %x) { +; CHECK-LABEL: f5 +; CHECK: tceb %f0, 1024 + %cast = bitcast float %x to i32 + %sign = icmp slt i32 %cast, 0 + %fcmp = fcmp oeq float %x, 0.0 + %res = and i1 %sign, %fcmp + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Test isnormal, from clang. +define i32 @f6(double %x) { +; CHECK-LABEL: f6 +; CHECK: tcdb %f0, 768 + %y = call double @llvm.fabs.f64(double %x) + %ord = fcmp ord double %x, 0.0 + %a = fcmp ult double %y, 0x7ff0000000000000 + %b = fcmp uge double %y, 0x0010000000000000 + %c = and i1 %ord, %a + %res = and i1 %b, %c + %xres = zext i1 %res to i32 + ret i32 %xres +} + +; Test isinf || isnan, from clang. +define i32 @f7(double %x) { +; CHECK-LABEL: f7 +; CHECK: tcdb %f0, 63 + %y = call double @llvm.fabs.f64(double %x) + %a = fcmp oeq double %y, 0x7ff0000000000000 + %b = fcmp uno double %x, 0.0 + %res = or i1 %a, %b + %xres = zext i1 %res to i32 + ret i32 %xres +} diff --git a/llvm/test/CodeGen/SystemZ/tdc-06.ll b/llvm/test/CodeGen/SystemZ/tdc-06.ll new file mode 100644 index 00000000000..11fb1e2916e --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/tdc-06.ll @@ -0,0 +1,48 @@ +; Test the Test Data Class instruction, as used by fpclassify. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) +declare fp128 @llvm.fabs.f128(fp128) + +define i32 @fpc(double %x) { +entry: +; CHECK-LABEL: fpc +; CHECK: lhi %r2, 5 +; CHECK: ltdbr %f0, %f0 +; CHECK: je [[RET:.L.*]] + %testeq = fcmp oeq double %x, 0.000000e+00 + br i1 %testeq, label %ret, label %nonzero + +nonzero: +; CHECK: lhi %r2, 1 +; CHECK: cdbr %f0, %f0 +; CHECK: jo [[RET]] + %testnan = fcmp uno double %x, 0.000000e+00 + br i1 %testnan, label %ret, label %nonzeroord + +nonzeroord: +; CHECK: lhi %r2, 2 +; CHECK: tcdb %f0, 48 +; CHECK: jl [[RET]] + %abs = tail call double @llvm.fabs.f64(double %x) + %testinf = fcmp oeq double %abs, 0x7FF0000000000000 + br i1 %testinf, label %ret, label %finite + +finite: +; CHECK: lhi %r2, 3 +; CHECK: tcdb %f0, 831 +; CHECK: blr %r14 +; CHECK: lhi %r2, 4 + %testnormal = fcmp uge double %abs, 0x10000000000000 + %finres = select i1 %testnormal, i32 3, i32 4 + br label %ret + +ret: +; CHECK: [[RET]]: +; CHECK: br %r14 + %res = phi i32 [ 5, %entry ], [ 1, %nonzero ], [ 2, %nonzeroord ], [ %finres, %finite ] + ret i32 %res +} |