Consider the following simple function (I can reproduce the bug just saving
this code as a .c file and compiling it with -S to see the asm output and using
-O1):
extern void a( void );
extern void b( void );
extern void c( void );
int weird(int t)
{
if (t > 32768) t = 32768;
a();
b();
c();
if (t < -32768) t = -32768;
return t;
}
GCC-4.1.1 seems to duplicate the block between the two ifs no matter what code
I put between them, here's the assembler output:
weird:
pushl %ebp
movl%esp, %ebp
pushl %ebx
subl$4, %esp
movl8(%ebp), %ebx
cmpl$32768, %ebx
jg .L2
calla
callb
callc
movl%ebx, %eax
cmpl$-32768, %ebx
jge .L5
movl$-32768, %eax
jmp .L5
.L2:
calla
callb
callc
movl$32768, %eax
.L5:
addl$4, %esp
popl%ebx
popl%ebp
ret
As you can see the first conditional branch skips over the code standing for
the second if - as it should since the conditions are mutually exclusive - but
the calls in-between them have to be replicated on the other side of the
branch. Now the problem is no matter how many calls I put in between the if()s
they will be replicated on both sides instead of being factored. Considering
that -O1 shouldn't turn on optimizations which cause trade-offs between size
and speed this seems a bug to me.
--
Summary: Poor optimization causes unbounded code duplication
Product: gcc
Version: 4.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: gabriele dot svelto at gmail dot com
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29285