@@ -3501,3 +3501,43 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ CONSTRUCTOR_ELT (ctor, idx / k)->value; })
(BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / k)->value; }
@1 { bitsize_int ((idx % k) * width); })))))))))
+
+/* 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. */
+
+(match ssa_name_p SSA_NAME)
+(for cmp (eq ne gt ge lt le)
+ (simplify
+ (cmp ssa_name_p@0 INTEGER_CST@1)
+ (with { gimple *def_stmt = SSA_NAME_DEF_STMT (@0); }
+ (if (is_gimple_assign (def_stmt)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+ (with { tree innerop = gimple_assign_rhs1 (def_stmt); }
+ (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 (@0)))
+ (with { value_range *vr = get_value_range (innerop); }
+ (if (vr
+ && range_int_cst_p (vr)
+ && range_fits_type_p (vr,
+ TYPE_PRECISION (TREE_TYPE (@0)),
+ TYPE_SIGN (TREE_TYPE (@0)))
+ && int_fits_type_p (@1, TREE_TYPE (innerop))
+ /* The range must not have overflowed, or if it did overflow we
+ must not be wrapping/trapping overflow and optimizing with
+ strict overflow semantics. */
+ && ((!is_negative_overflow_infinity (vr->min)
+ && !is_positive_overflow_infinity (vr->max))
+ || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (innerop)))
+ /* If the only use of INNEROP is the cast to @0, and @0 is also
+ used in other places, folding would introduce new uses of the
+ otherwise dead INNEROP without eliminating @0, so do not. */
+ && (!has_single_use (innerop) || has_single_use (@0)))
+ (cmp { innerop; } (convert @1))))))))))
@@ -259,7 +259,7 @@ positive_overflow_infinity (tree type)
/* Return whether VAL is a negative overflow infinity. */
-static inline bool
+bool
is_negative_overflow_infinity (const_tree val)
{
return (TREE_OVERFLOW_P (val)
@@ -269,7 +269,7 @@ is_negative_overflow_infinity (const_tree val)
/* Return whether VAL is a positive overflow infinity. */
-static inline bool
+bool
is_positive_overflow_infinity (const_tree val)
{
return (TREE_OVERFLOW_P (val)
@@ -640,7 +640,7 @@ abs_extent_range (value_range *vr, tree min, tree max)
If we have no values ranges recorded (ie, VRP is not running), then
return NULL. Otherwise create an empty range if none existed for VAR. */
-static value_range *
+value_range *
get_value_range (const_tree var)
{
static const value_range vr_const_varying
@@ -877,7 +877,7 @@ range_is_null (value_range *vr)
/* Return true if max and min of VR are INTEGER_CST. It's not necessary
a singleton. */
-static inline bool
+bool
range_int_cst_p (value_range *vr)
{
return (vr->type == VR_RANGE
@@ -9432,7 +9432,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
/* Return whether the value range *VR fits in an integer type specified
by PRECISION and UNSIGNED_P. */
-static bool
+bool
range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
{
tree src_type;
@@ -9486,7 +9486,7 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
the original conditional. */
static bool
-simplify_cond_using_ranges (gcond *stmt)
+simplify_cond_using_ranges (gimple_stmt_iterator *gsi, gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -9590,73 +9590,7 @@ simplify_cond_using_ranges (gcond *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)
- || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
- return false;
-
- innerop = gimple_assign_rhs1 (def_stmt);
-
- 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)))
- {
- value_range *vr = 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))
- /* The range must not have overflowed, or if it did overflow
- we must not be wrapping/trapping overflow and optimizing
- with strict overflow semantics. */
- && ((!is_negative_overflow_infinity (vr->min)
- && !is_positive_overflow_infinity (vr->max))
- || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (innerop))))
- {
- /* If the range overflowed and the user has asked for warnings
- when strict overflow semantics were used to optimize code,
- issue an appropriate warning. */
- if (cond_code != EQ_EXPR && cond_code != NE_EXPR
- && (is_negative_overflow_infinity (vr->min)
- || is_positive_overflow_infinity (vr->max))
- && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_CONDITIONAL))
- {
- location_t location;
-
- if (!gimple_has_location (stmt))
- location = input_location;
- else
- location = gimple_location (stmt);
- warning_at (location, OPT_Wstrict_overflow,
- "assuming signed overflow does not occur when "
- "simplifying conditional");
- }
-
- tree newconst = fold_convert (TREE_TYPE (innerop), op1);
- gimple_cond_set_lhs (stmt, innerop);
- gimple_cond_set_rhs (stmt, newconst);
- return true;
- }
- }
- }
-
- return false;
+ return fold_stmt (gsi, follow_single_use_edges);
}
/* Simplify a switch statement using the value range of the switch
@@ -10250,7 +10184,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
}
}
else if (gimple_code (stmt) == GIMPLE_COND)
- return simplify_cond_using_ranges (as_a <gcond *> (stmt));
+ return simplify_cond_using_ranges (gsi, as_a <gcond *> (stmt));
else if (gimple_code (stmt) == GIMPLE_SWITCH)
return simplify_switch_using_ranges (as_a <gswitch *> (stmt));
else if (is_gimple_call (stmt)
@@ -56,4 +56,9 @@ extern void extract_range_from_unary_expr (value_range *vr,
tree type,
value_range *vr0_,
tree op0_type);
-
+extern value_range *get_value_range (const_tree var);
+extern bool range_fits_type_p (value_range *vr, unsigned dest_precision,
+ signop dest_sgn);
+extern bool is_negative_overflow_infinity (const_tree val);
+extern bool is_positive_overflow_infinity (const_tree val);
+extern bool range_int_cst_p (value_range *vr);