SAVE_EXPR (I) * SAVE_EXPR (J)
(where the same SAVE_EXPR (J) is used in the original and the
- transformed version). */
+ transformed version).
+
+ NOWRAP specifies whether all outer operations in TYPE should
+ be considered not wrapping. Any type conversion within TOP acts
+ as a barrier and we will fall back to NOWRAP being false.
+ NOWRAP is mostly used to treat expressions in TYPE_SIZE and friends
+ as not wrapping even though they are generally using unsigned arithmetic. */
int
-multiple_of_p (tree type, const_tree top, const_tree bottom)
+multiple_of_p (tree type, const_tree top, const_tree bottom, bool nowrap)
{
gimple *stmt;
tree op1, op2;
a multiple of BOTTOM then TOP is a multiple of BOTTOM. */
if (!integer_pow2p (bottom))
return 0;
- return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
- || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
+ return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom, nowrap)
+ || multiple_of_p (type, TREE_OPERAND (top, 0), bottom, nowrap));
case MULT_EXPR:
+ /* If the multiplication can wrap we cannot recurse further unless
+ the bottom is a power of two which is where wrapping does not
+ matter. */
+ if (!nowrap
+ && !TYPE_OVERFLOW_UNDEFINED (type)
+ && !integer_pow2p (bottom))
+ return 0;
if (TREE_CODE (bottom) == INTEGER_CST)
{
op1 = TREE_OPERAND (top, 0);
std::swap (op1, op2);
if (TREE_CODE (op2) == INTEGER_CST)
{
- if (multiple_of_p (type, op2, bottom))
+ if (multiple_of_p (type, op2, bottom, nowrap))
return 1;
/* Handle multiple_of_p ((x * 2 + 2) * 4, 8). */
- if (multiple_of_p (type, bottom, op2))
+ if (multiple_of_p (type, bottom, op2, nowrap))
{
widest_int w = wi::sdiv_trunc (wi::to_widest (bottom),
wi::to_widest (op2));
if (wi::fits_to_tree_p (w, TREE_TYPE (bottom)))
{
op2 = wide_int_to_tree (TREE_TYPE (bottom), w);
- return multiple_of_p (type, op1, op2);
+ return multiple_of_p (type, op1, op2, nowrap);
}
}
- return multiple_of_p (type, op1, bottom);
+ return multiple_of_p (type, op1, bottom, nowrap);
}
}
- return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
- || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
+ return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom, nowrap)
+ || multiple_of_p (type, TREE_OPERAND (top, 0), bottom, nowrap));
case LSHIFT_EXPR:
/* Handle X << CST as X * (1 << CST) and only process the constant. */
wide_int mul_op
= wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
return multiple_of_p (type,
- wide_int_to_tree (type, mul_op), bottom);
+ wide_int_to_tree (type, mul_op), bottom,
+ nowrap);
}
}
return 0;
case MINUS_EXPR:
- /* It is impossible to prove if op0 - op1 is multiple of bottom
- precisely, so be conservative here checking if both op0 and op1
- are multiple of bottom. Note we check the second operand first
- since it's usually simpler. */
- return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
- && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
-
case PLUS_EXPR:
- /* The same as MINUS_EXPR, but handle cases like op0 + 0xfffffffd
- as op0 - 3 if the expression has unsigned type. For example,
- (X / 3) + 0xfffffffd is multiple of 3, but 0xfffffffd is not. */
+ /* If the addition or subtraction can wrap we cannot recurse further
+ unless bottom is a power of two which is where wrapping does not
+ matter. */
+ if (!nowrap
+ && !TYPE_OVERFLOW_UNDEFINED (type)
+ && !integer_pow2p (bottom))
+ return 0;
+
+ /* Handle cases like op0 + 0xfffffffd as op0 - 3 if the expression has
+ unsigned type. For example, (X / 3) + 0xfffffffd is multiple of 3,
+ but 0xfffffffd is not. */
op1 = TREE_OPERAND (top, 1);
- if (TYPE_UNSIGNED (type)
+ if (TREE_CODE (top) == PLUS_EXPR
+ && nowrap
+ && TYPE_UNSIGNED (type)
&& TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sign_bit (op1))
op1 = fold_build1 (NEGATE_EXPR, type, op1);
- return (multiple_of_p (type, op1, bottom)
- && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
+
+ /* It is impossible to prove if op0 +- op1 is multiple of bottom
+ precisely, so be conservative here checking if both op0 and op1
+ are multiple of bottom. Note we check the second operand first
+ since it's usually simpler. */
+ return (multiple_of_p (type, op1, bottom, nowrap)
+ && multiple_of_p (type, TREE_OPERAND (top, 0), bottom, nowrap));
CASE_CONVERT:
/* Can't handle conversions from non-integral or wider integral type. */
|| (TYPE_PRECISION (type)
< TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
return 0;
+ /* NOWRAP only extends to operations in the outermost type so
+ make sure to strip it off here. */
return multiple_of_p (TREE_TYPE (TREE_OPERAND (top, 0)),
- TREE_OPERAND (top, 0), bottom);
+ TREE_OPERAND (top, 0), bottom, false);
case SAVE_EXPR:
- return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
+ return multiple_of_p (type, TREE_OPERAND (top, 0), bottom, nowrap);
case COND_EXPR:
- return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
- && multiple_of_p (type, TREE_OPERAND (top, 2), bottom));
+ return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom, nowrap)
+ && multiple_of_p (type, TREE_OPERAND (top, 2), bottom, nowrap));
case INTEGER_CST:
if (TREE_CODE (bottom) != INTEGER_CST
new_base = base - step > FINAL ; step < 0
&& base - step doesn't overflow
- 2') |FINAL - new_base| is an exact multiple of step.
-
- Please refer to PR34114 as an example of loop-ch's impact, also refer
- to PR72817 as an example why condition 2') is necessary.
+ Please refer to PR34114 as an example of loop-ch's impact.
Note, for NE_EXPR, base equals to FINAL is a special case, in
- which the loop exits immediately, and the iv does not overflow. */
+ which the loop exits immediately, and the iv does not overflow.
+
+ Also note, we prove condition 2) by checking base and final seperately
+ along with condition 1) or 1'). */
if (!niter->control.no_overflow
- && (integer_onep (s) || multiple_of_p (type, c, s)))
+ && (integer_onep (s)
+ || (multiple_of_p (type, fold_convert (niter_type, iv->base), s,
+ false)
+ && multiple_of_p (type, fold_convert (niter_type, final), s,
+ false))))
{
- tree t, cond, new_c, relaxed_cond = boolean_false_node;
+ tree t, cond, relaxed_cond = boolean_false_node;
if (tree_int_cst_sign_bit (iv->step))
{
if (integer_nonzerop (t))
{
t = fold_build2 (MINUS_EXPR, type, iv->base, iv->step);
- new_c = fold_build2 (MINUS_EXPR, niter_type,
- fold_convert (niter_type, t),
- fold_convert (niter_type, final));
- if (multiple_of_p (type, new_c, s))
- relaxed_cond = fold_build2 (GT_EXPR, boolean_type_node,
- t, final);
+ relaxed_cond = fold_build2 (GT_EXPR, boolean_type_node, t,
+ final);
}
}
}
if (integer_nonzerop (t))
{
t = fold_build2 (MINUS_EXPR, type, iv->base, iv->step);
- new_c = fold_build2 (MINUS_EXPR, niter_type,
- fold_convert (niter_type, final),
- fold_convert (niter_type, t));
- if (multiple_of_p (type, new_c, s))
- relaxed_cond = fold_build2 (LT_EXPR, boolean_type_node,
- t, final);
+ relaxed_cond = fold_build2 (LT_EXPR, boolean_type_node, t,
+ final);
}
}
}
t = simplify_using_initial_conditions (loop, relaxed_cond);
if (t && integer_onep (t))
- niter->control.no_overflow = true;
- }
-
- /* First the trivial cases -- when the step is 1. */
- if (integer_onep (s))
- {
- niter->niter = c;
- return true;
- }
- if (niter->control.no_overflow && multiple_of_p (type, c, s))
- {
- niter->niter = fold_build2 (FLOOR_DIV_EXPR, niter_type, c, s);
- return true;
+ {
+ niter->control.no_overflow = true;
+ niter->niter = fold_build2 (EXACT_DIV_EXPR, niter_type, c, s);
+ return true;
+ }
}
/* Let nsd (step, size of mode) = d. If d does not divide c, the loop