Double Rounding Error

I have been reading assembly code for RISC-V, ARM64, and My ISA and came across what I think is an arithmetic anomaly across all three (and likely more) LLVM implementations.

It is commonly known as “the double Rounding Problem”::

Ref: 13-bitn.pdf

Ref 05-imacs17_1-article.pdf

The source code in question is of the form:

      float f, h;
      f = h * 1.425;

and in all cases the compiler produces something like: ISA independent assembly:

      CVTFD    Rt,Rh
      FMUL     Rt,Rt,Rconstant
      CVTDF    Rf,Rt

This sequence of code is subject to the double rounding problem described in the referenced documents unless the FMUL is performed in Round-to-Nearest-Odd rounding mode described therein. Yet, no implementations (that I know of) implements RNO and even if they did it would add several more instructions to the sequence to set the RM and then reset the RM. Yech.

I talked to my compiler writer and apparently LLVM chooses this method whenever the FP constant is not exact in (float or 32-bit) form and that the compiler suite is just trying to do its best.

I do not expect anyone to do anything about this, I just though your numerical analysist would get a laugh at the delicacy of trying to get IEEE 754 exactly right in light of producing optimized code.

Mitch

The source code in question is of the form:

|float f, h; f = h * 1.425; |

The IR you’re going to get for this code is:

define float @func(float %h) {
   %tmp = fpext float %h to double
   %mul = fmul double %tmp, 1.425
   %res = fptrunc double %mul to float
   ret float %res
}

Note that the constant 1.425 has type double (in C and C++), so you
need to promote the float to a double before doing the multiplication
and then down-converting it back into float. If you wanted to do an
fmul float, you need to use 1.425f to make the constant a
float-typed constant, or you can cast to a float instead via
(float)1.425.

So the compiler is doing the right thing here per IEEE 754, C, and C++
rules, it just may not have been what the user thought it was going to do.

2 Likes