[#3/7] introduce ifcombine_replace_cond (was: Re: [PATCH] fold fold_truth_andor field merging into ifcombine)
Commit Message
Refactor ifcombine_ifandif, moving the common code from the various
paths that apply the combined condition to a new function.
for gcc/ChangeLog
* tree-ssa-ifcombine.cc (ifcombine_replace_cond): Factor out
of...
(ifcombine_ifandif): ... this.
---
gcc/tree-ssa-ifcombine.cc | 137 +++++++++++++++++++++------------------------
1 file changed, 65 insertions(+), 72 deletions(-)
Comments
On 10/25/24 5:52 AM, Alexandre Oliva wrote:
>
> Refactor ifcombine_ifandif, moving the common code from the various
> paths that apply the combined condition to a new function.
>
>
> for gcc/ChangeLog
>
> * tree-ssa-ifcombine.cc (ifcombine_replace_cond): Factor out
> of...
> (ifcombine_ifandif): ... this.
It looks like you also did some simplifications in ifcombine_ifandif.
Those should be noted in the ChangeLog. Specifically you no longer make
the calls to force_gimple_operand_gsi and simplified the equality test.
OK with that change.
jeff
On Fri, Oct 25, 2024 at 4:39 PM Alexandre Oliva <oliva@adacore.com> wrote:
>
>
> Refactor ifcombine_ifandif, moving the common code from the various
> paths that apply the combined condition to a new function.
>
>
> for gcc/ChangeLog
>
> * tree-ssa-ifcombine.cc (ifcombine_replace_cond): Factor out
> of...
> (ifcombine_ifandif): ... this.
> ---
> gcc/tree-ssa-ifcombine.cc | 137 +++++++++++++++++++++------------------------
> 1 file changed, 65 insertions(+), 72 deletions(-)
>
> diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
> index 0a2ba970548c8..6dcf5e6efe1de 100644
> --- a/gcc/tree-ssa-ifcombine.cc
> +++ b/gcc/tree-ssa-ifcombine.cc
> @@ -399,6 +399,51 @@ update_profile_after_ifcombine (basic_block inner_cond_bb,
> outer2->probability = profile_probability::never ();
> }
>
> +/* Replace the conditions in INNER_COND with COND.
> + Replace OUTER_COND with a constant. */
> +
> +static bool
> +ifcombine_replace_cond (gcond *inner_cond, bool inner_inv,
> + gcond *outer_cond, bool outer_inv,
> + tree cond, bool must_canon, tree cond2)
> +{
> + bool result_inv = inner_inv;
> +
> + gcc_checking_assert (!cond2);
> +
> + if (result_inv)
> + cond = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
> +
> + if (tree tcanon = canonicalize_cond_expr_cond (cond))
> + cond = tcanon;
> + else if (must_canon)
> + return false;
> +
> + {
no need for this brace pair?
OK with it dropped.
Richard.
> + if (!is_gimple_condexpr_for_cond (cond))
> + {
> + gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond);
> + cond = force_gimple_operand_gsi_1 (&gsi, cond,
> + is_gimple_condexpr_for_cond,
> + NULL, true, GSI_SAME_STMT);
> + }
> + gimple_cond_set_condition_from_tree (inner_cond, cond);
> + 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 true;
> +}
> +
> /* 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 indicate whether the conditions are inverted.
> @@ -408,7 +453,6 @@ static bool
> ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> basic_block outer_cond_bb, bool outer_inv)
> {
> - bool result_inv = inner_inv;
> gimple_stmt_iterator gsi;
> tree name1, name2, bit1, bit2, bits1, bits2;
>
> @@ -446,26 +490,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)
> {
> @@ -485,9 +516,8 @@ 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
> @@ -530,33 +560,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)
> {
> @@ -576,7 +587,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;
> + tree t, ts = NULL_TREE;
> enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
> enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
>
> @@ -602,7 +613,6 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> gimple_bb (outer_cond))))
> {
> tree t1, t2;
> - gimple_stmt_iterator gsi;
> bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
> if (param_logical_op_non_short_circuit != -1)
> logical_op_non_short_circuit
> @@ -624,39 +634,22 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> gimple_cond_rhs (outer_cond));
> t = fold_build2_loc (gimple_location (inner_cond),
> TRUTH_AND_EXPR, boolean_type_node, t1, t2);
> - 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);
> }
> - 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 (!ifcombine_replace_cond (inner_cond, inner_inv,
> + outer_cond, outer_inv,
> + t, false, ts))
> + return false;
>
> if (dump_file)
> {
> fprintf (dump_file, "optimizing two comparisons to ");
> print_generic_expr (dump_file, t);
> + if (ts)
> + {
> + fprintf (dump_file, " and ");
> + print_generic_expr (dump_file, ts);
> + }
> fprintf (dump_file, "\n");
> }
>
>
> --
> Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
> Free Software Activist GNU Toolchain Engineer
> More tolerance and less prejudice are key for inclusion and diversity
> Excluding neuro-others for not behaving ""normal"" is *not* inclusive
On Oct 27, 2024, Jeff Law <jeffreyalaw@gmail.com> wrote:
> On 10/25/24 5:52 AM, Alexandre Oliva wrote:
>> Refactor ifcombine_ifandif, moving the common code from the various
>> paths that apply the combined condition to a new function.
>>
>> for gcc/ChangeLog
>> * tree-ssa-ifcombine.cc (ifcombine_replace_cond): Factor out
>> of...
>> (ifcombine_ifandif): ... this.
> It looks like you also did some simplifications in
> ifcombine_ifandif. Those should be noted in the ChangeLog.
Indeed, thanks!
> Specifically you no longer make the calls to force_gimple_operand_gsi
True, they're now implied by the other force_gimple_operand_gsi_1 call.
> and simplified the equality test.
I'm not sure what you mean here. Is it about leaving the inversion for
the refactored function to perform?
If so, this addition should do:
(ifcombine_ifandif): ... this. Leave it for the above to
gimplify and invert the condition.
On Oct 30, 2024, Richard Biener <richard.guenther@gmail.com> wrote:
> no need for this brace pair?
No need indeed, but this bit becomes the else branch of an if introduced
in #5. I figured the #5 patch would be cleaner if I kept this bit
braced and indented.
Alexandre Oliva <oliva@adacore.com> writes:
> Refactor ifcombine_ifandif, moving the common code from the various
> paths that apply the combined condition to a new function.
BTW, forgive the possibly silly question, but I don't see any testcases
for the series. Would it be possible to add any?
>
>
> for gcc/ChangeLog
>
> * tree-ssa-ifcombine.cc (ifcombine_replace_cond): Factor out
> of...
> (ifcombine_ifandif): ... this.
> ---
> gcc/tree-ssa-ifcombine.cc | 137 +++++++++++++++++++++------------------------
> 1 file changed, 65 insertions(+), 72 deletions(-)
>
> diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
> index 0a2ba970548c8..6dcf5e6efe1de 100644
> --- a/gcc/tree-ssa-ifcombine.cc
> +++ b/gcc/tree-ssa-ifcombine.cc
> @@ -399,6 +399,51 @@ update_profile_after_ifcombine (basic_block inner_cond_bb,
> outer2->probability = profile_probability::never ();
> }
>
> +/* Replace the conditions in INNER_COND with COND.
> + Replace OUTER_COND with a constant. */
> +
> +static bool
> +ifcombine_replace_cond (gcond *inner_cond, bool inner_inv,
> + gcond *outer_cond, bool outer_inv,
> + tree cond, bool must_canon, tree cond2)
> +{
> + bool result_inv = inner_inv;
> +
> + gcc_checking_assert (!cond2);
> +
> + if (result_inv)
> + cond = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
> +
> + if (tree tcanon = canonicalize_cond_expr_cond (cond))
> + cond = tcanon;
> + else if (must_canon)
> + return false;
> +
> + {
> + if (!is_gimple_condexpr_for_cond (cond))
> + {
> + gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond);
> + cond = force_gimple_operand_gsi_1 (&gsi, cond,
> + is_gimple_condexpr_for_cond,
> + NULL, true, GSI_SAME_STMT);
> + }
> + gimple_cond_set_condition_from_tree (inner_cond, cond);
> + 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 true;
> +}
> +
> /* 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 indicate whether the conditions are inverted.
> @@ -408,7 +453,6 @@ static bool
> ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> basic_block outer_cond_bb, bool outer_inv)
> {
> - bool result_inv = inner_inv;
> gimple_stmt_iterator gsi;
> tree name1, name2, bit1, bit2, bits1, bits2;
>
> @@ -446,26 +490,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)
> {
> @@ -485,9 +516,8 @@ 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
> @@ -530,33 +560,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)
> {
> @@ -576,7 +587,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;
> + tree t, ts = NULL_TREE;
> enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
> enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
>
> @@ -602,7 +613,6 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> gimple_bb (outer_cond))))
> {
> tree t1, t2;
> - gimple_stmt_iterator gsi;
> bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
> if (param_logical_op_non_short_circuit != -1)
> logical_op_non_short_circuit
> @@ -624,39 +634,22 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
> gimple_cond_rhs (outer_cond));
> t = fold_build2_loc (gimple_location (inner_cond),
> TRUTH_AND_EXPR, boolean_type_node, t1, t2);
> - 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);
> }
> - 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 (!ifcombine_replace_cond (inner_cond, inner_inv,
> + outer_cond, outer_inv,
> + t, false, ts))
> + return false;
>
> if (dump_file)
> {
> fprintf (dump_file, "optimizing two comparisons to ");
> print_generic_expr (dump_file, t);
> + if (ts)
> + {
> + fprintf (dump_file, " and ");
> + print_generic_expr (dump_file, ts);
> + }
> fprintf (dump_file, "\n");
> }
On Nov 2, 2024, Sam James <sam@gentoo.org> wrote:
> BTW, forgive the possibly silly question, but I don't see any testcases
> for the series.
They're in the original patch, upthread, that this series was split out
of at reviewers' request. The tests all depended on a feature that was
not to be included in this first patchset, but they were there, and I'm
still testing with the feature and the tests on top of the series.
> Would it be possible to add any?
It would, but they'd very soon (hopefully) be redundant, and
bootstrapping is a pretty thorough test already.
@@ -399,6 +399,51 @@ update_profile_after_ifcombine (basic_block inner_cond_bb,
outer2->probability = profile_probability::never ();
}
+/* Replace the conditions in INNER_COND with COND.
+ Replace OUTER_COND with a constant. */
+
+static bool
+ifcombine_replace_cond (gcond *inner_cond, bool inner_inv,
+ gcond *outer_cond, bool outer_inv,
+ tree cond, bool must_canon, tree cond2)
+{
+ bool result_inv = inner_inv;
+
+ gcc_checking_assert (!cond2);
+
+ if (result_inv)
+ cond = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
+
+ if (tree tcanon = canonicalize_cond_expr_cond (cond))
+ cond = tcanon;
+ else if (must_canon)
+ return false;
+
+ {
+ if (!is_gimple_condexpr_for_cond (cond))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond);
+ cond = force_gimple_operand_gsi_1 (&gsi, cond,
+ is_gimple_condexpr_for_cond,
+ NULL, true, GSI_SAME_STMT);
+ }
+ gimple_cond_set_condition_from_tree (inner_cond, cond);
+ 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 true;
+}
+
/* 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 indicate whether the conditions are inverted.
@@ -408,7 +453,6 @@ static bool
ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
basic_block outer_cond_bb, bool outer_inv)
{
- bool result_inv = inner_inv;
gimple_stmt_iterator gsi;
tree name1, name2, bit1, bit2, bits1, bits2;
@@ -446,26 +490,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)
{
@@ -485,9 +516,8 @@ 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
@@ -530,33 +560,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)
{
@@ -576,7 +587,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;
+ tree t, ts = NULL_TREE;
enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
@@ -602,7 +613,6 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
gimple_bb (outer_cond))))
{
tree t1, t2;
- gimple_stmt_iterator gsi;
bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
if (param_logical_op_non_short_circuit != -1)
logical_op_non_short_circuit
@@ -624,39 +634,22 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
gimple_cond_rhs (outer_cond));
t = fold_build2_loc (gimple_location (inner_cond),
TRUTH_AND_EXPR, boolean_type_node, t1, t2);
- 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);
}
- 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 (!ifcombine_replace_cond (inner_cond, inner_inv,
+ outer_cond, outer_inv,
+ t, false, ts))
+ return false;
if (dump_file)
{
fprintf (dump_file, "optimizing two comparisons to ");
print_generic_expr (dump_file, t);
+ if (ts)
+ {
+ fprintf (dump_file, " and ");
+ print_generic_expr (dump_file, ts);
+ }
fprintf (dump_file, "\n");
}