1

In C++ optimizers you can specify the use of fast floating point arithmetic instead of precise floating point arithmetic. The difference is that in fast mode it will do optimizations that would apply to real world math, but may not produce the correct results when done on a computer.

An example of this can be shown using GodBolt using the following code and the -O2 optimization. If you are using clang or gcc you can put in the -ffast-math parameter to view what the code looks like with these optimizations.

double mulBy6DivBy12(double x)
{ return 6 * x / 12; }

double divBy2(double x)
{ return x / 2; }

Without the -ffast-math parameter it will generate a multiply and divide operation in the mulBy6DivBy12 function, with it on the two functions will look the same.

What I want to know is at runtime, when being processed by the JIT does it do these potentially unsafe optimizations?

vandench
  • 1,973
  • 3
  • 19
  • 28
  • [This question (and the corresponding answers)](https://stackoverflow.com/questions/1503479/how-to-see-jit-compiled-code-in-jvm) might help. – Turing85 Jan 08 '18 at 01:36
  • 3
    To the best of my knowledge, JIT compilation is not permitted to cause evaluation of an expression to produce a different value than is demanded by the JLS. JLS leaves a little leeway for expressions that are not `strictfp`, and on some platforms that might be enough to allow the specific optimization in your example, but no, JIT does not perform arithmetic optimzations that might change the result value, except possibly by using intermediates with extended range and / or precision (which can also happen without JIT). – John Bollinger Jan 08 '18 at 01:54

1 Answers1

3

There are two interesting statements in the Java Language Specification.

The first is a broad one in JLS section 15.7:

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

This is already a fully guarantee; even though execution may be in any order, they have to appear to be in the left-to-right evaluation order. A re-ordering of the floating point operations would break that appearance, so it's not allowed.

Secondly, there is a guarantee specifically for floating point operations in JLS section 4.2.4:

The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest.

This clarifies exactly how each (left-to-right) operation should round its results. This also disallows any reordering that changes the result of the calculation from the result that you get if you perform the operations in left-to-right order.

Community
  • 1
  • 1
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79