summaryrefslogtreecommitdiffhomepage
path: root/ir/tv
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2014-12-30 07:23:23 +0100
committerMatthias Braun <matze@braunis.de>2014-12-30 11:09:08 +0100
commita57b8f66bf58476b73b8ea5d8701dc82ff21f7d6 (patch)
treebeff729bd0dafbb45e0c32475a1d6c433b40ef95 /ir/tv
parent2cc90595277b17bd9f0d8a0b0e869786e08f062d (diff)
fltcalc: take the "smaller NaN" for binops with 2 NaN inputs
ieee754 specifies that we have to take the payload of one of the input NaN. We choose the "smaller" one so commutativity of mal/add is preserved. This is still somewhat problematic as we really should do what our actual compilation target host would do, but have no information about that...
Diffstat (limited to 'ir/tv')
-rw-r--r--ir/tv/fltcalc.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c
index 5f4b37d..855c615 100644
--- a/ir/tv/fltcalc.c
+++ b/ir/tv/fltcalc.c
@@ -256,6 +256,11 @@ static bool normalize(const fp_value *in_val, fp_value *out_val, bool sticky)
return exact;
}
+static bool smaller_nan(const fp_value *a, const fp_value *b)
+{
+ return sc_comp(_mant(a), _mant(b)) == ir_relation_less;
+}
+
/**
* Operations involving NaN's must return NaN.
* They are NOT exact.
@@ -263,12 +268,18 @@ static bool normalize(const fp_value *in_val, fp_value *out_val, bool sticky)
static bool handle_NAN(const fp_value *a, const fp_value *b, fp_value *result)
{
if (a->clss == FC_NAN) {
+ /* for two NaN inputs take the smaller one to not break commutativity
+ * of some operations.
+ * TODO: Find out and do exactly what the current target host does. */
+ if (b->clss == FC_NAN && smaller_nan(b, a))
+ goto return_nan_b;
if (a != result)
memcpy(result, a, calc_buffer_size);
fc_exact = false;
return true;
}
if (b->clss == FC_NAN) {
+return_nan_b:
if (b != result) memcpy(result, b, calc_buffer_size);
fc_exact = false;
return true;