Hello everyone!
Some FPUs support different rounding mode, so if the floating-point operation yields a value that cannot be represented exactly, it is rounded according to the rounding mode. As far as I understand, the Rust compiler expects a "round to nearest" mode, and the behavior of a Rust program in any other rounding mode is undefined. Currently, the only way to perform computations in different rounding mode is with inline assembly, something like that (an example for x86-64):
unsafe {
core::arch::asm!(
"push rax",
"stmxcsr [r10]",
"mov eax, [r10]",
"or eax, 0x00004000", // setting the "round towards positive infinity" mode
"mov [r9], eax",
"ldmxcsr [r9]",
"addsd xmm0, xmm1",
"ldmxcsr [r10]",
"pop rax",
inout("xmm0") /*variable name*/,
in("xmm1") /*variable name*/,
in("r10") /*a pointer to variable to hold the old floating-point environment*/,
in("r9") /*a pointer to variable to hold the floating-point environment used during computation*/,
)
}
The algorithm is roughly like that:
- Save the old floating-point environment
- Set the required rounding mode
- Perform computations
- Restore the old floating-point environment
The problem in wrapping such operations in Rust functions is that when we have two operations, the algorithm becomes like:
- Save the old floating-point environment
- Set the required rounding mode
- Perform computations
- Restore the old floating-point environment
- Save the old floating-point environment again
- Set the required rounding mode again
- Perform other computations
- Restore the old floating-point environment
I propose implementing it in a way similar to algebraic math optimizations -- by making the compiler aware of such methods so it could optimize away steps 4-6 (provided that steps 3 and 7 use the same rounding mode). However, as far as I understand, that can require the compiler to reorder operations with the same rounding mode close to each other to avoid unnecessary rounding-mode switching. What do you think about this idea?
P.S. As far as I know, some C compilers handle possibility of changing rounding mode by providing a special compilation mode that disables optimizations that break programs that change rounding mode in runtime. In my opinion, this has disadvantages of missed optimization opportunities and making floating-point operations impure (the same operation may yield one result in one part of the program and another in the other part).