Okay, so does Java guarantee which bits one sees there, or is this something where the underlying hardware can shine through (and e.g. on x87, one can see NaN bits being disturbed)?
AFAIK this has nothing to do with old ARM chips. It's the 32-bit ARM SIMD instructions that will flush to zero. I believe that LLVM does not use these instructions unless -ffast-math is used, but this needs to be double-checked (and fixed in LLVM if this is not the case).
This cannot be fixed by changing the FP environment. ARM SIMD instruction ignore these settings and always flush to zero.
AArch64 does not have this problem: both scalar and SIMD instructions correctly handle subnormals. (Edited)
I would add that since the FP exception flags are not exposed, there is very little difference between signaling and non-signaling NaNs. In that case it would make sense to simply treat both quiet and signaling NaNs as interchangable. (Edited)
n the future, the non-determinism of NaN bits can be further restricted. For example, [wasm guarantees](https://webassembly.github.io/spec/core/exec/numerics.html#nan-propagation) that if all input NaNs are "canonical" than the output NaN is "canonical", leaving only 1 bit non-deterministic: the sign.
This is possible because in practice hardware implements one of 2 behaviors with regards to NaNs. If an input in NaN then either:
a) One of the NaN inputs is propagated unchanged as the result. (In multiple inputs are NaN, things get tricky).
b) A canonical NaN is produced.
This means that if no inputs are non-canonical NaNs then it is impossible to create a non-canonical NaN. (Edited)