This moves the canonicalization of `bool==0` and `bool!=1` from
forwprop to cleanupcfg. We will still need to call it from forwprop
so we don't need to call forwprop a few times to fp comparisons in some
cases (forwprop-16.c was added originally for this code even).
This is the first step in removing forward_propagate_into_gimple_cond
and forward_propagate_into_comparison.
Bootstrapped and tested on x86_64-linux-gnu.
gcc/ChangeLog:
* tree-cfgcleanup.cc (canonicalize_bool_cond): New function.
(cleanup_control_expr_graph): Call canonicalize_bool_cond for
GIMPLE_COND.
* tree-cfgcleanup.h (canonicalize_bool_cond): New declaration.
* tree-ssa-forwprop.cc (forward_propagate_into_gimple_cond):
Call canonicalize_bool_cond.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/tree-cfgcleanup.cc | 39 +++++++++++++++++++++++++++++++++++++++
gcc/tree-cfgcleanup.h | 1 +
gcc/tree-ssa-forwprop.cc | 18 ++----------------
3 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index 38a62499f93..66575393a44 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-into-ssa.h"
#include "tree-cfgcleanup.h"
#include "target.h"
+#include "gimple-pretty-print.h"
/* The set of blocks in that at least one of the following changes happened:
@@ -123,6 +124,41 @@ convert_single_case_switch (gswitch *swtch,
gimple_stmt_iterator &gsi)
return true;
}
+/* Canonicalize _Bool == 0 and _Bool != 1 to _Bool != 0 of STMT in BB by
+ swapping edges of the BB. */
+bool
+canonicalize_bool_cond (gcond *stmt, basic_block bb)
+{
+ tree rhs1 = gimple_cond_lhs (stmt);
+ tree rhs2 = gimple_cond_rhs (stmt);
+ enum tree_code code = gimple_cond_code (stmt);
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return false;
+ if (TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+ || TYPE_PRECISION (TREE_TYPE (rhs1)) != 1))
+ return false;
+
+ /* Canonicalize _Bool == 0 and _Bool != 1 to _Bool != 0 by swapping edges.
*/
+ if (code == EQ_EXPR && !integer_zerop (rhs2))
+ return false;
+ if (code == NE_EXPR && !integer_onep (rhs2))
+ return false;
+
+ gimple_cond_set_code (stmt, NE_EXPR);
+ gimple_cond_set_rhs (stmt, build_zero_cst (TREE_TYPE (rhs1)));
+ EDGE_SUCC (bb, 0)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
+ EDGE_SUCC (bb, 1)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, " Swapped '");
+ print_gimple_expr (dump_file, stmt, 0);
+ fprintf (dump_file, "'\n");
+ }
+ return true;
+}
+
/* Disconnect an unreachable block in the control expression starting
at block BB. */
@@ -146,6 +182,9 @@ cleanup_control_expr_graph (basic_block bb,
gimple_stmt_iterator gsi)
&& convert_single_case_switch (as_a<gswitch *> (stmt), gsi))
stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) == GIMPLE_COND)
+ canonicalize_bool_cond (as_a<gcond*> (stmt), bb);
+
fold_defer_overflow_warnings ();
switch (gimple_code (stmt))
{
diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h
index 83c857fe33a..94b430e0c71 100644
--- a/gcc/tree-cfgcleanup.h
+++ b/gcc/tree-cfgcleanup.h
@@ -28,5 +28,6 @@ extern bool delete_unreachable_blocks_update_callgraph
(cgraph_node *dst_node,
bool update_clones);
extern unsigned clean_up_loop_closed_phi (function *);
extern bool phi_alternatives_equal (basic_block, edge, edge);
+extern bool canonicalize_bool_cond (gcond *stmt, basic_block bb);
#endif /* GCC_TREE_CFGCLEANUP_H */
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index bd407ef8a69..d718d8f7faf 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -579,22 +579,8 @@ forward_propagate_into_gimple_cond (gcond *stmt)
return (cfg_changed || is_gimple_min_invariant (tmp)) ? 2 : 1;
}
- /* Canonicalize _Bool == 0 and _Bool != 1 to _Bool != 0 by swapping edges.
*/
- if ((TREE_CODE (TREE_TYPE (rhs1)) == BOOLEAN_TYPE
- || (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
- && TYPE_PRECISION (TREE_TYPE (rhs1)) == 1))
- && ((code == EQ_EXPR
- && integer_zerop (rhs2))
- || (code == NE_EXPR
- && integer_onep (rhs2))))
- {
- basic_block bb = gimple_bb (stmt);
- gimple_cond_set_code (stmt, NE_EXPR);
- gimple_cond_set_rhs (stmt, build_zero_cst (TREE_TYPE (rhs1)));
- EDGE_SUCC (bb, 0)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
- EDGE_SUCC (bb, 1)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
- return 1;
- }
+ if (canonicalize_bool_cond (stmt, gimple_bb (stmt)))
+ return 1;
return 0;
}
--
2.43.0