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);

Reply via email to