aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfgcleanup.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfgcleanup.cc')
-rw-r--r--gcc/tree-cfgcleanup.cc39
1 files changed, 39 insertions, 0 deletions
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index 9a8a668..a34a51e 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "tree-into-ssa.h"
#include "tree-cfgcleanup.h"
+#include "gimple-pretty-print.h"
/* The set of blocks in that at least one of the following changes happened:
@@ -122,6 +123,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. */
@@ -145,6 +181,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))
{