llvm / llvm/llvm-project

[Flang] Calculation error for PRODUCT with -O0

Open
#211,437 2 comments 0 reactions 1 assignee Claimed by @yus3710-fj View on GitHub
flang:runtime
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Summary

The result of the PRODUCT intrinsic differs between `-O0` and `-O1`. The expected result is negative zero, but Flang returns positive zero with `-O0`. Some processors may not distinguish between positive and negative zeros, but Flang seems to do so.

* 7.1.3 Set of values

> The sets of valid values for integer, character, and real are processor dependent.

* 7.4.3.2 Real type

> The real type includes a zero value. Processors that distinguish between positive and negative zeros shall treat them as mathematically equivalent
> * in all intrinsic relational operations, and
> * as actual arguments to intrinsic procedures other than those for which it is explicitly specified that negative zero is distinguished.

### Reproducer

* test.f90

```fortran
use IEEE_ARITHMETIC
real,parameter, dimension (2) :: b = [0.0,-30.0]
real,dimension(2)::a
real:: d

a = b
d = product(a)

print *, sign(1.0,d)
print "('product in exec exp: ',z8.8)", d
if (IEEE_CLASS(d) /= IEEE_NEGATIVE_ZERO) then
print "('Error product in exec exp: ',z8.8)", d
end if

print *,'pass'
end
```

* commands

```console
$ flang --version
flang version 24.0.0git (https://github.com/llvm/llvm-project.git ba9d799b1bf2433bf960a08ff995497f5b6d2feb)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to/llvm/build/bin
Build config: +assertions
$ flang test.f90 && ./a.out
1.
product in exec exp: 00000000
Error product in exec exp: 00000000
pass
$ flang test.f90 -O1 && ./a.out
-1.
product in exec exp: 80000000
pass
```

## Non-problematic Conditions

The issue does not occur under the following conditions:
* Giving the result as a constant (i.e., allowing the frontend to perform folding):
```diff
@@ -1,10 +1,7 @@
use IEEE_ARITHMETIC
real,parameter, dimension (2) :: b = [0.0,-30.0]
real,dimension(2)::a
-real:: d
-
-a = b
-d = product(a)
+real,parameter :: d = product(b)

print *, sign(1.0,d)
print "('product in exec exp: ',z8.8)", d
```
* Exchanging the signs of elements in the input array (i.e., giving `[-0.0,30.0]` to PRODUCT).
* However, PRODUCT incorrectly returns negative zero for `[-0.0,-30.0]`.

## Other Compilers

* GFortran
```console
$ gfortran --version
GNU Fortran (GCC) 16.1.0
Copyright (C) 2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gfortran test.f90 && ./a.out
-1.00000000
product in exec exp: 80000000
pass
$ gfortran test.f90 -O3 && ./a.out
-1.00000000
product in exec exp: 80000000
pass
```

* Intel Fortran
```console
$ ifx --version
ifx (IFX) 2025.3.2 20260112
Copyright (C) 1985-2026 Intel Corporation. All rights reserved.

$ ifx -O0 test.f90 && ./a.out
1.000000
product in exec exp: 80000000
pass
$ ifx -O3 test.f90 && ./a.out
1.000000
product in exec exp: 80000000
pass
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.