Commit 8148a06b authored by Roland Scheidegger's avatar Roland Scheidegger

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
So, for the reference, simply flush all (input/output) denorms manually
to zero in this case.

This fixes
Reviewed-by: Jose Fonseca's avatarJose Fonseca <>
parent 93d30ff5
......@@ -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;
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 {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment