summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_arit.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_test_arit.c b/src/gallium/drivers/llvmpipe/lp_test_arit.c
index 3fc64ce691d..290c523f049 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_arit.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_arit.c
@@ -33,6 +33,7 @@
#include "util/u_pointer.h"
#include "util/u_memory.h"
#include "util/u_math.h"
+#include "util/u_cpu_detect.h"
#include "gallivm/lp_bld.h"
#include "gallivm/lp_bld_debug.h"
@@ -333,6 +334,38 @@ build_unary_test_func(struct gallivm_state *gallivm,
/*
+ * Flush denorms to zero.
+ */
+static float
+flush_denorm_to_zero(float val)
+{
+ /*
+ * If we have a denorm manually set it to (+-)0.
+ * This is because the reference may or may not do the right thing
+ * otherwise because we want the result according to treating all
+ * denormals as zero (FTZ/DAZ). Not using fpclassify because
+ * a) some compilers are stuck at c89 (msvc)
+ * b) not sure it reliably works with non-standard ftz/daz mode
+ * And, right now we only disable denorms with jited code on x86/sse
+ * (albeit this should be classified as a bug) so to get results which
+ * match we must only flush them to zero here in that case too.
+ */
+ union fi fi_val;
+
+ fi_val.f = val;
+
+#if defined(PIPE_ARCH_SSE)
+ if (util_cpu_caps.has_sse) {
+ if ((fi_val.ui & 0x7f800000) == 0) {
+ fi_val.ui &= 0xff800000;
+ }
+ }
+#endif
+
+ return fi_val.f;
+}
+
+/*
* Test one LLVM unary arithmetic builder function.
*/
static boolean
@@ -374,10 +407,13 @@ test_unary(unsigned verbose, FILE *fp, const struct unary_test_t *test)
test_func_jit(out, in);
for (i = 0; i < num_vals; ++i) {
- float ref = test->ref(in[i]);
+ float testval, ref;
double error, precision;
bool pass;
+ testval = flush_denorm_to_zero(in[i]);
+ ref = flush_denorm_to_zero(test->ref(testval));
+
if (util_inf_sign(ref) && util_inf_sign(out[i]) == util_inf_sign(ref)) {
error = 0;
} else {