Skip to content

[clang] -ffast-math in 19.1.0 prevents function from returning intended __m128 bitmask #118152

@shinfd

Description

@shinfd

Hello.

A function like below may return an unexpected __m128 value when compiled using clang 19.1.0 with -ffast-math -O2.

auto maskFunc = []() {
    return _mm_castsi128_ps(_mm_set_epi32( 0x7FFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF ));
};

Sample code at Compiler Explorer https://godbolt.org/z/xG5r1n7xY , demonstrating different result from lambda return and immediate assignment.

Workaround:

  • Remove -ffast-math or -O2
  • Add -fno-finite-math-only
  • Use clang 18

I can speculate that this is because the i32 values set in the sample function are NaN when interpreted as float, and -ffast-math optimizer discarded such return value as invalid. However, the __m128 value was intended for use in bitwise operation intrinsics like _mm_and_ps(), and not as a value in floating point calculation.

This was permitted in clang 18, but no longer as of clang 19.1.0. Was this behavior change intended?

If so, is guaranteeing assignment and returning of an arbitrary __m128 value, which may contain NaN or INFINITY, no longer possible with -ffast-math enabled for clang 19 onward? In addition to bitwise intrinsics, comparison intrinsics like _mm_cmpgt_ps() will use 0xFFFFFFFF as truth values, so handling non-finite value are necessary for multiple intrinsics by definition.

Or, is it simply not recommended to use these intrinsics with -ffast-math, or more specifically -ffinite-math-only? Using -ffast-math -fno-finite-math-only combo is a valid workaround, but will affect the entire compilation, potentially preventing other uninvolved code from taking benefit of finite-math-only-optimization.

Regards,

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions