diff options
author | Asher Mancinelli <ashermancinelli@gmail.com> | 2025-03-12 08:14:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-12 08:14:46 -0700 |
commit | 982527eef0f284161dd5e09a9b4fc952b332ec92 (patch) | |
tree | 558a2c54520c71c21bd490e67aef7ece49735ca6 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 8be1d1235d58d5b2711295dbd9b36abe4b2401d0 (diff) | |
download | llvm-982527eef0f284161dd5e09a9b4fc952b332ec92.zip llvm-982527eef0f284161dd5e09a9b4fc952b332ec92.tar.gz llvm-982527eef0f284161dd5e09a9b4fc952b332ec92.tar.bz2 |
[flang] Use saturated intrinsics for floating point to integer conversions (#130686)
The saturated floating point conversion intrinsics match the semantics in the standard more closely than the fptosi/fptoui instructions.
Case 2 of 16.9.100 is
> INT (A [, KIND])
> If A is of type real, there are two cases: if |A| < 1, INT (A) has the
value 0; if |A| ≥ 1, INT (A) is the integer whose magnitude is the
largest integer that does not exceed the magnitude of A and whose sign
is the same as the sign of A.
Currently, converting a floating point value into an integer type too
small to hold the constant will be converted to poison in opt, leaving
us with garbage:
```
> cat t.f90
program main
real(kind=16) :: f
integer(kind=4) :: i
f=huge(f)
i=f
print *, i
end program main
# current upstream
> for i in `seq 10`; do; ./a.out; done
-862156992
-1497393344
-739096768
-1649494208
1761228608
-1959270592
-746244288
-1629194432
-231217344
382322496
```
With the saturated fptoui/fptosi intrinsics, we get the appropriate
values
```
# mine
> flang -O2 ./t.f90 && ./a.out
2147483647
> perl -e 'printf "%d\n", (2 ** 31) - 1'
2147483647
```
One notable difference: NaNs being converted to ints will become zero, unlike current flang (and some other compilers). Newer versions of GCC have this behavior.
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
0 files changed, 0 insertions, 0 deletions