From 9b80d091af4760e4c8869917790bd01465b7a59e Mon Sep 17 00:00:00 2001 From: Kai Tietz Date: Tue, 2 Aug 2011 16:55:47 +0200 Subject: [PATCH] gimple.c (canonicalize_cond_expr_cond): Handle cast from boolean-type. * gimple.c (canonicalize_cond_expr_cond): Handle cast from boolean-type. (ssa_forward_propagate_and_combine): Interprete result of forward_propagate_comparison. * gcc/gimple-fold.c (fold_gimple_assign): Add canonicalization for boolean-typed operands for comparisons. * gcc.dg/tree-ssa/forwprop-15.c: New testcase. From-SVN: r177170 --- gcc/ChangeLog | 9 +++++ gcc/gimple-fold.c | 41 +++++++++++++++++++++ gcc/gimple.c | 4 +- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-15.c | 14 +++++++ gcc/tree-ssa-forwprop.c | 5 ++- 6 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/forwprop-15.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f525c95441a..7493d2313b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-08-02 Kai Tietz + + * gimple.c (canonicalize_cond_expr_cond): Handle cast from + boolean-type. + (ssa_forward_propagate_and_combine): Interprete result of + forward_propagate_comparison. + * gcc/gimple-fold.c (fold_gimple_assign): Add canonicalization for + boolean-typed operands for comparisons. + 2011-08-02 Georg-Johann Lay * config/avr/libgcc.S: Gather related function in the diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index cc89b2fd4fb..cd988b9c1db 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -814,6 +814,47 @@ fold_gimple_assign (gimple_stmt_iterator *si) gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt)); } + /* Try to canonicalize for boolean-typed X the comparisons + X == 0, X == 1, X != 0, and X != 1. */ + else if (gimple_assign_rhs_code (stmt) == EQ_EXPR + || gimple_assign_rhs_code (stmt) == NE_EXPR) + { + tree lhs = gimple_assign_lhs (stmt); + tree op1 = gimple_assign_rhs1 (stmt); + tree op2 = gimple_assign_rhs2 (stmt); + tree type = TREE_TYPE (op1); + + /* Check whether the comparison operands are of the same boolean + type as the result type is. + Check that second operand is an integer-constant with value + one or zero. */ + if (TREE_CODE (op2) == INTEGER_CST + && (integer_zerop (op2) || integer_onep (op2)) + && useless_type_conversion_p (TREE_TYPE (lhs), type)) + { + enum tree_code cmp_code = gimple_assign_rhs_code (stmt); + bool is_logical_not = false; + + /* X == 0 and X != 1 is a logical-not.of X + X == 1 and X != 0 is X */ + if ((cmp_code == EQ_EXPR && integer_zerop (op2)) + || (cmp_code == NE_EXPR && integer_onep (op2))) + is_logical_not = true; + + if (is_logical_not == false) + result = op1; + /* Only for one-bit precision typed X the transformation + !X -> ~X is valied. */ + else if (TYPE_PRECISION (type) == 1) + result = build1_loc (gimple_location (stmt), BIT_NOT_EXPR, + type, op1); + /* Otherwise we use !X -> X ^ 1. */ + else + result = build2_loc (gimple_location (stmt), BIT_XOR_EXPR, + type, op1, build_int_cst (type, 1)); + + } + } if (!result) result = fold_binary_loc (loc, subcode, diff --git a/gcc/gimple.c b/gcc/gimple.c index e3095d7e261..af23c6a3fc9 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3160,7 +3160,9 @@ canonicalize_cond_expr_cond (tree t) { /* Strip conversions around boolean operations. */ if (CONVERT_EXPR_P (t) - && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))) + && (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0))) + || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) + == BOOLEAN_TYPE)) t = TREE_OPERAND (t, 0); /* For !x use x == 0. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4ff8a1010d4..103bf569b86 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-08-02 Kai Tietz + + * gcc.dg/tree-ssa/forwprop-15.c: New testcase. + 2011-08-01 Jason Merrill PR c++/49932 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-15.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-15.c new file mode 100644 index 00000000000..43c63516774 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-15.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +_Bool +foo (_Bool a, _Bool b, _Bool c +{ + _Bool r1 = a == 0 & b != 0; + _Bool r2 = b != 0 & c == 0; + return (r1 == 0 & r2 == 0); +} + +/* { dg-final { scan-tree-dump-times " == " 0 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times " != " 0 "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 7cf420ff496..2a56b79a423 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -468,7 +468,9 @@ forward_propagate_into_comparison (gimple_stmt_iterator *gsi) if (tmp) { gimple_assign_set_rhs_from_tree (gsi, tmp); + fold_stmt_inplace (stmt); update_stmt (stmt); + if (TREE_CODE (rhs1) == SSA_NAME) cfg_changed |= remove_prop_source_from_use (rhs1); if (TREE_CODE (rhs2) == SSA_NAME) @@ -2407,7 +2409,8 @@ ssa_forward_propagate_and_combine (void) } else if (TREE_CODE_CLASS (code) == tcc_comparison) { - forward_propagate_comparison (stmt); + if (forward_propagate_comparison (stmt)) + cfg_changed = true; gsi_next (&gsi); } else -- 2.30.2