diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_test_arit.c | 38 |
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 { |