{
tree type = TREE_TYPE (val);
- if (INTEGRAL_TYPE_P (type) && val == TYPE_MIN_VALUE (type))
+ if (INTEGRAL_TYPE_P (type)
+ && operand_equal_p (val, TYPE_MIN_VALUE (type), 0))
return 0;
else
return range_binop (MINUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
{
tree type = TREE_TYPE (val);
- if (INTEGRAL_TYPE_P (type) && val == TYPE_MAX_VALUE (type))
+ if (INTEGRAL_TYPE_P (type)
+ && operand_equal_p (val, TYPE_MAX_VALUE (type), 0))
return 0;
else
return range_binop (PLUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
return NULL_TREE;
case TRUNC_DIV_EXPR:
- case ROUND_DIV_EXPR:
case FLOOR_DIV_EXPR:
+ /* Simplify A / (B << N) where A and B are positive and B is
+ a power of 2, to A >> (N + log2(B)). */
+ if (TREE_CODE (arg1) == LSHIFT_EXPR
+ && (TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (arg0)))
+ {
+ tree sval = TREE_OPERAND (arg1, 0);
+ if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
+ {
+ tree sh_cnt = TREE_OPERAND (arg1, 1);
+ unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+
+ sh_cnt = fold_build2 (PLUS_EXPR, TREE_TYPE (sh_cnt),
+ sh_cnt, build_int_cst (NULL_TREE, pow2));
+ return fold_build2 (RSHIFT_EXPR, type,
+ fold_convert (type, arg0), sh_cnt);
+ }
+ }
+ /* Fall thru */
+
+ case ROUND_DIV_EXPR:
case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
if (integer_onep (arg1))
return omit_one_operand (type, integer_zero_node, arg0);
/* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
- i.e. "X % C" into "X & C2", if X and C are positive. */
+ i.e. "X % C" into "X & (C - 1)", if X and C are positive. */
if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
- && (TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (arg0))
- && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) >= 0)
+ && (TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (arg0)))
{
- unsigned HOST_WIDE_INT high, low;
- tree mask;
- int l;
+ tree c = arg1;
+ /* Also optimize A % (C << N) where C is a power of 2,
+ to A & ((C << N) - 1). */
+ if (TREE_CODE (arg1) == LSHIFT_EXPR)
+ c = TREE_OPERAND (arg1, 0);
- l = tree_log2 (arg1);
- if (l >= HOST_BITS_PER_WIDE_INT)
+ if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
{
- high = ((unsigned HOST_WIDE_INT) 1
- << (l - HOST_BITS_PER_WIDE_INT)) - 1;
- low = -1;
- }
- else
- {
- high = 0;
- low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
+ tree mask = fold_build2 (MINUS_EXPR, TREE_TYPE (arg1),
+ arg1, integer_one_node);
+ return fold_build2 (BIT_AND_EXPR, type,
+ fold_convert (type, arg0),
+ fold_convert (type, mask));
}
-
- mask = build_int_cst_wide (type, low, high);
- return fold_build2 (BIT_AND_EXPR, type,
- fold_convert (type, arg0), mask);
}
/* X % -C is the same as X % C. */
if (integer_zerop (op2)
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
- return fold_build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1);
+ return fold_build2 (TRUTH_ANDIF_EXPR, type,
+ fold_convert (type, arg0),
+ arg1);
/* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (op2)
/* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold_build2 (TRUTH_ORIF_EXPR, type, tem, arg1);
+ return fold_build2 (TRUTH_ORIF_EXPR, type,
+ fold_convert (type, tem),
+ arg1);
}
/* Convert A ? 0 : B into !A && B if A and B are truth values. */
/* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold_build2 (TRUTH_ANDIF_EXPR, type, tem, op2);
+ return fold_build2 (TRUTH_ANDIF_EXPR, type,
+ fold_convert (type, tem),
+ op2);
}
/* Convert A ? 1 : B into A || B if A and B are truth values. */
if (integer_onep (arg1)
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (op2)))
- return fold_build2 (TRUTH_ORIF_EXPR, type, arg0, op2);
+ return fold_build2 (TRUTH_ORIF_EXPR, type,
+ fold_convert (type, arg0),
+ op2);
return NULL_TREE;