The following code: struct A { int r0; int r1; }; void sigh(struct A *a, const int d) { int i; for (i = 0; i < 8; ++i) { if (d & (1U << i)) a->r0 = 1; else a->r1 = 1; } }
compiled using arm-none-eabi-gcc -mcpu=arm7tdmi -marm -O3 -S -o- tmp2.c produces very poor code: sigh: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. tst r1, #1 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #2 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #4 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #8 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #16 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #32 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #64 moveq r3, #1 movne r3, #1 streq r3, [r0, #4] strne r3, [r0, #0] tst r1, #128 movne r3, #1 moveq r3, #1 strne r3, [r0, #0] streq r3, [r0, #4] bx lr Note the silly occurrences of: moveq r1, #1 movne r1, #1 More importantly, there is no need to load the constant 1 into r3 in every iteration. It should be loaded only once before the (unrolled) loop. -- Summary: Very poor code generation (unnecessary conditionals and reloads) for ARM Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: tobias at ringis dot se GCC host triplet: x86_64-redhat-linux GCC target triplet: arm-none-eabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43908