[gcc(refs/users/aoliva/heads/testme)] refactor ifcombine
Alexandre Oliva
aoliva@gcc.gnu.org
Thu Sep 19 06:32:39 GMT 2024
https://gcc.gnu.org/g:3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78
commit 3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78
Author: Alexandre Oliva <oliva@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;
More information about the Gcc-cvs
mailing list