summaryrefslogtreecommitdiff
path: root/src/literal.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/literal.h')
-rw-r--r--src/literal.h23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/literal.h b/src/literal.h
index ffd565c71..9d9630ec4 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -706,6 +706,29 @@ struct GCData {
GCData(HeapType type, Literals values) : type(type), values(values) {}
};
+// Wasm has nondeterministic rules for NaN propagation in some operations. For
+// example. f32.neg is deterministic and just flips the sign, even of a NaN, but
+// f32.add is nondeterministic, and if one or more of the inputs is a NaN, then
+//
+// * if all NaNs are canonical NaNs, the output is some arbitrary canonical NaN
+// * otherwise the output is some arbitrary arithmetic NaN
+//
+// (canonical = NaN payload is 1000..000; arithmetic: 1???..???, that is, the
+// high bit is 1 and all others can be 0 or 1)
+//
+// For many things we don't need to care, and can just do a normal C++ add for
+// an f32.add, for example - the wasm rules are specified so that things like
+// that just work (in order for such math to be fast). However, for our
+// optimizer, it is useful to "standardize" NaNs when there is nondeterminism.
+// That is, when there are multiple valid outputs, it's nice to emit the same
+// one consistently, so that it doesn't look like the optimization changed
+// something. In other words, if the valid output of an expression is a set of
+// valid NaNs, and after optimization the output is still that same set, then
+// the optimization is valid. And if the interpreter picks the same NaN in both
+// cases from that identical set then nothing looks wrong to the fuzzer.
+Literal standardizeNaN(float result);
+Literal standardizeNaN(double result);
+
} // namespace wasm
namespace std {