nir: fix denorm flush-to-zero in sqrt's lowering at nir_lower_double_ops
authorSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Tue, 10 Jul 2018 10:04:38 +0000 (12:04 +0200)
committerAndres Gomez <agomez@igalia.com>
Tue, 17 Sep 2019 20:39:18 +0000 (23:39 +0300)
v2:
- Replace hard coded value with DBL_MIN (Connor).

v3:
- Have into account the FLOAT_CONTROLS_DENORM_PRESERVE_FP64
  flag (Caio).

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Signed-off-by: Andres Gomez <agomez@igalia.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com> [v2]
src/compiler/nir/nir_lower_double_ops.c

index 45ac155de51c622e7fd50d688acda1688c4cc94e..322ae49bacde0ece83100af2011f1d0c38f8d2af 100644 (file)
@@ -26,6 +26,8 @@
 #include "nir_builder.h"
 #include "c99_math.h"
 
+#include <float.h>
+
 /*
  * Lowers some unsupported double operations, using only:
  *
@@ -289,9 +291,20 @@ lower_sqrt_rsq(nir_builder *b, nir_ssa_def *src, bool sqrt)
        * 0 -> 0 and
        * +inf -> +inf
        */
-      res = nir_bcsel(b, nir_ior(b, nir_feq(b, src, nir_imm_double(b, 0.0)),
+      const bool preserve_denorms =
+         b->shader->info.float_controls_execution_mode &
+         FLOAT_CONTROLS_DENORM_PRESERVE_FP64;
+      nir_ssa_def *src_flushed = src;
+      if (!preserve_denorms) {
+         src_flushed = nir_bcsel(b,
+                                 nir_flt(b, nir_fabs(b, src),
+                                         nir_imm_double(b, DBL_MIN)),
+                                 nir_imm_double(b, 0.0),
+                                 src);
+      }
+      res = nir_bcsel(b, nir_ior(b, nir_feq(b, src_flushed, nir_imm_double(b, 0.0)),
                                  nir_feq(b, src, nir_imm_double(b, INFINITY))),
-                                 src, res);
+                                 src_flushed, res);
    } else {
       res = fix_inv_result(b, res, src, new_exp);
    }