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

            Bug ID: 122770
           Summary: gcc doesn't trigger FE_INVALID when the
                    arithmetic/logical operation is considered INVALID in
                    compliance with IEEE-754 Section-7.2
           Product: gcc
           Version: 14.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mohamed.selim at dxc dot com
  Target Milestone: ---

GCC doesn't seem to comply with IEEE-754 Section 7.2 on INVALID operation.
The section 7.2 according to IEEE-754, found in:
(https://www.gnu.org/software/libc/manual/html_node/FP-Exceptions.html)
(https://www-users.cse.umn.edu/~vinals/tspot_files/phys4041/2020/IEEE%20Standard%20754-2019.pdf)

The exceptions defined in IEEE 754 are:

‘Invalid Operation’

This exception is raised if the given operands are invalid for the operation to
be performed. Examples are (see IEEE 754, section 7):

    1-Addition or subtraction: ∞ - ∞. (But ∞ + ∞ = ∞).
    2-Multiplication: 0 · ∞.
    3-Division: 0/0 or ∞/∞.
    4-Remainder: x REM y, where y is zero or x is infinite.
    5-Square root if the operand is less than zero. More generally, any
mathematical function evaluated outside its domain produces this exception.
    6-Conversion of a floating-point number to an integer or decimal string,
when the number cannot be represented in the target format (due to overflow,
infinity, or NaN).
    7-Conversion of an unrecognizable input string.
    8-Comparison via predicates involving < or >, when one or other of the
operands is NaN. You can prevent this exception by using the unordered
comparison functions instead.


It seems that GCC 14.1.0 deosn't raise the FE_INVALID on points 6 and 8, with
the following results:

(pinf >= qnan): 0
No Exception reported

(zero <= snan): 0
No Exception reported

static_cast<std::int32_t>(some_finite_large_double): 2147483647
No Exception reported

for the program

```
    const auto pinf = std::numeric_limits<double>::infinity();
    const auto ninf = std::copysign(pinf, -1.0);
    const auto qnan = std::numeric_limits<double>::quiet_NaN();
    const auto snan = std::numeric_limits<double>::signaling_NaN();
    constexpr auto some_finite_large_double{
       
598008216632976371697735644702348584536405246902083247220875921706093794716375762404103004004990504111786204800430166155026589905240121409306972824498630058082565445957748647537262486126146850127872.0};
    const double zero{0.0};
    // see point 8
    {
        volatile auto result = (pinf >= qnan);
        fe_status = check_fe();
        std::cout << "\n";
        std::cout << "(pinf >= qnan): " << result << "\n";
        std::cout << fe_status << "\n";
    }
    // see point 8
    {
        volatile auto result = (zero <= snan);
        fe_status = check_fe();
        std::cout << "\n";
        std::cout << "(zero <= snan): " << result << "\n";
        std::cout << fe_status << "\n";
    }
    // see point 6
    {
        volatile auto result =
static_cast<std::int32_t>(some_finite_large_double);
        fe_status = check_fe();
        std::cout << "\n";
        std::cout << "static_cast<std::int32_t>(double): " << result << "\n";
        std::cout << fe_status << "\n";
    }

```

gcc command:
`g++-14 -o test -std=c++17 fe_invalid.cpp -O2 -frounding-math -fsignaling-nans
-ftrapping-math -fno-builtin -fno-strict-aliasing -fwrapv`


So, for comaparison of NaNs and quantization for finite large numbers, e.g.
casting to smaller int32_t. The gcc is not reporting/triggering FE_INVALID

While with clang using `-ffp-exception-behavior=strict`, all of the them report
FE_INVALID as expected.

```
clang++-19 -o test -std=c++20 fe_invalid.cpp -O2 -ffp-exception-behavior=strict
&& ./test

...

(pinf >= qnan): 0
FE_INVALID 

(zero <= snan): 0
FE_INVALID 

static_cast<std::int32_t>(double): -2147483648
FE_INVALID 

```

Using clang command:
`clang++-19 -o test -std=c++20 fe_invalid.cpp -O2
-ffp-exception-behavior=strict`

The results are consistent between x86-64, armv8.1-a and armv9.2-a

Reply via email to