Compile the following code with options -march=armv7-a -mthumb -Os struct S { int f1, f2; }; int t04(int x, struct S* p) { return p->f1 == 9 && p->f2 == 0; } GCC 4.6 generates: t04: ldr r3, [r1, #0] cmp r3, #9 // A bne .L3 ldr r0, [r1, #4] rsbs r0, r0, #1 it cc movcc r0, #0 bx lr // C .L3: movs r0, #0 // B bx lr Instruction B can be moved before instruction A, and instruction C can be removed. t04: ldr r3, [r1, #0] movs r0, #0 cmp r3, #9 bne .L3 ldr r0, [r1, #4] rsbs r0, r0, #1 it cc movcc r0, #0 .L3: bx lr When compiled to arm instructions, it has the same problem. It should be enabled for code size optimization only because it may execute one more instruction run time. Looks like an if-conversion opportunity.
I have confirmed this on r168563 of trunk.
5.4+ produces: ldr r3, [r1] cmp r3, #9 ittte eq ldreq r0, [r1, #4] clzeq r0, r0 lsreq r0, r0, #5 movne r0, #0 bx lr