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