[llvm-bugs] [Bug 45155] New: Incorrect optimization while converting from FP to Integer
via llvm-bugs
llvm-bugs at lists.llvm.org
Mon Mar 9 09:59:07 PDT 2020
https://bugs.llvm.org/show_bug.cgi?id=45155
Bug ID: 45155
Summary: Incorrect optimization while converting from FP to
Integer
Product: clang
Version: 9.0
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: C
Assignee: unassignedclangbugs at nondot.org
Reporter: code.optimizer at gmail.com
CC: blitzrakete at gmail.com, dgregor at apple.com,
erik.pilkington at gmail.com, llvm-bugs at lists.llvm.org,
richard-llvm at metafoo.co.uk
Given the following example where there is logic to guard the possible
generation of a floating point error if the double argument is >= LONG_MAX (and
as the comments say, negative values are being ignored):
[dparks at build-lin64 tmp]$ cat uint64.c
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
#define _GNU_SOURCE 1
#include <fenv.h>
static void __attribute__ ((constructor))
trapfpe ()
{
/* Enable some exceptions. At startup all exceptions are masked. */
feenableexcept (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
}
double d_out_of_range = LONG_MAX;
double d_still_in_range = LONG_MAX-(1024*1024);
uint64_t __attribute__((noinline))
dbl_2_u64(double d)
{
// ignore -ive values - that's not the point
return (d < LONG_MAX) ? d : 0x8000000000000000ull;
}
int
main()
{
uint64_t u64;
u64 = dbl_2_u64(d_still_in_range);
printf("d=%f u=%" PRId64 ", u=%#" PRIx64 "\n", d_still_in_range, u64, u64);
u64 = dbl_2_u64(d_out_of_range);
printf("d=%f u=%" PRId64 ", u=%#" PRIx64 "\n", d_out_of_range, u64, u64);
}
[dparks at build-lin64 tmp]$
If compiled with clang 9.0:
[dparks at build-lin64 tmp]$ clang --version
clang version 9.0.0 (/home/<DELETED>/git/official/llvm/tools/clang
45898f3be1d37727502cd6342b14c19e7c94bfae) (/home/<DELETED>/git/official/llvm
5364ee5faec778f1ddf86b6b4b8452df7db191c5)
Target: x86_64-unknown-linux-gnu
Thread model: posix
[dparks at build-lin64 tmp]$ clang uint64.c -march=core2 -O0 -lm
uint64.c:13:3: warning: implicit declaration of function 'feenableexcept' is
invalid in C99 [-Wimplicit-function-declaration]
feenableexcept (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
^
1 warning generated.
[dparks at build-lin64 tmp]$ ./a.out
d=9223372036853727232.000000 u=9223372036853727232, u=0x7ffffffffff00000
Floating point exception
[dparks at build-lin64 tmp]$
At any optimization level (-O0..-O3) the program will abort with a Floating
point exception.
The exception is caused because does not recognize the guard (x < LONG_MAX) and
converts the double to uint64_t and *then* chooses which result to return, the
unsigned integer or 0x8000000000000000ull (code sequence from -O3):
.LCPI1_0:
.quad 4890909195324358656 # double 9.2233720368547758E+18
.text
.globl dbl_2_u64
.p2align 4, 0x90
.type dbl_2_u64, at function
dbl_2_u64: # @dbl_2_u64
.cfi_startproc
# %bb.0:
movsd .LCPI1_0(%rip), %xmm1 # xmm1 = mem[0],zero
minsd %xmm1, %xmm0
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
cvttsd2si %xmm2, %rax
movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
xorq %rax, %rcx
cvttsd2si %xmm0, %rax
ucomisd %xmm1, %xmm0
cmovaeq %rcx, %rax
retq
While code sequences where jumps have been eliminated, the above does not work.
If the code is modified to take into account negative number "( fabs(d) <
LONG_MAX )", floating point errors are still generated.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200309/46c5b947/attachment.html>
More information about the llvm-bugs
mailing list