https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84997

            Bug ID: 84997
           Summary: Optimize integer operations on floating point
                    constants without -ffast-math
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: antoshkka at gmail dot com
  Target Milestone: ---

If it is known at compile time that changing the floating point constant to
integral constant results in exactly the same value, then replace the floating
point operation with integral operation.

For example

int test2(int lhs) {
    lhs += 2.0;
    return lhs;
}

clang optimizes to the following assembly

test2(int): # @test2(int)
  lea eax, [rdi + 2]
  ret

, while GCC produces a suboptimal assembly:

test(int):
        pxor    xmm0, xmm0
        cvtsi2sd        xmm0, edi
        addsd   xmm0, QWORD PTR .LC0[rip]
        cvttsd2si       eax, xmm0
        ret
.LC0:
        .long   0
        .long   1073741824




More complex examples (where clang fails):

#include <limits>

int test2(int lhs) {
    lhs += 2.000000000000001;
    return lhs;
}

int test3(int lhs) {
    constexpr auto fp = 2.001;
    constexpr int max = std::numeric_limits<int>::max();
    constexpr int min = std::numeric_limits<int>::min();

    // Checking that the result is same even with max * epsilon
    static_assert(
        static_cast<int>(fp + max - fp) == max
        && static_cast<int>(fp + min - fp) == min,
        ""
    );

    return fp + lhs - fp;
}

Reply via email to