Hi, max (MAX_CONDITIONAL_EXECUTE) is doubled for IF-THEN-ELSE since there is one more JUMP for the taken branch to goto the successor of IF-THEN-ELSE. But when the last JUMP is a RETURN, the additional JUMP can be optimized.
Here are the two different assemble codes the attached test case (-O2 -mthumb) for ARM. IT block (current result): cmp r0, #0 itete lt rsblt r0, r0, #2 movwge r3, #21846 addlt r0, r0, r0, lsl #1 movtge r3, 21845 iteee lt lsllt r0, r0, #1 subge r0, r0, #2 smullge r2, r3, r3, r0 subge r0, r3, r0, asr #31 bx lr Branch (after patch): cmp r0, #0 blt .L5 movw r3, #21846 subs r0, r0, #2 movt r3, 21845 smull r2, r3, r3, r0 sub r0, r3, r0, asr #31 bx lr .L5: rsb r0, r0, #2 add r0, r0, r0, lsl #1 lsls r0, r0, #1 bx lr In general, I think the later one will have better performance. The patch will check whether there is RETURN. If has, do not double max. No make check regression and no performance regression for SPECINT2000 for ARM. Is it OK? Thanks! -Zhenqiang ChangeLog: 2013-01-08 Zhenqiang Chen <zhenqiang.c...@linaro.org> * ifcvt.c (cond_exec_process_if_block): Do not increase max when there has RETURN in IF-THEN-ELSE. testsuite/ChangeLog: * gcc.target/arm/if-then-else-return.c: New. diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index b518b0e..70cb53a 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -443,6 +443,8 @@ cond_exec_process_if_block (ce_if_block_t * ce_info, rtx else_first_tail = NULL_RTX; /* First match at the tail of ELSE */ int then_n_insns, else_n_insns, n_insns; enum rtx_code false_code; + bool has_return_p = FALSE; + rtx insn; /* If test is comprised of && or || elements, and we've failed at handling all of them together, just use the last test if it is the special case of @@ -478,11 +480,19 @@ cond_exec_process_if_block (ce_if_block_t * ce_info, n_insns = then_n_insns; max = MAX_CONDITIONAL_EXECUTE; + insn = BB_END (then_bb); + if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn))) + has_return_p = TRUE; + if (else_bb) { int n_matching; + insn = BB_END (else_bb); + if (!has_return_p && JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn))) + has_return_p = TRUE; - max *= 2; + if (!has_return_p) + max *= 2; else_start = first_active_insn (else_bb); else_end = last_active_insn (else_bb, TRUE); else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb);
/* For this case, we do not expect it generates IT block. */ /* { dg-do compile } */ /* { dg-options "-O2 -mthumb" } */ int test (int a) { int r = a; if (r < 0) { r = -r; r += 2; r *= 6; } else { r -= 2; r /= 3; } return r; } /* { dg-final { scan-assembler "\tblt" } } */