https://gcc.gnu.org/g:a29037a8f9c752e41a906f0eac66ff3792e98bcc
commit a29037a8f9c752e41a906f0eac66ff3792e98bcc Author: Alexandre Oliva <ol...@gnu.org> Date: Tue Sep 17 20:15:55 2024 -0300 support noncontiguous ifcombine Diff: --- gcc/tree-ssa-ifcombine.cc | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc index 3d57c615d827..79ccc70b2678 100644 --- a/gcc/tree-ssa-ifcombine.cc +++ b/gcc/tree-ssa-ifcombine.cc @@ -779,13 +779,13 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb, if-conversion helper. We start with BB as the innermost worker basic-block. Returns true if a transformation was done. */ -static bool +static basic_block tree_ssa_ifcombine_bb (basic_block inner_cond_bb) { basic_block then_bb = NULL, else_bb = NULL; if (!recognize_if_then_else (inner_cond_bb, &then_bb, &else_bb)) - return false; + return NULL; /* Recognize && and || of two conditions with a common then/else block which entry edges we can merge. That is: @@ -802,7 +802,7 @@ tree_ssa_ifcombine_bb (basic_block inner_cond_bb) if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, then_bb, else_bb, inner_cond_bb)) - return true; + return bb; if (forwarder_block_to (else_bb, then_bb)) { @@ -814,7 +814,7 @@ tree_ssa_ifcombine_bb (basic_block inner_cond_bb) edge from outer_cond_bb and the forwarder block. */ if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, else_bb, then_bb, else_bb)) - return true; + return bb; } else if (forwarder_block_to (then_bb, else_bb)) { @@ -826,11 +826,11 @@ tree_ssa_ifcombine_bb (basic_block inner_cond_bb) edge from outer_cond_bb and the forwarder block. */ if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, else_bb, then_bb, then_bb)) - return true; + return bb; } } - return false; + return NULL; } /* Main entry for the tree if-conversion pass. */ @@ -881,12 +881,14 @@ pass_tree_ifcombine::execute (function *fun) inner ones, and also that we do not try to visit a removed block. This is opposite of PHI-OPT, because we cascade the combining rather than cascading PHIs. */ + basic_block seen = NULL; + bool changed = false; for (i = n_basic_blocks_for_fn (fun) - NUM_FIXED_BLOCKS - 1; i >= 0; i--) { basic_block bb = bbs[i]; if (safe_is_a <gcond *> (*gsi_last_bb (bb))) - if (tree_ssa_ifcombine_bb (bb)) + if (basic_block outer_bb = tree_ssa_ifcombine_bb (bb)) { /* Clear range info from all stmts in BB which is now executed conditional on a always true/false condition. */ @@ -905,7 +907,24 @@ pass_tree_ifcombine::execute (function *fun) rewrite_to_defined_overflow (&gsi); } cfg_changed |= true; + if (seen) + changed |= true; + else + seen = bb; + /* Go back and check whether the modified outer_bb can be further + optimized. ??? How could it? */ + do + i++; + while (bbs[i] != outer_bb); + continue; } + + if (bb == seen) + { + gcc_assert (!changed); + seen = NULL; + changed = false; + } } free (bbs);