From 8148a06b8fdb734f7f9a11ce787ee6505939fdaa Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Mon, 24 Nov 2014 23:32:12 +0100 Subject: [PATCH] llvmpipe: fix lp_test_arit denorm handling 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. Reviewed-by: Jose Fonseca --- 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 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" @@ -332,6 +333,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. */ @@ -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 { -- 2.30.2