For translating a compound logical expression GCC uses an ldm instruction to interrupt the evaluation of conditions fields. When optimizing for size it would be promising to use condition fields instead of the ldm, if possible. --- c example --- int func(char*); int foo (char* name) { int n = func (name); return (name[n-4] == 'a' && name[n-3] == 'b' && name[n-2] == 'c' && name[n-1] == 'd'); } --- arm code --- foo: mov ip, sp stmfd sp!, {r4, fp, ip, lr, pc} sub fp, ip, #4 mov r4, r0 bl func add r4, r4, r0 ldrb r3, [r4, #-4] cmp r3, #97 mov r0, #0 <- OLD ldmneea fp, {r4, fp, sp, pc} <- OLD ldrb r3, [r4, #-3] <- OLD cmp r3, #98 <- OLD ldmneea fp, {r4, fp, sp, pc} <- OLD ldrb r3, [r4, #-2] <- OLD cmp r3, #99 <- OLD ldmneea fp, {r4, fp, sp, pc} <- OLD ldrb r3, [r4, #-1] <- OLD cmp r3, #100 <- OLD movne r0, #0 moveq r0, #1 ldmea fp, {r4, fp, sp, pc} --- possible solution --- foo: mov ip, sp stmfd sp!, {r4, fp, ip, lr, pc} sub fp, ip, #4 mov r4, r0 bl func add r4, r4, r0 ldrb r3, [r4, #-4] cmp r3, #97 ldreqb r3, [r4, #-3] <- NEW cmpeq r3, #98 <- NEW ldreqb r3, [r4, #-2] <- NEW cmpeq r3, #99 <- NEW ldreqb r3, [r4, #-1] <- NEW cmpeq r3, #100 <- NEW movne r0, #0 moveq r0, #1 ldmea fp, {r4, fp, sp, pc}
Confirmed with mainline (20030825).
I verified that this is fixed in GCC 3.4, 4.0 as well as on mainline. So this can be closed.
It looks worse on the mainline: stmfd sp!, {r4, lr} mov r4, r0 bl func add r4, r4, r0 ldrb r3, [r4, #-4] @ zero_extendqisi2 cmp r3, #97 bne .L2 ldrb r3, [r4, #-3] @ zero_extendqisi2 cmp r3, #98 bne .L2 ldrb r3, [r4, #-2] @ zero_extendqisi2 cmp r3, #99 bne .L2 ldrb r3, [r4, #-1] @ zero_extendqisi2 cmp r3, #100 movne r0, #0 moveq r0, #1 ldmfd sp!, {r4, pc} .L2: mov r0, #0 ldmfd sp!, {r4, pc} .size foo, .-foo
With Mainline today it looks worse - stmfd sp!, {r4, lr} mov r4, r0 bl func add r0, r4, r0 ldrb r3, [r0, #-4] @ zero_extendqisi2 cmp r3, #97 beq .L6 .L2: mov r0, #0 ldmfd sp!, {r4, pc} .L6: ldrb r3, [r0, #-3] @ zero_extendqisi2 cmp r3, #98 bne .L2 ldrb r3, [r0, #-2] @ zero_extendqisi2 cmp r3, #99 bne .L2 ldrb r0, [r0, #-1] @ zero_extendqisi2 cmp r0, #100 movne r0, #0 moveq r0, #1 ldmfd sp!, {r4, pc}
This isn't something that should be fixed in the back-end, but most likely an enhancement to a pass such as ifcvt. To handle this case we would have to teach ifcvt about dominated conditions and conditional comparisons -- at present it can only handle conditional insns that do not modify the predicating condition.
Does the ARM backend already support conditional compares?
(In reply to comment #6) > Does the ARM backend already support conditional compares? > Yes, but only by manipulating store-flag sequences in the combine pass. That's a poor-man's implementation and it can lead to some sequences that don't get fully simplified. That code could be compiled to ldrb r3, [r4, #-4] @ zero_extendqisi2 cmp r3, #97 ldrbeq r3, [r4, #-3] @ zero_extendqisi2 cmpeq r3, #98 ldrbeq r3, [r4, #-2] @ zero_extendqisi2 cmpeq r3, #99 ldrbeq r3, [r4, #-1] @ zero_extendqisi2 cmpeq r3, #100 but the compiler currently has no chance of achieving that.