This patch improves ifcombine by doing two things. First tries to see if the then and else are swapped and handles that case. Also it handles the case where the else or then cases have an empty basic block instead of just fall through.
OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. Thanks, Andrew Pinski ChangeLog: * tree-ssa-ifcombine.c (recognize_if_then_else): Handle the case where the the then and else are swapped. (tree_ssa_ifcombine_bb): Handle the case were we have an empty basic block for either then or else. * gcc.dg/tree-ssa/ssa-ifcombine-8.c: New testcase. * gcc.dg/tree-ssa/ssa-ifcombine-9.c: New testcase.
Index: testsuite/gcc.dg/tree-ssa/ssa-ifcombine-8.c =================================================================== --- testsuite/gcc.dg/tree-ssa/ssa-ifcombine-8.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/ssa-ifcombine-8.c (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase for PR31657. */ + +int f(int x, int a, int b) +{ + int t = 0; + int c = 1 << a; + if (!(x & 1)) + t = 0; + else + if (x & (1 << 2)) + t = 3; + else + t = 0; + return t; +} +/* { dg-final { scan-tree-dump "& 5" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: testsuite/gcc.dg/tree-ssa/ssa-ifcombine-9.c =================================================================== --- testsuite/gcc.dg/tree-ssa/ssa-ifcombine-9.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/ssa-ifcombine-9.c (revision 0) @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase for PR31657. */ +int g(void); +int f(int x, int a, int b) +{ + int t = 0; + int c = 1 << a; + if (!(x & 1)) + t = 0; + else + if (x & (1 << 2)) + t = g(); + else + t = 0; + return t; +} + +/* { dg-final { scan-tree-dump "& 5" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: tree-ssa-ifcombine.c =================================================================== --- tree-ssa-ifcombine.c (revision 189800) +++ tree-ssa-ifcombine.c (working copy) @@ -78,12 +78,34 @@ recognize_if_then_else (basic_block cond return false; /* Check if the edge destinations point to the required block. */ - if (*then_bb - && t->dest != *then_bb) - return false; - if (*else_bb - && e->dest != *else_bb) - return false; + if ((*then_bb + && t->dest != *then_bb) + || (*else_bb + && e->dest != *else_bb)) + { + gimple stmt; + tree cond; + edge ee; + if ((*then_bb + && e->dest != *then_bb) + || (*else_bb + && t->dest != *else_bb)) + return false; + stmt = last_stmt (cond_bb); + cond = fold_build2 (gimple_cond_code (stmt), boolean_type_node, + gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); + cond = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (cond), cond); + /* The opposite of the condition does not reduce so we cannot flip around the condition. */ + if (!is_gimple_condexpr (cond)) + return false; + e->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); + t->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); + gimple_cond_set_condition_from_tree (stmt, unshare_expr (cond)); + update_stmt (stmt); + ee = e; + e = t; + t = ee; + } if (!*then_bb) *then_bb = t->dest; @@ -590,6 +612,29 @@ tree_ssa_ifcombine_bb (basic_block inner return ifcombine_ifandif (inner_cond_bb, outer_cond_bb); } + /* The && form is characterized by a common else_bb with + the two edges leading to it mergable. The latter is + guaranteed by matching PHI arguments in the else_bb and + the inner cond_bb having no side-effects. */ + if (empty_block_p (else_bb) + && single_succ_p (else_bb) + && single_succ_edge (else_bb)->dest == then_bb + && recognize_if_then_else (outer_cond_bb, &inner_cond_bb, &then_bb) + && same_phi_args_p (outer_cond_bb, else_bb, then_bb) + && bb_no_side_effects_p (inner_cond_bb)) + { + /* We have + <outer_cond_bb> + if (q) goto inner_cond_bb; else goto else_bb; + <inner_cond_bb> + if (p) goto ...; else goto else_bb; + ... + <else_bb> + ... + */ + return ifcombine_ifandif (inner_cond_bb, outer_cond_bb); + } + /* The || form is characterized by a common then_bb with the two edges leading to it mergable. The latter is guaranteed by matching PHI arguments in the then_bb and the inner cond_bb @@ -599,6 +644,27 @@ tree_ssa_ifcombine_bb (basic_block inner && bb_no_side_effects_p (inner_cond_bb)) { /* We have + <outer_cond_bb> + if (q) goto then_bb; else goto inner_cond_bb; + <inner_cond_bb> + if (q) goto then_bb; else goto ...; + <then_bb> + ... + */ + return ifcombine_iforif (inner_cond_bb, outer_cond_bb); + } + /* The || form is characterized by a common then_bb with the + two edges leading to it mergable. The latter is guaranteed + by matching PHI arguments in the then_bb and the inner cond_bb + having no side-effects. */ + if (empty_block_p (then_bb) + && single_succ_p (then_bb) + && single_succ_edge (then_bb)->dest == else_bb + && recognize_if_then_else (outer_cond_bb, &else_bb, &inner_cond_bb) + && same_phi_args_p (outer_cond_bb, inner_cond_bb, else_bb) + && bb_no_side_effects_p (inner_cond_bb)) + { + /* We have <outer_cond_bb> if (q) goto then_bb; else goto inner_cond_bb; <inner_cond_bb>