This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: GCC optimizes integer overflow: bug or feature?
- From: Denis Vlasenko <vda dot linux at googlemail dot com>
- To: Paul Brook <paul at codesourcery dot com>
- Cc: gcc at gcc dot gnu dot org, Andrew Haley <aph at redhat dot com>, Paolo Bonzini <bonzini at gnu dot org>, bug-gnulib at gnu dot org
- Date: Sat, 23 Dec 2006 00:44:15 +0100
- Subject: Re: GCC optimizes integer overflow: bug or feature?
- References: <20061218230847.GD3824@iam.uni-bonn.de> <200612220158.39677.vda.linux@googlemail.com> <200612220203.24487.paul@codesourcery.com>
On Friday 22 December 2006 03:03, Paul Brook wrote:
> On Friday 22 December 2006 00:58, Denis Vlasenko wrote:
> > On Tuesday 19 December 2006 23:39, Denis Vlasenko wrote:
> > > There are a lot of 100.00% safe optimizations which gcc
> > > can do. Value range propagation for bitwise operations, for one
> >
> > Or this, absolutely typical C code. i386 arch can compare
> > 16 bits at a time here (luckily, no alighment worries on this arch):
> >
> > int f(char *p)
> > {
> > ? ? if (p[0] == 1 && p[1] == 2) return 1;
> > ? ? return 0;
> > }
>
> Definitely not 100% safe. p may point to memory that is sensitive to the
> access width and/or number of accesses. (ie. memory mapped IO).
Take a look what Linux does when you need to touch a MMIO
or PIO areas. In short: it wraps it in macros/inlines
which do all required magic (which may be rather different
on different architectures. For i386, they amount to
*(volatile char*)p).
"Simple" access to such areas with *p will never work
safely across all spectrum of hardware.
Ok, next example of real-world code I recently saw.
i >= N comparisons are completely superfluous -
programmer probably overlooked that fact.
But gcc didn't notice that either and generated 16 bytes extra
for first function:
# cat t3.c
int i64c(int i) {
if (i <= 0) return '.';
if (i == 1) return '/';
if (i >= 2 && i < 12) return ('0' - 2 + i);
if (i >= 12 && i < 38) return ('A' - 12 + i);
if (i >= 38 && i < 63) return ('a' - 38 + i);
return 'z';
}
int i64c_2(int i) {
if (i <= 0) return '.';
if (i == 1) return '/';
if (i < 12) return ('0' - 2 + i);
if (i < 38) return ('A' - 12 + i);
if (i < 63) return ('a' - 38 + i);
return 'z';
}
# gcc -O2 -c -fomit-frame-pointer t3.c
# nm --size-sort t3.o
00000038 T i64c_2
00000048 T i64c
# gcc -O2 -S -fomit-frame-pointer t3.c
# cat t3.s
.file "t3.c"
.text
.p2align 2,,3
.globl i64c
.type i64c, @function
i64c:
movl 4(%esp), %edx
testl %edx, %edx
jle .L15
cmpl $1, %edx
je .L16
leal -2(%edx), %eax
cmpl $9, %eax
jbe .L17
leal -12(%edx), %eax
cmpl $25, %eax
jbe .L18
leal -38(%edx), %eax
cmpl $24, %eax
ja .L19
leal 59(%edx), %eax
ret
.p2align 2,,3
.L17:
leal 46(%edx), %eax
ret
.p2align 2,,3
.L16:
movl $47, %eax
ret
.p2align 2,,3
.L19:
movl $122, %eax
ret
.L18:
leal 53(%edx), %eax
ret
.L15:
movl $46, %eax
ret
.size i64c, .-i64c
.p2align 2,,3
.globl i64c_2
.type i64c_2, @function
i64c_2:
movl 4(%esp), %eax
testl %eax, %eax
jle .L33
cmpl $1, %eax
je .L34
cmpl $11, %eax
jle .L35
cmpl $37, %eax
jle .L36
cmpl $62, %eax
jg .L37
addl $59, %eax
ret
.p2align 2,,3
.L35:
addl $46, %eax
ret
.p2align 2,,3
.L34:
movb $47, %al
ret
.p2align 2,,3
.L37:
movl $122, %eax
ret
.L36:
addl $53, %eax
ret
.L33:
movl $46, %eax
ret
.size i64c_2, .-i64c_2
.ident "GCC: (GNU) 4.2.0 20061128 (prerelease)"
.section .note.GNU-stack,"",@progbits
--
vda