Move vrp_simplify_cond_using_ranges into the simplifier.
This static VRP routine does a simplification with casted conditions. Add it to the general simplfier, and continue to invoke if from the VRP folder. * tree-vrp.c (vrp_simplify_cond_using_ranges): Add return type and move to vr-values.c. (simplify_casted_conds): Move to vrp_folder class. (execute_vrp): Call via vrp_folder now. * vr-values.c (simplify_cond_using_ranges_1): Call simplify_casted_cond. (simplify_using_ranges::simplify_casted_cond): Relocate from tree-vrp.c. * vr-values.h (simplify_casted_cond): Add prototype.
This commit is contained in:
parent
cb15322240
commit
f5bacd9c5b
|
@ -4031,6 +4031,7 @@ class vrp_folder : public substitute_and_fold_engine
|
||||||
: substitute_and_fold_engine (/* Fold all stmts. */ true),
|
: substitute_and_fold_engine (/* Fold all stmts. */ true),
|
||||||
m_vr_values (v), simplifier (v)
|
m_vr_values (v), simplifier (v)
|
||||||
{ }
|
{ }
|
||||||
|
void simplify_casted_conds (function *fun);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tree value_of_expr (tree name, gimple *stmt) OVERRIDE
|
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);
|
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
|
/* 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
|
was set by a type conversion can often be rewritten to use the RHS
|
||||||
of the type conversion. Do this optimization for all conditionals
|
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
|
So that transformation is not performed until after jump threading
|
||||||
is complete. */
|
is complete. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
simplify_casted_conds (function *fun, range_query *query)
|
vrp_folder::simplify_casted_conds (function *fun)
|
||||||
{
|
{
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
FOR_EACH_BB_FN (bb, fun)
|
FOR_EACH_BB_FN (bb, fun)
|
||||||
{
|
{
|
||||||
gimple *last = last_stmt (bb);
|
gimple *last = last_stmt (bb);
|
||||||
if (last && gimple_code (last) == GIMPLE_COND)
|
if (last && gimple_code (last) == GIMPLE_COND)
|
||||||
vrp_simplify_cond_using_ranges (query, as_a <gcond *> (last));
|
{
|
||||||
|
if (simplifier.simplify_casted_cond (as_a <gcond *> (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 ();
|
array_checker.check ();
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify_casted_conds (fun, &vrp_vr_values);
|
folder.simplify_casted_conds (fun);
|
||||||
|
|
||||||
free_numbers_of_iterations_estimates (fun);
|
free_numbers_of_iterations_estimates (fun);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
tree vrp_evaluate_conditional_warnv_with_ops (gimple *stmt, enum tree_code,
|
tree vrp_evaluate_conditional_warnv_with_ops (gimple *stmt, enum tree_code,
|
||||||
tree, tree, bool,
|
tree, tree, bool,
|
||||||
bool *, bool *);
|
bool *, bool *);
|
||||||
|
bool simplify_casted_cond (gcond *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
|
bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
|
||||||
|
|
Loading…
Reference in New Issue