it seems the code which notices things like assert(x > 0) to help strength-reduce division to shifts doesn't help if the divide is inside a loop. for example:
% cat idiv-assert.c void fail(void) __attribute__((noreturn)); int bar(int); int foo(int x) { int i; int s = 0; if (x <= 0) fail(); for (i = 0; i < x; ++i) { s += bar(i/4); } return s; } % gcc -g -O3 -Wall -c -o idiv-assert.o idiv-assert.c % objdump -dr idiv-assert.o idiv-assert.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <foo>: 0: 41 54 push %r12 2: 41 89 fc mov %edi,%r12d 5: 55 push %rbp 6: 31 ed xor %ebp,%ebp 8: 53 push %rbx 9: 31 db xor %ebx,%ebx b: 85 ff test %edi,%edi d: 7e 22 jle 31 <foo+0x31> f: 90 nop 10: 8d 7b 03 lea 0x3(%rbx),%edi 13: 85 db test %ebx,%ebx 15: 0f 49 fb cmovns %ebx,%edi 18: 83 c3 01 add $0x1,%ebx 1b: c1 ff 02 sar $0x2,%edi 1e: e8 00 00 00 00 callq 23 <foo+0x23> 1f: R_X86_64_PC32 bar+0xfffffffffffffffc 23: 01 c5 add %eax,%ebp 25: 41 39 dc cmp %ebx,%r12d 28: 7f e6 jg 10 <foo+0x10> 2a: 5b pop %rbx 2b: 89 e8 mov %ebp,%eax 2d: 5d pop %rbp 2e: 41 5c pop %r12 30: c3 retq 31: e8 00 00 00 00 callq 36 <foo+0x36> 32: R_X86_64_PC32 fail+0xfffffffffffffffc % gcc -v Using built-in specs. Target: x86_64-unknown-linux-gnu Configured with: ../gcc/configure --prefix=/home/odo/gcc --disable-multilib --disable-biarch x86_64-unknown-linux-gnu --enable-languages=c Thread model: posix gcc version 4.3.0 20070217 (experimental) note that gcc handles a more trivial case just fine: if (x <= 0) fail(); return x / 4; -dean -- Summary: strength-reduce idiv given assertion numerator is positive Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: pending AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: dean at arctic dot org GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31521