http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56369
Bug #: 56369 Summary: Missed opportunity to combine comparisons with zero Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: tree-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: olege...@gcc.gnu.org Target: sh*-*-* arm*-*-* I'm not sure whether this is really a tree-optimization or middle-end (e.g. combine) issue... With rev 196091 the following example: extern int func_10 (void*); int func_11 (void* x) { int status = 0; do { status = func10 (x); status = status < 0 ? status : 0; } while (status >= 0); return status; } compiled for SH4 with -O2 -m4 results in: _func_11: mov.l r8,@-r15 mov.l r9,@-r15 mov r4,r9 mov.l .L8,r8 sts.l pr,@-r15 .align 2 .L4: jsr @r8 mov r9,r4 cmp/pl r0 // T = r0 > 0 bt/s .L4 tst r0,r0 // T = r0 == 0 bt .L4 lds.l @r15+,pr mov.l @r15+,r9 rts mov.l @r15+,r8 .L9: .align 2 .L8: .long _func10 As seen above, the two comparisons could be done with a single one: cmp/pz r0 // T = r0 >= 0 I've tried out a few SH specific things to see if combine would do it, but it just won't combine the two. I guess because the two comparisons end up in two different basic blocks. On ARM, there's a smin insn defined, but the problem is the similar. The example above compiled with -O2 results in: func_11: stmfd sp!, {r4, lr} mov r4, r0 .L3: mov r0, r4 bl func10 and r0, r0, r0, asr #31 // smin (r0, 0) cmp r0, #0 // r == 0 beq .L3 ldmfd sp!, {r4, lr} bx lr which could be done without the smin (r0, 0), and save the and insn: func_11: stmfd sp!, {r4, lr} mov r4, r0 .L3: mov r0, r4 bl func10 cmp r0, #0 bge .L3 ldmfd sp!, {r4, lr} bx lr