diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a948c524098..38ea50303e0 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4031,6 +4031,7 @@ class vrp_folder : public substitute_and_fold_engine : substitute_and_fold_engine (/* Fold all stmts. */ true), m_vr_values (v), simplifier (v) { } + void simplify_casted_conds (function *fun); private: tree value_of_expr (tree name, gimple *stmt) OVERRIDE @@ -4117,78 +4118,6 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si) return simplifier.simplify (si); } -/* STMT is a conditional at the end of a basic block. - - If the conditional is of the form SSA_NAME op constant and the SSA_NAME - was set via a type conversion, try to replace the SSA_NAME with the RHS - of the type conversion. Doing so makes the conversion dead which helps - subsequent passes. */ - -static void -vrp_simplify_cond_using_ranges (range_query *query, gcond *stmt) -{ - tree op0 = gimple_cond_lhs (stmt); - tree op1 = gimple_cond_rhs (stmt); - - /* If we have a comparison of an SSA_NAME (OP0) against a constant, - see if OP0 was set by a type conversion where the source of - the conversion is another SSA_NAME with a range that fits - into the range of OP0's type. - - If so, the conversion is redundant as the earlier SSA_NAME can be - used for the comparison directly if we just massage the constant in the - comparison. */ - if (TREE_CODE (op0) == SSA_NAME - && TREE_CODE (op1) == INTEGER_CST) - { - gimple *def_stmt = SSA_NAME_DEF_STMT (op0); - tree innerop; - - if (!is_gimple_assign (def_stmt)) - return; - - switch (gimple_assign_rhs_code (def_stmt)) - { - CASE_CONVERT: - innerop = gimple_assign_rhs1 (def_stmt); - break; - case VIEW_CONVERT_EXPR: - innerop = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); - if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop))) - return; - break; - default: - return; - } - - if (TREE_CODE (innerop) == SSA_NAME - && !POINTER_TYPE_P (TREE_TYPE (innerop)) - && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop) - && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0))) - { - const value_range *vr = query->get_value_range (innerop); - - if (range_int_cst_p (vr) - && range_fits_type_p (vr, - TYPE_PRECISION (TREE_TYPE (op0)), - TYPE_SIGN (TREE_TYPE (op0))) - && int_fits_type_p (op1, TREE_TYPE (innerop))) - { - tree newconst = fold_convert (TREE_TYPE (innerop), op1); - gimple_cond_set_lhs (stmt, innerop); - gimple_cond_set_rhs (stmt, newconst); - update_stmt (stmt); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Folded into: "); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - fprintf (dump_file, "\n"); - } - } - } - } -} - /* A comparison of an SSA_NAME against a constant where the SSA_NAME was set by a type conversion can often be rewritten to use the RHS of the type conversion. Do this optimization for all conditionals @@ -4198,15 +4127,25 @@ vrp_simplify_cond_using_ranges (range_query *query, gcond *stmt) So that transformation is not performed until after jump threading is complete. */ -static void -simplify_casted_conds (function *fun, range_query *query) +void +vrp_folder::simplify_casted_conds (function *fun) { basic_block bb; FOR_EACH_BB_FN (bb, fun) { gimple *last = last_stmt (bb); if (last && gimple_code (last) == GIMPLE_COND) - vrp_simplify_cond_using_ranges (query, as_a (last)); + { + if (simplifier.simplify_casted_cond (as_a (last))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Folded into: "); + print_gimple_stmt (dump_file, last, 0, TDF_SLIM); + fprintf (dump_file, "\n"); + } + } + } } } @@ -4301,7 +4240,7 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) array_checker.check (); } - simplify_casted_conds (fun, &vrp_vr_values); + folder.simplify_casted_conds (fun); free_numbers_of_iterations_estimates (fun); diff --git a/gcc/vr-values.c b/gcc/vr-values.c index d0f7cb41bc8..00246c9d3af 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -3630,6 +3630,75 @@ simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt) } } } + // Try to simplify casted conditions. + return simplify_casted_cond (stmt); +} + +/* STMT is a conditional at the end of a basic block. + + If the conditional is of the form SSA_NAME op constant and the SSA_NAME + was set via a type conversion, try to replace the SSA_NAME with the RHS + of the type conversion. Doing so makes the conversion dead which helps + subsequent passes. */ + +bool +simplify_using_ranges::simplify_casted_cond (gcond *stmt) +{ + tree op0 = gimple_cond_lhs (stmt); + tree op1 = gimple_cond_rhs (stmt); + + /* If we have a comparison of an SSA_NAME (OP0) against a constant, + see if OP0 was set by a type conversion where the source of + the conversion is another SSA_NAME with a range that fits + into the range of OP0's type. + + If so, the conversion is redundant as the earlier SSA_NAME can be + used for the comparison directly if we just massage the constant in the + comparison. */ + if (TREE_CODE (op0) == SSA_NAME + && TREE_CODE (op1) == INTEGER_CST) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (op0); + tree innerop; + + if (!is_gimple_assign (def_stmt)) + return false; + + switch (gimple_assign_rhs_code (def_stmt)) + { + CASE_CONVERT: + innerop = gimple_assign_rhs1 (def_stmt); + break; + case VIEW_CONVERT_EXPR: + innerop = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); + if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop))) + return false; + break; + default: + return false; + } + + if (TREE_CODE (innerop) == SSA_NAME + && !POINTER_TYPE_P (TREE_TYPE (innerop)) + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop) + && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0))) + { + const value_range *vr = query->get_value_range (innerop); + + if (range_int_cst_p (vr) + && range_fits_type_p (vr, + TYPE_PRECISION (TREE_TYPE (op0)), + TYPE_SIGN (TREE_TYPE (op0))) + && int_fits_type_p (op1, TREE_TYPE (innerop))) + { + tree newconst = fold_convert (TREE_TYPE (innerop), op1); + gimple_cond_set_lhs (stmt, innerop); + gimple_cond_set_rhs (stmt, newconst); + update_stmt (stmt); + return true; + } + } + } return false; } diff --git a/gcc/vr-values.h b/gcc/vr-values.h index 821bcb9d58d..21dc4eaebce 100644 --- a/gcc/vr-values.h +++ b/gcc/vr-values.h @@ -44,6 +44,7 @@ public: tree vrp_evaluate_conditional_warnv_with_ops (gimple *stmt, enum tree_code, tree, tree, bool, bool *, bool *); + bool simplify_casted_cond (gcond *); private: bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);