public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug target/107174] New: [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2
@ 2022-10-06 18:49 rozne at pabich dot waw.pl
2022-10-06 18:54 ` [Bug target/107174] " pinskia at gcc dot gnu.org
2022-10-06 18:56 ` pinskia at gcc dot gnu.org
0 siblings, 2 replies; 3+ messages in thread
From: rozne at pabich dot waw.pl @ 2022-10-06 18:49 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107174
Bug ID: 107174
Summary: [ARM] Wrong opcodes *.f64.s32 (signed) in conversion
[unsigned ->double] with -O2
Product: gcc
Version: 8.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: rozne at pabich dot waw.pl
Target Milestone: ---
When building for 32-bit ARMhf with optimization -O2 and higher sometimes wrong
conversion opcodes are generated - *.f64.s32 (signed conversion) instead of
*.f64.u32 (unsigned). These are very rare cases, and are higly sensitive to
code arrangement.
The bug seems to be present at least since GCC 8.3. GCC 8.4 and 12 are
affected.
GCC 7.5 is not affected (and very old 4.4 also).
It is not present on x86 architecture, seems to be ARM specific.
Example cross-compiled on Ubuntu 18.04.6 (x86_64):
arm-linux-gnueabihf-gcc-8 -Wall -Wextra -O2 -static
GCC 8.4 version:
arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-1ubuntu1~18.04) 8.4.0
Code:
#include <stdio.h>
__attribute__((noinline)) double deltaToDouble(int a, int b) {
if (a < b) {
unsigned int delta = b - a;
return -((double)delta);
} else {
unsigned int delta = a - b;
return (double)delta;
}
}
int main() {
return (deltaToDouble( 2000000000, -1000000000) != 3000000000.0 ||
deltaToDouble(-1000000000, 2000000000) != -3000000000.0);
}
Disassembly:
<deltaToDouble>:
cmp r0, r1
itete lt
sublt r0, r1, r0
subge r0, r0, r1
vmovlt s15, r0
vmovge s15, r0
itte lt
vcvtlt.f64.s32 d0, s15
vneglt.f64 d0, d0
vcvtge.f64.s32 d0, s15
bx lr
It is easy to see that opcodes are for signed int32 conversion (vcvtlt.f64.s32,
vcvtge.f64.s32). Code generated by older GCC 7.5 is same except correct opcodes
for unsigned int32 (vcvtlt.f64.u32, vcvtge.f64.u32) were used.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Bug target/107174] [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2
2022-10-06 18:49 [Bug target/107174] New: [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2 rozne at pabich dot waw.pl
@ 2022-10-06 18:54 ` pinskia at gcc dot gnu.org
2022-10-06 18:56 ` pinskia at gcc dot gnu.org
1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-10-06 18:54 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107174
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |INVALID
Status|UNCONFIRMED |RESOLVED
--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
There is no bug here as signed integer overflow is undefined.
You should do the following if you want unsigned conversion.
__attribute__((noinline)) double deltaToDouble(int a, int b) {
unsigned ua = a;
unsigned ub = b;
if (a < b) {
unsigned int delta = ub - ua;
return -((double)delta);
} else {
unsigned int delta = ua - ub;
return (double)delta;
}
}
Otherwise GCC will assume (a - b) and (b - a) will never be overflow (as it is
undefined) and you will get the signed coversions.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Bug target/107174] [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2
2022-10-06 18:49 [Bug target/107174] New: [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2 rozne at pabich dot waw.pl
2022-10-06 18:54 ` [Bug target/107174] " pinskia at gcc dot gnu.org
@ 2022-10-06 18:56 ` pinskia at gcc dot gnu.org
1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-10-06 18:56 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107174
--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
-fsanitize=undefined catches this at runtime:
/app/example.cpp:10:28: runtime error: signed integer overflow: 2000000000 -
-1000000000 cannot be represented in type 'int'
/app/example.cpp:7:28: runtime error: signed integer overflow: 2000000000 -
-1000000000 cannot be represented in type 'int'
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-10-06 18:56 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-06 18:49 [Bug target/107174] New: [ARM] Wrong opcodes *.f64.s32 (signed) in conversion [unsigned ->double] with -O2 rozne at pabich dot waw.pl
2022-10-06 18:54 ` [Bug target/107174] " pinskia at gcc dot gnu.org
2022-10-06 18:56 ` pinskia at gcc dot gnu.org
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).