This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/37176] New: [arm] Optimizer omits loop condition leading to failing code
- From: "berndorfer at festo dot at" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 20 Aug 2008 10:13:52 -0000
- Subject: [Bug c/37176] New: [arm] Optimizer omits loop condition leading to failing code
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
My recent 2.6.21.6-rt21 kernel build for ARM dumps a NULL pointer dereference
exception due to a missing loop termination condition that was omitted by the
gcc 4.3.1 optimizer.
This happens in net/ipv4/inet_hashtables.c, in function
inet_lookup_listener_slow which is inlined by the optimizer (-Os, -O2, -O3)
into function inet_lookup_listener:
===== C-Code:
sk_for_each(sk, node, head) {
const struct inet_sock *inet = inet_sk(sk);
if (inet->num == hnum && !ipv6_only_sock(sk)) {
...
}
}
===== Generated assembler code with my comments:
.L57:
mov r4, r0
ldr r1, [r4], #-8 @ node = node->next; THIS FAILS !!!
#APP
@ 108 "include/asm/processor.h" 1
pld [r1, #0] @ preload node
@ 0 "" 2
ldrh r3, [r4, ip] @ load 'inet->num' ...
mov r0, r1
cmp r3, r5 @ ... and compare this with 'hnum'
bne .L57 @ if 'inet->num != hnum' continue loop
b .L58 @ do the work inside the loop
===== why this code fails:
If you look at sk_for_each macro it is replaced with something like:
for (node=head; node && ...; node=node->next)
Unfortunately the condition for node being non zero is not evaluated every
loop. It seems to me that this important condition is replaces with the inner
if-condition inet->num == hnum whereas node!=0 is evaluated later on.
===== possible workarounds:
Do not use -Os, -O2, -O3. -O1 and -O0 works.
E.g. this is the code for the -O1 case:
.L47:
mov r3, r0
mov r4, ip
.L50:
cmp r2, #0 @ CHECKS node != 0 !!!!!!!
beq .L49 @ terminates loop
mov r0, r3
mov ip, r4
b .L51 @ next loop
.L43:
mvn r0, #0
mov ip, #0
mov r3, #516
add lr, r3, #2
.L51:
mov r4, r2
ldr r2, [r4], #-8
#APP
@ 108 "include/asm/processor.h" 1
pld [r2, #0]
@ 0 "" 2
mov r1, r4
ldrh r3, [r4, lr]
cmp r3, r5
bne .L47
b .L54
.L49:
===== Compiler version: 4.3.1 (release version)
===== System type: ARM Linux, XScale-PXA255 (ARMv5-TE)
===== Compiler configure command line:
$ ../gcc-4.3.1/configure --prefix=/tmp/tc3/sysroot/cross --target=arm-linux
--host=i686-pc-linux-gnu --disable-multilib --with-sysroot=/tmp/tc3/sysroot
--disable-nls --enable-shared --enable-languages=c,c++ --enable-__cxa_atexit
--enable-c99 --enable-threads=posix --with-float=soft
===== Commandline: (generated by kernel makefile hierarchy)
arm-linux-gcc -Wp,-MD,net/ipv4/.inet_hashtables.o.d -nostdinc -isystem
tmp/tc3/sysroot/cross/lib/gcc/arm-linux/4.3.1/include -D__KERNEL__ -Iinclude
in
clude include/linux/autoconf.h -mlittle-endian -Wall -Wundef
-Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -marm
fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu
-mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=xscale
-Wa,-mcpu=xscale -msoft-float -Uarm -fno-omit-frame-pointer
-fno-optimize-sibling-calls -fno-stack-protector -Wdeclaration-after-statement
-Wno-pointer-sign -DFW_VERSION=\"1.1.1-cec0\" -D"KBUILD_STR(s)=\#s"
-D"KBUILD_BASENAME=KBUILD_STR(inet_hashtables)" -D"KBUILD_MODNAME=KBUILD_STR
(inet_hashtables)" -c -o net/ipv4/inet_hashtables.o net/ipv4/inet_hashtables.c
===== Compiler outputs/warnings: none
===== Attachments: .c, .i and .s files
--
Summary: [arm] Optimizer omits loop condition leading to failing
code
Product: gcc
Version: 4.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: berndorfer at festo dot at
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: arm-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37176