Subzero: fix cosh/sinh deqp failures

As was done with LLVM (https://swiftshader-review.googlesource.com/c/SwiftShader/+/35988),
implement Sinh and Cosh in terms of Exp for Subzero. Both backends now
call into EmulatedReactor. This is not the right solution, as Reactor
should be implemented in terms of std cosh/sinh or intrinsics, as per
b/149110874.

Bug: b/145754674
Change-Id: I8f513e46fb4af270a847343e4b561927aaad1560
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41009
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Reactor/EmulatedReactor.cpp b/src/Reactor/EmulatedReactor.cpp
index 631960b..994158c 100644
--- a/src/Reactor/EmulatedReactor.cpp
+++ b/src/Reactor/EmulatedReactor.cpp
@@ -193,12 +193,14 @@
 
 RValue<Float4> Sinh(RValue<Float4> x)
 {
-	return call4(sinhf, x);
+	// TODO(b/149110874) Use coshf/sinhf when we've implemented SpirV versions at the SpirV level
+	return Float4(0.5f) * (emulated::Exp(x) - emulated::Exp(-x));
 }
 
 RValue<Float4> Cosh(RValue<Float4> x)
 {
-	return call4(coshf, x);
+	// TODO(b/149110874) Use coshf/sinhf when we've implemented SpirV versions at the SpirV level
+	return Float4(0.5f) * (emulated::Exp(x) + emulated::Exp(-x));
 }
 
 RValue<Float4> Tanh(RValue<Float4> x)
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index b0c014e..c8d74c2 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -16,6 +16,7 @@
 
 #include "CPUID.hpp"
 #include "Debug.hpp"
+#include "EmulatedReactor.hpp"
 #include "LLVMReactorDebugInfo.hpp"
 #include "Reactor.hpp"
 #include "x86.hpp"
@@ -3171,12 +3172,12 @@
 
 RValue<Float4> Sinh(RValue<Float4> v)
 {
-	return Float4(0.5f) * (Exp(v) - Exp(-v));
+	return emulated::Sinh(v);
 }
 
 RValue<Float4> Cosh(RValue<Float4> v)
 {
-	return Float4(0.5f) * (Exp(v) + Exp(-v));
+	return emulated::Cosh(v);
 }
 
 RValue<Float4> Tanh(RValue<Float4> v)
diff --git a/src/Reactor/ReactorUnitTests.cpp b/src/Reactor/ReactorUnitTests.cpp
index a0b8406..508e815 100644
--- a/src/Reactor/ReactorUnitTests.cpp
+++ b/src/Reactor/ReactorUnitTests.cpp
@@ -2134,6 +2134,15 @@
 // clang-format on
 
 // TODO(b/149110874) Use coshf/sinhf when we've implemented SpirV versions at the SpirV level
+float vulkan_sinhf(float a)
+{
+	return ((expf(a) - expf(-a)) / 2);
+}
+float vulkan_coshf(float a)
+{
+	return ((expf(a) + expf(-a)) / 2);
+}
+
 // clang-format off
 INSTANTIATE_TEST_SUITE_P(IntrinsicTestParams_Float4, IntrinsicTest_Float4, testing::Values(
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sin(v); },   sinf,   {0.f, 1.f, PI, 12345.f}  },
@@ -2142,8 +2151,8 @@
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Asin(v); },  asinf,  {0.f, 1.f, -1.f}  },
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Acos(v); },  acosf,  {0.f, 1.f, -1.f}  },
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Atan(v); },  atanf,  {0.f, 1.f, PI, 12345.f}  },
-	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sinh(v); },  sinhf,  {0.f, 1.f, PI, 12345.f}  },
-	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Cosh(v); },  coshf,  {0.f, 1.f, PI, 12345.f} },
+	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sinh(v); },  vulkan_sinhf,  {0.f, 1.f, PI, 12345.f, 0x1.65a84ep6}  },
+	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Cosh(v); },  vulkan_coshf,  {0.f, 1.f, PI, 12345.f, 0x1.65a84ep6} },
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Tanh(v); },  tanhf,  {0.f, 1.f, PI, 12345.f}  },
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Asinh(v); }, asinhf, {0.f, 1.f, PI, 12345.f}  },
 	IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Acosh(v); }, acoshf, {     1.f, PI, 12345.f}  },