fold-const.c (fold_negate_expr): Add ANY_INTEGRAL_TYPE_P check.
* fold-const.c (fold_negate_expr): Add ANY_INTEGRAL_TYPE_P check. (extract_muldiv_1): Likewise. (maybe_canonicalize_comparison_1): Likewise. (fold_comparison): Likewise. (tree_binary_nonnegative_warnv_p): Likewise. (tree_binary_nonzero_warnv_p): Likewise. * gimple-ssa-strength-reduction.c (legal_cast_p_1): Likewise. * tree-scalar-evolution.c (simple_iv): Likewise. (scev_const_prop): Likewise. * tree-ssa-loop-niter.c (expand_simple_operations): Likewise. * tree-vect-generic.c (expand_vector_operation): Likewise. * tree.h (ANY_INTEGRAL_TYPE_CHECK): Define. (ANY_INTEGRAL_TYPE_P): Define. (TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED, TYPE_OVERFLOW_TRAPS): Add ANY_INTEGRAL_TYPE_CHECK. (any_integral_type_check): New function. From-SVN: r218621
This commit is contained in:
parent
f63950e561
commit
20bd649ae4
|
@ -1,3 +1,22 @@
|
|||
2014-12-11 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* fold-const.c (fold_negate_expr): Add ANY_INTEGRAL_TYPE_P check.
|
||||
(extract_muldiv_1): Likewise.
|
||||
(maybe_canonicalize_comparison_1): Likewise.
|
||||
(fold_comparison): Likewise.
|
||||
(tree_binary_nonnegative_warnv_p): Likewise.
|
||||
(tree_binary_nonzero_warnv_p): Likewise.
|
||||
* gimple-ssa-strength-reduction.c (legal_cast_p_1): Likewise.
|
||||
* tree-scalar-evolution.c (simple_iv): Likewise.
|
||||
(scev_const_prop): Likewise.
|
||||
* tree-ssa-loop-niter.c (expand_simple_operations): Likewise.
|
||||
* tree-vect-generic.c (expand_vector_operation): Likewise.
|
||||
* tree.h (ANY_INTEGRAL_TYPE_CHECK): Define.
|
||||
(ANY_INTEGRAL_TYPE_P): Define.
|
||||
(TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED, TYPE_OVERFLOW_TRAPS):
|
||||
Add ANY_INTEGRAL_TYPE_CHECK.
|
||||
(any_integral_type_check): New function.
|
||||
|
||||
2014-12-11 Tobias Burnus <burnus@net-b.de>
|
||||
Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||
|
||||
|
|
|
@ -558,7 +558,8 @@ fold_negate_expr (location_t loc, tree t)
|
|||
case INTEGER_CST:
|
||||
tem = fold_negate_const (t, type);
|
||||
if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
|
||||
|| (!TYPE_OVERFLOW_TRAPS (type)
|
||||
|| (ANY_INTEGRAL_TYPE_P (type)
|
||||
&& !TYPE_OVERFLOW_TRAPS (type)
|
||||
&& TYPE_OVERFLOW_WRAPS (type))
|
||||
|| (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
|
||||
return tem;
|
||||
|
@ -5951,7 +5952,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|
|||
|| EXPRESSION_CLASS_P (op0))
|
||||
/* ... and has wrapping overflow, and its type is smaller
|
||||
than ctype, then we cannot pass through as widening. */
|
||||
&& ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))
|
||||
&& (((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0)))
|
||||
&& (TYPE_PRECISION (ctype)
|
||||
> TYPE_PRECISION (TREE_TYPE (op0))))
|
||||
/* ... or this is a truncation (t is narrower than op0),
|
||||
|
@ -5966,7 +5968,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|
|||
/* ... or has undefined overflow while the converted to
|
||||
type has not, we cannot do the operation in the inner type
|
||||
as that would introduce undefined overflow. */
|
||||
|| (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
|
||||
|| ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
|
||||
&& !TYPE_OVERFLOW_UNDEFINED (type))))
|
||||
break;
|
||||
|
||||
|
@ -8497,7 +8500,8 @@ maybe_canonicalize_comparison_1 (location_t loc, enum tree_code code, tree type,
|
|||
|
||||
/* Match A +- CST code arg1 and CST code arg1. We can change the
|
||||
first form only if overflow is undefined. */
|
||||
if (!((TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
|
||||
if (!(((ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
|
||||
/* In principle pointers also have undefined overflow behavior,
|
||||
but that causes problems elsewhere. */
|
||||
&& !POINTER_TYPE_P (TREE_TYPE (arg0))
|
||||
|
@ -8712,7 +8716,9 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
|||
|
||||
/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */
|
||||
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
|
||||
&& (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
|
||||
&& (equality_code
|
||||
|| (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
|
||||
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
|
||||
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
|
||||
&& TREE_CODE (arg1) == INTEGER_CST
|
||||
|
@ -9031,7 +9037,8 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
|||
X CMP Y +- C2 +- C1 for signed X, Y. This is valid if
|
||||
the resulting offset is smaller in absolute value than the
|
||||
original one and has the same sign. */
|
||||
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
|
||||
if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
|
||||
&& (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
|
||||
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
|
||||
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
|
||||
|
@ -9085,7 +9092,8 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
|||
signed arithmetic case. That form is created by the compiler
|
||||
often enough for folding it to be of value. One example is in
|
||||
computing loop trip counts after Operator Strength Reduction. */
|
||||
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
|
||||
if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
|
||||
&& TREE_CODE (arg0) == MULT_EXPR
|
||||
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
|
||||
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
|
||||
|
@ -14733,7 +14741,8 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
|
|||
|| (tree_expr_nonnegative_warnv_p (op0, strict_overflow_p)
|
||||
&& tree_expr_nonnegative_warnv_p (op1, strict_overflow_p)))
|
||||
{
|
||||
if (TYPE_OVERFLOW_UNDEFINED (type))
|
||||
if (ANY_INTEGRAL_TYPE_P (type)
|
||||
&& TYPE_OVERFLOW_UNDEFINED (type))
|
||||
*strict_overflow_p = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -15205,7 +15214,7 @@ tree_binary_nonzero_warnv_p (enum tree_code code,
|
|||
{
|
||||
case POINTER_PLUS_EXPR:
|
||||
case PLUS_EXPR:
|
||||
if (TYPE_OVERFLOW_UNDEFINED (type))
|
||||
if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
|
||||
{
|
||||
/* With the presence of negative values it is hard
|
||||
to say something. */
|
||||
|
|
|
@ -1487,8 +1487,8 @@ legal_cast_p_1 (tree lhs, tree rhs)
|
|||
rhs_type = TREE_TYPE (rhs);
|
||||
lhs_size = TYPE_PRECISION (lhs_type);
|
||||
rhs_size = TYPE_PRECISION (rhs_type);
|
||||
lhs_wraps = TYPE_OVERFLOW_WRAPS (lhs_type);
|
||||
rhs_wraps = TYPE_OVERFLOW_WRAPS (rhs_type);
|
||||
lhs_wraps = ANY_INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS (lhs_type);
|
||||
rhs_wraps = ANY_INTEGRAL_TYPE_P (rhs_type) && TYPE_OVERFLOW_WRAPS (rhs_type);
|
||||
|
||||
if (lhs_size < rhs_size
|
||||
|| (rhs_wraps && !lhs_wraps)
|
||||
|
|
|
@ -3267,7 +3267,8 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
|
|||
if (tree_contains_chrecs (iv->base, NULL))
|
||||
return false;
|
||||
|
||||
iv->no_overflow = !folded_casts && TYPE_OVERFLOW_UNDEFINED (type);
|
||||
iv->no_overflow = (!folded_casts && ANY_INTEGRAL_TYPE_P (type)
|
||||
&& TYPE_OVERFLOW_UNDEFINED (type));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3490,7 +3491,8 @@ scev_const_prop (void)
|
|||
/* If def's type has undefined overflow and there were folded
|
||||
casts, rewrite all stmts added for def into arithmetics
|
||||
with defined overflow behavior. */
|
||||
if (folded_casts && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (def)))
|
||||
if (folded_casts && ANY_INTEGRAL_TYPE_P (TREE_TYPE (def))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (def)))
|
||||
{
|
||||
gimple_seq stmts;
|
||||
gimple_stmt_iterator gsi2;
|
||||
|
|
|
@ -1642,7 +1642,8 @@ expand_simple_operations (tree expr)
|
|||
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
if (TYPE_OVERFLOW_TRAPS (TREE_TYPE (expr)))
|
||||
if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (expr))
|
||||
&& TYPE_OVERFLOW_TRAPS (TREE_TYPE (expr)))
|
||||
return expr;
|
||||
/* Fallthru. */
|
||||
case POINTER_PLUS_EXPR:
|
||||
|
|
|
@ -926,14 +926,14 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
|
|||
{
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
if (!TYPE_OVERFLOW_TRAPS (type))
|
||||
if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
|
||||
return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
|
||||
gimple_assign_rhs1 (assign),
|
||||
gimple_assign_rhs2 (assign), code);
|
||||
break;
|
||||
|
||||
case NEGATE_EXPR:
|
||||
if (!TYPE_OVERFLOW_TRAPS (type))
|
||||
if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
|
||||
return expand_vector_addition (gsi, do_unop, do_negate, type,
|
||||
gimple_assign_rhs1 (assign),
|
||||
NULL_TREE, code);
|
||||
|
|
44
gcc/tree.h
44
gcc/tree.h
|
@ -283,6 +283,10 @@ along with GCC; see the file COPYING3. If not see
|
|||
#define NON_TYPE_CHECK(T) \
|
||||
(non_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
|
||||
|
||||
/* These checks have to be special cased. */
|
||||
#define ANY_INTEGRAL_TYPE_CHECK(T) \
|
||||
(any_integral_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
|
||||
|
||||
#define TREE_INT_CST_ELT_CHECK(T, I) \
|
||||
(*tree_int_cst_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))
|
||||
|
||||
|
@ -388,6 +392,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
|||
#define OMP_CLAUSE_ELT_CHECK(T, i) ((T)->omp_clause.ops[i])
|
||||
#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) (T)
|
||||
#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) (T)
|
||||
#define ANY_INTEGRAL_TYPE_CHECK(T) (T)
|
||||
|
||||
#define TREE_CHAIN(NODE) ((NODE)->common.chain)
|
||||
#define TREE_TYPE(NODE) ((NODE)->typed.type)
|
||||
|
@ -482,6 +487,15 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
|||
|| TREE_CODE (TYPE) == BOOLEAN_TYPE \
|
||||
|| TREE_CODE (TYPE) == INTEGER_TYPE)
|
||||
|
||||
/* Nonzero if TYPE represents an integral type, including complex
|
||||
and vector integer types. */
|
||||
|
||||
#define ANY_INTEGRAL_TYPE_P(TYPE) \
|
||||
(INTEGRAL_TYPE_P (TYPE) \
|
||||
|| ((TREE_CODE (TYPE) == COMPLEX_TYPE \
|
||||
|| VECTOR_TYPE_P (TYPE)) \
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TYPE))))
|
||||
|
||||
/* Nonzero if TYPE represents a non-saturating fixed-point type. */
|
||||
|
||||
#define NON_SAT_FIXED_POINT_TYPE_P(TYPE) \
|
||||
|
@ -771,7 +785,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
|||
/* True if overflow wraps around for the given integral type. That
|
||||
is, TYPE_MAX + 1 == TYPE_MIN. */
|
||||
#define TYPE_OVERFLOW_WRAPS(TYPE) \
|
||||
(TYPE_UNSIGNED (TYPE) || flag_wrapv)
|
||||
(ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag || flag_wrapv)
|
||||
|
||||
/* True if overflow is undefined for the given integral type. We may
|
||||
optimize on the assumption that values in the type never overflow.
|
||||
|
@ -781,13 +795,14 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
|||
it will be appropriate to issue the warning immediately, and in
|
||||
other cases it will be appropriate to simply set a flag and let the
|
||||
caller decide whether a warning is appropriate or not. */
|
||||
#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
|
||||
(!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && flag_strict_overflow)
|
||||
#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
|
||||
(!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \
|
||||
&& !flag_wrapv && !flag_trapv && flag_strict_overflow)
|
||||
|
||||
/* True if overflow for the given integral type should issue a
|
||||
trap. */
|
||||
#define TYPE_OVERFLOW_TRAPS(TYPE) \
|
||||
(!TYPE_UNSIGNED (TYPE) && flag_trapv)
|
||||
(!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag && flag_trapv)
|
||||
|
||||
/* True if an overflow is to be preserved for sanitization. */
|
||||
#define TYPE_OVERFLOW_SANITIZED(TYPE) \
|
||||
|
@ -2990,6 +3005,17 @@ omp_clause_elt_check (tree __t, int __i,
|
|||
return &__t->omp_clause.ops[__i];
|
||||
}
|
||||
|
||||
/* These checks have to be special cased. */
|
||||
|
||||
inline tree
|
||||
any_integral_type_check (tree __t, const char *__f, int __l, const char *__g)
|
||||
{
|
||||
if (!ANY_INTEGRAL_TYPE_P (__t))
|
||||
tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE,
|
||||
INTEGER_TYPE, 0);
|
||||
return __t;
|
||||
}
|
||||
|
||||
inline const_tree
|
||||
tree_check (const_tree __t, const char *__f, int __l, const char *__g,
|
||||
tree_code __c)
|
||||
|
@ -3197,6 +3223,16 @@ omp_clause_elt_check (const_tree __t, int __i,
|
|||
return CONST_CAST (const_tree *, &__t->omp_clause.ops[__i]);
|
||||
}
|
||||
|
||||
inline const_tree
|
||||
any_integral_type_check (const_tree __t, const char *__f, int __l,
|
||||
const char *__g)
|
||||
{
|
||||
if (!ANY_INTEGRAL_TYPE_P (__t))
|
||||
tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE,
|
||||
INTEGER_TYPE, 0);
|
||||
return __t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Compute the number of operands in an expression node NODE. For
|
||||
|
|
Loading…
Reference in New Issue