Repository navigation
fix(maul): keep Clang's trapping math off in the family's float flags - #129
Conversation
siracozmen01
left a comment
There was a problem hiding this comment.
Review at f3d3aff: no change needed, with two points not verified below. I read the diff and the family's float environment (maul-anim src/fpenv.h, a family file); I did not run a compiler.
Strict to ignore with contraction off, no reassociation, no reciprocal, signed zeros kept and round to nearest. Every + - * / and sqrt has one correctly rounded result in both modes, so whether Clang evaluates one at run time, folds it, hoists it, speculates it or drops a dead one, the bits are the same. What ignore mode adds over strict is freedom to move and fold, not freedom to change a finite result. The folds it allows and strict forbids are x * 1.0, x + -0.0 and x - 0.0 to x, plus commuting operands. Those differ from an IEEE evaluation only in NaN bits: a signaling NaN is not quieted, and with two NaN operands the other one's payload may come out. Arithmetic never makes a signaling NaN; only bytes read in as a float do. So a golden sees the difference only if it hashes a NaN taken from input bytes, and the libraries refuse NaN inputs.
The family already assumes ignore mode. fpenv.h says compilers do not order float arithmetic against writes to the control register, which is why every public call does its arithmetic in a NOINLINE worker. GCC (with trapping math on) and Clang before 19 never ordered them either. So no library relies on what strict mode gave, and the comment in this pull request now says the same.
Not verified. Please grep:
- libm calls with constant arguments. In ignore mode Clang may fold a libm transcendental (
sinf,cosf,expf,logf,powf,atan2fand so on) whose argument is known at compile time, using its own evaluation in place of the target's libm. Strict mode did not fold those. A library that calls one on a constant, in a path a golden covers, could see its bits move on Clang. A grep of the libraries'src/for those names settles it. If they use only the family's own math, nothing moves. - x87 builds. If any family build does float math on x87 (32-bit x86 without SSE2), strict mode left inexact constant expressions to run time, in x87's wider precision, while ignore mode folds them correctly rounded. Android's i686 ABI has SSSE3, so LLVM uses SSE there and this does not apply. I only ask in case another 32-bit x86 build exists.
For maul-rhi's armv7 run (from memory, not checked here): NEON on ARMv7 always flushes denormals, and LLVM keeps float math off NEON on ARMv7 unless unsafe-math flags allow it, which this flag set does not. The goldens-unchanged run you plan will confirm it. Separately, fpenv.h names MXCSR, FPCR and WebAssembly only, so that build will also show whether the environment code handles 32-bit ARM's FPSCR.
The body has Problem, Change and Verification, and has no column-0 word( or type(scope): line.
Problem
The family's
cmake/CompilerFlags.cmakepasses-fno-unsafe-math-optimizations, and its comment says trapping math stays at each compiler's default, off in Clang. In Clang 19 and later that flag also turns trapping math on, which sets-ffp-exception-behavior=stricton every Clang build. Clang refuses strict floating-point exceptions on 32-bit ARM, so with the family's warnings as errors every file of a Maul library stops on Android armeabi-v7a withoverriding currently unsupported use of floating point exceptions on this target [-Werror,-Wunsupported-floating-point-opt](found by maul-rhi while building its drivers for 32-bit targets). A library withsrc/fpenv.cis refused on 32-bit ARM anyway, by design, since its float environment is known only on x86, AArch64 and WebAssembly; a library without it, such as maul-rhi, is stopped by this flag alone. On every other target Clang compiles in strict exception mode, which no Maul library reads: none callsfetestexcept,feclearexceptor usesFENV_ACCESS.Change
The unsafe optimizations are turned off one by one,
-fno-associative-math -fno-reciprocal-math -fsigned-zeros, in place of-fno-unsafe-math-optimizations, and the comment says why. Contraction stays off, errno math stays off, and a user's-funsafe-math-optimizationsearlier on the command line is still undone.Verification
-std=c23 -Werror: the old flags fail on armv7a with the error above; the new flags compile on armv7a, aarch64, i686 and x86_64.-###): the new flags give exactly Clang's defaults (no reassociation, reciprocal, signed-zero, approximate-function or exception option); after a user's-funsafe-math-optimizationsthey still remove every one of its options; the old flags added-ffp-exception-behavior=strictin both cases.-Q --help=optimizersis identical between the old and the new flags with no user flag, after-funsafe-math-optimizationsand after-ffast-math.-Werror.echo_suppressor.c,octave_eq.c): its nine voice and EQ suites print the same 53 lines under both flag sets, and both files' objects disassemble identically, with identical constant sections, so nothing Clang folds there moves.