https://gcc.gnu.org/g:3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78

commit 3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78
Author: Alexandre Oliva <ol...@gnu.org>
Date:   Thu Sep 19 02:43:51 2024 -0300

    refactor ifcombine

Diff:
---
 gcc/tree-ssa-ifcombine.cc | 181 +++++++++++++++++++++++-----------------------
 1 file changed, 89 insertions(+), 92 deletions(-)

diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
index eb4317bebdfb..3d57c615d827 100644
--- a/gcc/tree-ssa-ifcombine.cc
+++ b/gcc/tree-ssa-ifcombine.cc
@@ -107,6 +107,14 @@ recognize_if_then_else (basic_block cond_bb,
   if (!*else_bb)
     *else_bb = e->dest;
 
+  gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (cond_bb));
+  if (!cond)
+    return false;
+
+  if (CONSTANT_CLASS_P (gimple_cond_lhs (cond))
+      && CONSTANT_CLASS_P (gimple_cond_rhs (cond)))
+    return false;
+
   return true;
 }
 
@@ -407,15 +415,67 @@ fold_truth_andor_maybe_separate (location_t loc,
                                 enum tree_code rcode, tree rl_arg, tree rr_arg,
                                 tree *separatep);
 
+/* Replace the conditions in INNER_COND and OUTER_COND with COND and COND2.
+   COND and COND2 are computed for insertion at INNER_COND, with OUTER_COND
+   replaced with a constant, but if there are intervening blocks, it's best to
+   adjust COND for insertion at OUTER_COND, placing COND2 at INNER_COND.  */
+
+static tree
+ifcombine_replace_cond (gcond *inner_cond, bool inner_inv,
+                       gcond *outer_cond, bool outer_inv,
+                       tree cond, bool must_canon,
+                       tree cond2)
+{
+  tree t = cond;
+  bool result_inv = inner_inv;
+
+  /* ??? Support intervening blocks.  */
+  if (single_pred (gimple_bb (inner_cond)) != gimple_bb (outer_cond))
+    return NULL_TREE;
+
+  /* ??? Use both conditions.  */
+  if (cond2)
+    t = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (t), cond, cond2);
+
+  /* ??? Insert at outer_cond.  */
+  if (result_inv)
+    t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
+  tree ret = t;
+
+  if (tree tcanon = canonicalize_cond_expr_cond (t))
+    ret = t = tcanon;
+  else if (must_canon)
+    return NULL_TREE;
+  if (!is_gimple_condexpr_for_cond (t))
+    {
+      gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond);
+      t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
+                                     NULL, true, GSI_SAME_STMT);
+    }
+  gimple_cond_set_condition_from_tree (inner_cond, t);
+  update_stmt (inner_cond);
+
+  /* Leave CFG optimization to cfg_cleanup.  */
+  gimple_cond_set_condition_from_tree (outer_cond,
+                                      outer_inv
+                                      ? boolean_false_node
+                                      : boolean_true_node);
+  update_stmt (outer_cond);
+
+  update_profile_after_ifcombine (gimple_bb (inner_cond),
+                                 gimple_bb (outer_cond));
+
+  return ret;
+}
+
 /* If-convert on a and pattern with a common else block.  The inner
    if is specified by its INNER_COND_BB, the outer by OUTER_COND_BB.
-   inner_inv, outer_inv and result_inv indicate whether the conditions
-   are inverted.
+   inner_inv, outer_inv indicate whether the conditions are inverted.
    Returns true if the edges to the common else basic-block were merged.  */
 
 static bool
 ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
-                  basic_block outer_cond_bb, bool outer_inv, bool result_inv)
+                  basic_block outer_cond_bb, bool outer_inv)
 {
   gimple_stmt_iterator gsi;
   tree name1, name2, bit1, bit2, bits1, bits2;
@@ -454,26 +514,13 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
       t2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
       t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE,
                                     true, GSI_SAME_STMT);
-      t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR,
-                      boolean_type_node, t2, t);
-      t = canonicalize_cond_expr_cond (t);
-      if (!t)
-       return false;
-      if (!is_gimple_condexpr_for_cond (t))
-       {
-         gsi = gsi_for_stmt (inner_cond);
-         t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
-                                         NULL, true, GSI_SAME_STMT);
-       }
-      gimple_cond_set_condition_from_tree (inner_cond, t);
-      update_stmt (inner_cond);
 
-      /* Leave CFG optimization to cfg_cleanup.  */
-      gimple_cond_set_condition_from_tree (outer_cond,
-       outer_inv ? boolean_false_node : boolean_true_node);
-      update_stmt (outer_cond);
+      t = fold_build2 (EQ_EXPR, boolean_type_node, t2, t);
 
-      update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
+      if (!ifcombine_replace_cond (inner_cond, inner_inv,
+                                  outer_cond, outer_inv,
+                                  t, true, NULL_TREE))
+       return false;
 
       if (dump_file)
        {
@@ -493,17 +540,10 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
      In that case remove the outer test and change the inner one to
      test for name & (bits1 | bits2) != 0.  */
   else if (recognize_bits_test (inner_cond, &name1, &bits1, !inner_inv)
-      && recognize_bits_test (outer_cond, &name2, &bits2, !outer_inv))
+          && recognize_bits_test (outer_cond, &name2, &bits2, !outer_inv))
     {
-      gimple_stmt_iterator gsi;
       tree t;
 
-      if ((TREE_CODE (name1) == SSA_NAME
-          && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
-         || (TREE_CODE (name2) == SSA_NAME
-             && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)))
-       return false;
-
       /* Find the common name which is bit-tested.  */
       if (name1 == name2)
        ;
@@ -519,6 +559,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
       else
        return false;
 
+      if ((TREE_CODE (name1) == SSA_NAME
+          && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
+         || (TREE_CODE (name2) == SSA_NAME
+             && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)))
+       return false;
+
       /* As we strip non-widening conversions in finding a common
          name that is tested make sure to end up with an integral
         type for building the bit operations.  */
@@ -538,33 +584,14 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
          bits1 = fold_convert (TREE_TYPE (bits2), bits1);
        }
 
-      /* Do it.  */
-      gsi = gsi_for_stmt (inner_cond);
       t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), bits1, bits2);
-      t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
-                                   true, GSI_SAME_STMT);
       t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
-      t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
-                                   true, GSI_SAME_STMT);
-      t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR, boolean_type_node, t,
+      t = fold_build2 (EQ_EXPR, boolean_type_node, t,
                       build_int_cst (TREE_TYPE (t), 0));
-      t = canonicalize_cond_expr_cond (t);
-      if (!t)
+      if (!ifcombine_replace_cond (inner_cond, inner_inv,
+                                  outer_cond, outer_inv,
+                                  t, false, NULL_TREE))
        return false;
-      if (!is_gimple_condexpr_for_cond (t))
-       {
-         gsi = gsi_for_stmt (inner_cond);
-         t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
-                                         NULL, true, GSI_SAME_STMT);
-       }
-      gimple_cond_set_condition_from_tree (inner_cond, t);
-      update_stmt (inner_cond);
-
-      /* Leave CFG optimization to cfg_cleanup.  */
-      gimple_cond_set_condition_from_tree (outer_cond,
-       outer_inv ? boolean_false_node : boolean_true_node);
-      update_stmt (outer_cond);
-      update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
 
       if (dump_file)
        {
@@ -584,7 +611,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
   else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
           && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
     {
-      tree t, ts = NULL_TREE;
+      tree t, ts = NULL_TREE, ts2 = NULL_TREE;
       enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
       enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
 
@@ -617,7 +644,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
                          inner_cond_code,
                          gimple_cond_lhs (inner_cond),
                          gimple_cond_rhs (inner_cond),
-                         NULL))))
+                         &ts2))))
        {
          {
          tree t1, t2;
@@ -643,38 +670,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
          t = fold_build2_loc (gimple_location (inner_cond), 
                               TRUTH_AND_EXPR, boolean_type_node, t1, t2);
          }
-       gimplify_after_fold:
-         if (result_inv)
-           {
-             t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
-             result_inv = false;
-           }
-         gsi = gsi_for_stmt (inner_cond);
-         t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
-                                         NULL, true, GSI_SAME_STMT);
         }
-      /* ??? Fold should avoid this.  */
-      else if (ts && !is_gimple_condexpr_for_cond (t))
-       goto gimplify_after_fold;
-      if (result_inv)
-       t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
-      t = canonicalize_cond_expr_cond (t);
-      if (!t)
-       return false;
-      if (!is_gimple_condexpr_for_cond (t))
-       {
-         gsi = gsi_for_stmt (inner_cond);
-         t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
-                                         NULL, true, GSI_SAME_STMT);
-       }
-      gimple_cond_set_condition_from_tree (inner_cond, t);
-      update_stmt (inner_cond);
 
-      /* Leave CFG optimization to cfg_cleanup.  */
-      gimple_cond_set_condition_from_tree (outer_cond,
-       outer_inv ? boolean_false_node : boolean_true_node);
-      update_stmt (outer_cond);
-      update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
+      if (!(t = ifcombine_replace_cond (inner_cond, inner_inv,
+                                       outer_cond, outer_inv,
+                                       t, false, ts2)))
+       return false;
 
       if (dump_file)
        {
@@ -716,8 +717,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, 
basic_block outer_cond_bb,
           <else_bb>
             ...
        */
-      return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, false,
-                               false);
+      return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, false);
     }
 
   /* And a version where the outer condition is negated.  */
@@ -734,8 +734,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, 
basic_block outer_cond_bb,
           <else_bb>
             ...
        */
-      return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, true,
-                               false);
+      return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, true);
     }
 
   /* The || form is characterized by a common then_bb with the
@@ -754,8 +753,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, 
basic_block outer_cond_bb,
           <then_bb>
             ...
        */
-      return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, true,
-                               true);
+      return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, true);
     }
 
   /* And a version where the outer condition is negated.  */
@@ -771,8 +769,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, 
basic_block outer_cond_bb,
           <then_bb>
             ...
        */
-      return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, false,
-                               true);
+      return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, false);
     }
 
   return false;

Reply via email to