[Bug regression/30173] New: Regression in ARM softfloat routine __adddf3
dpm at danger dot com
gcc-bugzilla@gcc.gnu.org
Tue Dec 12 16:00:00 GMT 2006
Version Information
[dpm@spenseweed ~]$ arm-elf-gcc -v
Using built-in specs.
Target: arm-elf
Configured with: ../gcc-4.1.1/configure
--prefix=/usr/local/armdev-926ej-s-4.1.1 --target=arm-elf --enable-languages=c
--with-float=soft --enable-interwork --enable-multilib --with-cpu=arm926ej-s
--disable-threads --with-dwarf2 --without-headers
Thread model: single
gcc version 4.1.1
[dpm@spenseweed ~]$
Introduction
This bug was found by building Danger's Java platform using GCC 4.1.1 and
running it against the Java ME CLDC TCK 1.1a. The test suite had previously
passed when building our Java platform against GCC 3.4.3, so the new test
failures constituted a regression. The proposed fix was confirmed to correct
the failing tests without introducing other failures in the test suite.
The bug should be reproducible using the appended .i file when compiler
optimizations are disabled; however, I cannot confirm that because our embedded
product requires our supporting OS. If I try to compile this test, I get the
following link error:
[dpm@spenseweed ~]$ arm-elf-gcc -save-temps -o test test.c
/usr/local/armdev-926ej-s-4.1.1/lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld:
crt0.o: No such file: No such file or directory
collect2: ld returned 1 exit status
Analysis of the bug
The test case should simply return; however, on our system it goes into an
infinite loop. The cause of the bug is found in the function __adddf3 in
gcc/config/arm/ieee754-df.S. In the test case, the inputs to this function are:
r0 10000000000000000000000000000000
r1 00000000000000000000000000000001
r2 00000000000000000000000000000000
r3 00000000000000000000000000000000
Hand simulation of the code shows that r4 and r5 are set as follows:
r4 00000000000000000000000000000000
r5 00000000000000000000000000000000
__adddf3 correctly identifies that 0.0 is one of the inputs. As a result, we
branch to LSYM(Lad_s) and then reach this comment:
@ Result is x + 0.0 = x or 0.0 + y = y.
It is here that we encounter the bug. The code tries to determine which
argument is 0.0 by testing r4.
teq r4, #0
If the test passes, the first argument is thought to be 0.0, so the second
argument is moved into r0/r1 for return, and the function exits. If the test
fails, the function exits directly, returning the first argument.
This test is insufficient when the first argument is a very small number. In
that case, r4 will be 0, but the first argument overall will be non-zero. As a
result, the function returns the second argument when it should have returned
the first.
To fix the bug, the following line should be inserted after the above line:
teqeq xl, #0
This verifies that the entire first argument is indeed 0, not just the high 32
bits.
test.i file
[dpm@spenseweed ~]$ cat test.i
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test.c"
int
main()
{
double x = -4.9E-324;
double y = +0.0;
double z = x + y;
while (z != x)
;
return 0;
}
Full unified patch:
--- ieee754-df.S.orig 2006-12-06 14:57:12.000000000 -0800
+++ ieee754-df.S 2006-12-06 14:57:30.000000000 -0800
@@ -327,6 +327,7 @@
@ Result is x + 0.0 = x or 0.0 + y = y.
teq r4, #0
+ teqeq xl, #0
moveq xh, yh
moveq xl, yl
RETLDM "r4, r5"
--
Summary: Regression in ARM softfloat routine __adddf3
Product: gcc
Version: 4.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: regression
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dpm at danger dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30173
More information about the Gcc-bugs
mailing list