From: Richard Guenther Date: Thu, 4 Aug 2011 14:11:30 +0000 (+0000) Subject: re PR middle-end/49806 (FAIL: gcc.dg/tree-ssa/vrp47.c) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7e29ba60f137272db19c41c09cc04921027a56b8;p=gcc.git re PR middle-end/49806 (FAIL: gcc.dg/tree-ssa/vrp47.c) 2011-08-04 Richard Guenther PR tree-optimization/49806 * tree-vrp.c (op_with_boolean_value_range_p): New function. (simplify_truth_ops_using_ranges): Simplify. Allow inserting a new statement for a final conversion to bool. From-SVN: r177392 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6e0dd68a017..773df850ca1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-08-04 Richard Guenther + + PR tree-optimization/49806 + * tree-vrp.c (op_with_boolean_value_range_p): New function. + (simplify_truth_ops_using_ranges): Simplify. Allow inserting + a new statement for a final conversion to bool. + 2011-08-04 Romain Geissler * gengtype-state.c: Include "bconfig.h" if diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 15331e1fcc6..5aa942be611 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1454,6 +1454,28 @@ op_with_constant_singleton_value_range (tree op) return NULL_TREE; } +/* Return true if op is in a boolean [0, 1] value-range. */ + +static bool +op_with_boolean_value_range_p (tree op) +{ + value_range_t *vr; + + if (TYPE_PRECISION (TREE_TYPE (op)) == 1) + return true; + + if (integer_zerop (op) + || integer_onep (op)) + return true; + + if (TREE_CODE (op) != SSA_NAME) + return false; + + vr = get_value_range (op); + return (vr->type == VR_RANGE + && integer_zerop (vr->min) + && integer_onep (vr->max)); +} /* Extract value range information from an ASSERT_EXPR EXPR and store it in *VR_P. */ @@ -6753,115 +6775,64 @@ static bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); - tree val = NULL; - tree op0, op1; - value_range_t *vr; - bool sop = false; + tree lhs, op0, op1; bool need_conversion; /* We handle only !=/== case here. */ gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR); op0 = gimple_assign_rhs1 (stmt); - if (TYPE_PRECISION (TREE_TYPE (op0)) != 1) - { - if (TREE_CODE (op0) != SSA_NAME) - return false; - vr = get_value_range (op0); - - val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop); - if (!val || !integer_onep (val)) - return false; - - val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop); - if (!val || !integer_onep (val)) - return false; - } + if (!op_with_boolean_value_range_p (op0)) + return false; op1 = gimple_assign_rhs2 (stmt); + if (!op_with_boolean_value_range_p (op1)) + return false; - /* Reduce number of cases to handle. */ - if (is_gimple_min_invariant (op1)) - { - if (!integer_zerop (op1) - && !integer_onep (op1) - && !integer_all_onesp (op1)) - return false; - - /* Limit the number of cases we have to consider. */ - if (rhs_code == EQ_EXPR) - { - rhs_code = NE_EXPR; - /* OP1 is a constant. */ - op1 = fold_unary (TRUTH_NOT_EXPR, TREE_TYPE (op1), op1); - } - } - else - { - /* Punt on A == B as there is no BIT_XNOR_EXPR. */ - if (rhs_code == EQ_EXPR) - return false; - - if (TYPE_PRECISION (TREE_TYPE (op1)) != 1) - { - vr = get_value_range (op1); - val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop); - if (!val || !integer_onep (val)) - return false; - - val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop); - if (!val || !integer_onep (val)) - return false; - } - } - - if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC)) + /* Reduce number of cases to handle to NE_EXPR. As there is no + BIT_XNOR_EXPR we cannot replace A == B with a single statement. */ + if (rhs_code == EQ_EXPR) { - location_t location; - - if (!gimple_has_location (stmt)) - location = input_location; + if (TREE_CODE (op1) == INTEGER_CST) + op1 = int_const_binop (BIT_XOR_EXPR, op1, integer_one_node); else - location = gimple_location (stmt); - - warning_at (location, OPT_Wstrict_overflow, - _("assuming signed overflow does not occur when " - "simplifying ==, != or ! to identity or ^")); + return false; } - need_conversion = - !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)), - TREE_TYPE (op0)); + lhs = gimple_assign_lhs (stmt); + need_conversion + = !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (op0)); - /* Make sure to not sign-extend -1 as a boolean value. */ + /* Make sure to not sign-extend a 1-bit 1 when converting the result. */ if (need_conversion && !TYPE_UNSIGNED (TREE_TYPE (op0)) - && TYPE_PRECISION (TREE_TYPE (op0)) == 1) + && TYPE_PRECISION (TREE_TYPE (op0)) == 1 + && TYPE_PRECISION (TREE_TYPE (lhs)) > 1) return false; - switch (rhs_code) - { - case NE_EXPR: - if (integer_zerop (op1)) - { - gimple_assign_set_rhs_with_ops (gsi, - need_conversion ? NOP_EXPR : SSA_NAME, - op0, NULL); - update_stmt (gsi_stmt (*gsi)); - return true; - } - - rhs_code = BIT_XOR_EXPR; - break; - default: - gcc_unreachable (); - } - - if (need_conversion) - return false; - - gimple_assign_set_rhs_with_ops (gsi, rhs_code, op0, op1); + /* For A != 0 we can substitute A itself. */ + if (integer_zerop (op1)) + gimple_assign_set_rhs_with_ops (gsi, + need_conversion + ? NOP_EXPR : TREE_CODE (op0), + op0, NULL_TREE); + /* For A != B we substitute A ^ B. Either with conversion. */ + else if (need_conversion) + { + gimple newop; + tree tem = create_tmp_reg (TREE_TYPE (op0), NULL); + newop = gimple_build_assign_with_ops (BIT_XOR_EXPR, tem, op0, op1); + tem = make_ssa_name (tem, newop); + gimple_assign_set_lhs (newop, tem); + gsi_insert_before (gsi, newop, GSI_SAME_STMT); + update_stmt (newop); + gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE); + } + /* Or without. */ + else + gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op0, op1); update_stmt (gsi_stmt (*gsi)); + return true; }