[Mesa-dev] [PATCH] llvmpipe: fix lp_test_arit denorm handling

sroland at vmware.com sroland at vmware.com
Mon Nov 24 14:37:17 PST 2014


From: Roland Scheidegger <sroland at vmware.com>

llvmpipe disables denorms on purpose (on x86/sse only), because denorms are
generally neither required nor desired for graphic apis (and in case of d3d10,
they are forbidden).
However, this caused some arithmetic tests using denorms to fail on some
systems, because the reference did not generate the same results anymore.
(It did not fail on all systems - behavior of these math functions is sort
of undefined when called with non-standard floating point mode, hence the
result differing depending on implementation and in particular the sse
capabilities.)
So, for the reference, simply flush all (input/output) denorms manually
to zero in this case.

This fixes https://bugs.freedesktop.org/show_bug.cgi?id=67672.
---
 src/gallium/drivers/llvmpipe/lp_test_arit.c | 38 ++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_test_arit.c b/src/gallium/drivers/llvmpipe/lp_test_arit.c
index 3fc64ce..290c523 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 {
-- 
1.9.1



More information about the mesa-dev mailing list