/* If VAR is a default definition of a parameter, the variable can
take any value in VAR's type. */
sym = SSA_NAME_VAR (var);
- if (SSA_NAME_IS_DEFAULT_DEF (var)
- && TREE_CODE (sym) == PARM_DECL)
- {
- /* Try to use the "nonnull" attribute to create ~[0, 0]
- anti-ranges for pointers. Note that this is only valid with
- default definitions of PARM_DECLs. */
- if (POINTER_TYPE_P (TREE_TYPE (sym))
- && nonnull_arg_p (sym))
+ if (SSA_NAME_IS_DEFAULT_DEF (var))
+ {
+ if (TREE_CODE (sym) == PARM_DECL)
+ {
+ /* Try to use the "nonnull" attribute to create ~[0, 0]
+ anti-ranges for pointers. Note that this is only valid with
+ default definitions of PARM_DECLs. */
+ if (POINTER_TYPE_P (TREE_TYPE (sym))
+ && nonnull_arg_p (sym))
+ set_value_range_to_nonnull (vr, TREE_TYPE (sym));
+ else
+ set_value_range_to_varying (vr);
+ }
+ else if (TREE_CODE (sym) == RESULT_DECL
+ && DECL_BY_REFERENCE (sym))
set_value_range_to_nonnull (vr, TREE_TYPE (sym));
- else
- set_value_range_to_varying (vr);
}
return vr;
behavior from the shift operation. We cannot even trust
SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
shifts, and the operation at the tree level may be widened. */
- if (code == RSHIFT_EXPR)
+ if (vr1.type != VR_RANGE
+ || !value_range_nonnegative_p (&vr1)
+ || TREE_CODE (vr1.max) != INTEGER_CST
+ || compare_tree_int (vr1.max, TYPE_PRECISION (expr_type) - 1) == 1)
{
- if (vr1.type != VR_RANGE
- || !value_range_nonnegative_p (&vr1)
- || TREE_CODE (vr1.max) != INTEGER_CST
- || compare_tree_int (vr1.max,
- TYPE_PRECISION (expr_type) - 1) == 1)
- {
- set_value_range_to_varying (vr);
- return;
- }
+ set_value_range_to_varying (vr);
+ return;
}
extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
size_int (TYPE_PRECISION (outer_type)))))))
{
tree new_min, new_max;
- new_min = force_fit_type_double (outer_type,
- tree_to_double_int (vr0.min),
- 0, false);
- new_max = force_fit_type_double (outer_type,
- tree_to_double_int (vr0.max),
- 0, false);
if (is_overflow_infinity (vr0.min))
new_min = negative_overflow_infinity (outer_type);
+ else
+ new_min = force_fit_type_double (outer_type,
+ tree_to_double_int (vr0.min),
+ 0, false);
if (is_overflow_infinity (vr0.max))
new_max = positive_overflow_infinity (outer_type);
+ else
+ new_max = force_fit_type_double (outer_type,
+ tree_to_double_int (vr0.max),
+ 0, false);
set_and_canonicalize_value_range (vr, vr0.type,
new_min, new_max, NULL);
return;
set_value_range_to_varying (&vr1);
/* The resulting value range is the union of the operand ranges */
- vrp_meet (&vr0, &vr1);
copy_value_range (vr, &vr0);
+ vrp_meet (vr, &vr1);
}
{
if (vr0->type == VR_UNDEFINED)
{
- copy_value_range (vr0, vr1);
+ /* Drop equivalences. See PR53465. */
+ set_value_range (vr0, vr1->type, vr1->min, vr1->max, NULL);
return;
}
if (vr1->type == VR_UNDEFINED)
{
- /* Nothing to do. VR0 already has the resulting range. */
+ /* VR0 already has the resulting range, just drop equivalences.
+ See PR53465. */
+ if (vr0->equiv)
+ bitmap_clear (vr0->equiv);
return;
}
tree lhs = PHI_RESULT (phi);
value_range_t *lhs_vr = get_value_range (lhs);
value_range_t vr_result = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+ bool first = true;
int edges, old_edges;
struct loop *l;
fprintf (dump_file, "\n");
}
- vrp_meet (&vr_result, &vr_arg);
+ if (first)
+ copy_value_range (&vr_result, &vr_arg);
+ else
+ vrp_meet (&vr_result, &vr_arg);
+ first = false;
if (vr_result.type == VR_VARYING)
break;
tree innerop, middleop, finaltype;
gimple def_stmt;
value_range_t *innervr;
- double_int innermin, innermax, middlemin, middlemax;
+ bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
+ unsigned inner_prec, middle_prec, final_prec;
+ double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
if (!INTEGRAL_TYPE_P (finaltype))
the middle conversion is removed. */
innermin = tree_to_double_int (innervr->min);
innermax = tree_to_double_int (innervr->max);
- middlemin = double_int_ext (innermin, TYPE_PRECISION (TREE_TYPE (middleop)),
- TYPE_UNSIGNED (TREE_TYPE (middleop)));
- middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)),
- TYPE_UNSIGNED (TREE_TYPE (middleop)));
- /* If the middle values are not equal to the original values fail.
- But only if the inner cast truncates (thus we ignore differences
- in extension to handle the case going from a range to an anti-range
- and back). */
- if ((TYPE_PRECISION (TREE_TYPE (innerop))
- > TYPE_PRECISION (TREE_TYPE (middleop)))
- && (!double_int_equal_p (innermin, middlemin)
- || !double_int_equal_p (innermax, middlemax)))
+
+ inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
+ middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
+ final_prec = TYPE_PRECISION (finaltype);
+
+ /* If the first conversion is not injective, the second must not
+ be widening. */
+ if (double_int_cmp (double_int_sub (innermax, innermin),
+ double_int_mask (middle_prec), true) > 0
+ && middle_prec < final_prec)
return false;
+ /* We also want a medium value so that we can track the effect that
+ narrowing conversions with sign change have. */
+ inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
+ if (inner_unsigned_p)
+ innermed = double_int_rshift (double_int_mask (inner_prec),
+ 1, inner_prec, false);
+ else
+ innermed = double_int_zero;
+ if (double_int_cmp (innermin, innermed, inner_unsigned_p) >= 0
+ || double_int_cmp (innermed, innermax, inner_unsigned_p) >= 0)
+ innermed = innermin;
+
+ middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
+ middlemin = double_int_ext (innermin, middle_prec, middle_unsigned_p);
+ middlemed = double_int_ext (innermed, middle_prec, middle_unsigned_p);
+ middlemax = double_int_ext (innermax, middle_prec, middle_unsigned_p);
+
/* Require that the final conversion applied to both the original
and the intermediate range produces the same result. */
+ final_unsigned_p = TYPE_UNSIGNED (finaltype);
if (!double_int_equal_p (double_int_ext (middlemin,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)),
+ final_prec, final_unsigned_p),
double_int_ext (innermin,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)))
+ final_prec, final_unsigned_p))
+ || !double_int_equal_p (double_int_ext (middlemed,
+ final_prec, final_unsigned_p),
+ double_int_ext (innermed,
+ final_prec, final_unsigned_p))
|| !double_int_equal_p (double_int_ext (middlemax,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)),
+ final_prec, final_unsigned_p),
double_int_ext (innermax,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype))))
+ final_prec, final_unsigned_p)))
return false;
gimple_assign_set_rhs1 (stmt, innerop);