On Sun, 16 Nov 2014, Richard Biener wrote:
I think the element_mode is the way to go.
The following passed bootstrap+testsuite.
2014-11-16 Marc Glisse <marc.gli...@inria.fr>
* tree.c (element_mode, integer_truep): New functions.
* tree.h (element_mode, integer_truep): Declare them.
* fold-const.c (negate_expr_p, fold_negate_expr, combine_comparisons,
fold_cond_expr_with_comparison, fold_real_zero_addition_p,
fold_comparison, fold_ternary_loc, tree_call_nonnegative_warnv_p,
fold_strip_sign_ops): Use element_mode.
(fold_binary_loc): Use element_mode and element_precision.
* match.pd: Use integer_truep, element_mode, element_precision,
VECTOR_TYPE_P and build_one_cst. Extend some transformations to
vectors. Simplify A/-A.
--
Marc Glisse
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 217614)
+++ gcc/fold-const.c (working copy)
@@ -435,46 +435,46 @@ negate_expr_p (tree t)
}
case COMPLEX_EXPR:
return negate_expr_p (TREE_OPERAND (t, 0))
&& negate_expr_p (TREE_OPERAND (t, 1));
case CONJ_EXPR:
return negate_expr_p (TREE_OPERAND (t, 0));
case PLUS_EXPR:
- if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
- || HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
+ || HONOR_SIGNED_ZEROS (element_mode (type)))
return false;
/* -(A + B) -> (-B) - A. */
if (negate_expr_p (TREE_OPERAND (t, 1))
&& reorder_operands_p (TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1)))
return true;
/* -(A + B) -> (-A) - B. */
return negate_expr_p (TREE_OPERAND (t, 0));
case MINUS_EXPR:
/* We can't turn -(A-B) into B-A when we honor signed zeros. */
- return !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
+ && !HONOR_SIGNED_ZEROS (element_mode (type))
&& reorder_operands_p (TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1));
case MULT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (t)))
break;
/* Fall through. */
case RDIV_EXPR:
- if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+ if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (TREE_TYPE (t))))
return negate_expr_p (TREE_OPERAND (t, 1))
|| negate_expr_p (TREE_OPERAND (t, 0));
break;
case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
/* In general we can't negate A / B, because if A is INT_MIN and
B is 1, we may turn this into INT_MIN / -1 which is undefined
and actually traps on some architectures. But if overflow is
@@ -610,22 +610,22 @@ fold_negate_expr (location_t loc, tree t
return fold_build1_loc (loc, CONJ_EXPR, type,
fold_negate_expr (loc, TREE_OPERAND (t, 0)));
break;
case NEGATE_EXPR:
if (!TYPE_OVERFLOW_SANITIZED (type))
return TREE_OPERAND (t, 0);
break;
case PLUS_EXPR:
- if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
+ && !HONOR_SIGNED_ZEROS (element_mode (type)))
{
/* -(A + B) -> (-B) - A. */
if (negate_expr_p (TREE_OPERAND (t, 1))
&& reorder_operands_p (TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1)))
{
tem = negate_expr (TREE_OPERAND (t, 1));
return fold_build2_loc (loc, MINUS_EXPR, type,
tem, TREE_OPERAND (t, 0));
}
@@ -635,35 +635,35 @@ fold_negate_expr (location_t loc, tree t
{
tem = negate_expr (TREE_OPERAND (t, 0));
return fold_build2_loc (loc, MINUS_EXPR, type,
tem, TREE_OPERAND (t, 1));
}
}
break;
case MINUS_EXPR:
/* - (A - B) -> B - A */
- if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
+ && !HONOR_SIGNED_ZEROS (element_mode (type))
&& reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
return fold_build2_loc (loc, MINUS_EXPR, type,
TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
break;
case MULT_EXPR:
if (TYPE_UNSIGNED (type))
break;
/* Fall through. */
case RDIV_EXPR:
- if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type)))
+ if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)))
{
tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem))
return fold_build2_loc (loc, TREE_CODE (t), type,
TREE_OPERAND (t, 0), negate_expr (tem));
tem = TREE_OPERAND (t, 0);
if (negate_expr_p (tem))
return fold_build2_loc (loc, TREE_CODE (t), type,
negate_expr (tem), TREE_OPERAND (t, 1));
}
@@ -2308,21 +2308,21 @@ compcode_to_comparison (enum comparison_
and RCODE on the identical operands LL_ARG and LR_ARG. Take into account
the possibility of trapping if the mode has NaNs, and return NULL_TREE
if this makes the transformation invalid. */
tree
combine_comparisons (location_t loc,
enum tree_code code, enum tree_code lcode,
enum tree_code rcode, tree truth_type,
tree ll_arg, tree lr_arg)
{
- bool honor_nans = HONOR_NANS (TYPE_MODE (TREE_TYPE (ll_arg)));
+ bool honor_nans = HONOR_NANS (element_mode (ll_arg));
enum comparison_code lcompcode = comparison_to_compcode (lcode);
enum comparison_code rcompcode = comparison_to_compcode (rcode);
int compcode;
switch (code)
{
case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR:
compcode = lcompcode & rcompcode;
break;
@@ -4574,21 +4574,21 @@ fold_cond_expr_with_comparison (location
None of these transformations work for modes with signed
zeros. If A is +/-0, the first two transformations will
change the sign of the result (from +0 to -0, or vice
versa). The last four will fix the sign of the result,
even though the original expressions could be positive or
negative, depending on the sign of A.
Note that all these transformations are correct if A is
NaN, since the two alternatives (A and -A) are also NaNs. */
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ if (!HONOR_SIGNED_ZEROS (element_mode (type))
&& (FLOAT_TYPE_P (TREE_TYPE (arg01))
? real_zerop (arg01)
: integer_zerop (arg01))
&& ((TREE_CODE (arg2) == NEGATE_EXPR
&& operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
/* In the case that A is of the form X-Y, '-A' (arg2) may
have already been folded to Y-X, check for that. */
|| (TREE_CODE (arg1) == MINUS_EXPR
&& TREE_CODE (arg2) == MINUS_EXPR
&& operand_equal_p (TREE_OPERAND (arg1, 0),
@@ -4632,21 +4632,21 @@ fold_cond_expr_with_comparison (location
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
break;
}
/* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
A == 0 ? A : 0 is always 0 unless A is -0. Note that
both transformations are correct when A is NaN: A != 0
is then true, and A == 0 is false. */
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ if (!HONOR_SIGNED_ZEROS (element_mode (type))
&& integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type,
arg1));
else if (comp_code == EQ_EXPR)
return build_zero_cst (type);
}
/* Try some transformations of A op B ? A : B.
@@ -4667,21 +4667,21 @@ fold_cond_expr_with_comparison (location
The first two transformations are correct if either A or B
is a NaN. In the first transformation, the condition will
be false, and B will indeed be chosen. In the case of the
second transformation, the condition A != B will be true,
and A will be chosen.
The conversions to max() and min() are not correct if B is
a number and A is not. The conditions in the original
expressions will be false, so all four give B. The min()
and max() versions would give a NaN instead. */
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ if (!HONOR_SIGNED_ZEROS (element_mode (type))
&& operand_equal_for_comparison_p (arg01, arg2, arg00)
/* Avoid these transformations if the COND_EXPR may be used
as an lvalue in the C++ front-end. PR c++/19199. */
&& (in_gimple_form
|| VECTOR_TYPE_P (type)
|| (strcmp (lang_hooks.name, "GNU C++") != 0
&& strcmp (lang_hooks.name, "GNU Objective-C++") != 0)
|| ! maybe_lvalue_p (arg1)
|| ! maybe_lvalue_p (arg2)))
{
@@ -4704,55 +4704,55 @@ fold_cond_expr_with_comparison (location
case NE_EXPR:
return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type,
arg1));
case LE_EXPR:
case LT_EXPR:
case UNLE_EXPR:
case UNLT_EXPR:
/* In C++ a ?: expression can be an lvalue, so put the
operand which will be used if they are equal first
so that we can convert this back to the
corresponding COND_EXPR. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ if (!HONOR_NANS (element_mode (arg1)))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0,
comp_op1)
: fold_build2_loc (loc, MIN_EXPR, comp_type,
comp_op1, comp_op0);
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, tem));
}
break;
case GE_EXPR:
case GT_EXPR:
case UNGE_EXPR:
case UNGT_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ if (!HONOR_NANS (element_mode (arg1)))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0,
comp_op1)
: fold_build2_loc (loc, MAX_EXPR, comp_type,
comp_op1, comp_op0);
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, tem));
}
break;
case UNEQ_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ if (!HONOR_NANS (element_mode (arg1)))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg2));
break;
case LTGT_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ if (!HONOR_NANS (element_mode (arg1)))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg1));
break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
break;
}
}
/* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
@@ -6083,40 +6083,40 @@ fold_binary_op_with_conditional_arg (loc
X - 0 is not the same as X because 0 - 0 is -0. In other rounding
modes, X + 0 is not the same as X because -0 + 0 is 0. */
bool
fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
{
if (!real_zerop (addend))
return false;
/* Don't allow the fold with -fsignaling-nans. */
- if (HONOR_SNANS (TYPE_MODE (type)))
+ if (HONOR_SNANS (element_mode (type)))
return false;
/* Allow the fold if zeros aren't signed, or their sign isn't important. */
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ if (!HONOR_SIGNED_ZEROS (element_mode (type)))
return true;
/* In a vector or complex, we would need to check the sign of all zeros. */
if (TREE_CODE (addend) != REAL_CST)
return false;
/* Treat x + -0 as x - 0 and x - -0 as x + 0. */
if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
negate = !negate;
/* The mode has signed zeros, and we have to honor their sign.
In this situation, there is only one case we can return true for.
X - 0 is the same as X unless rounding towards -infinity is
supported. */
- return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
+ return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
}
/* Subroutine of fold() that checks comparisons of built-in math
functions against real constants.
FCODE is the DECL_FUNCTION_CODE of the built-in, CODE is the comparison
operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, GE_EXPR or LE_EXPR. TYPE
is the type of the result and ARG0 and ARG1 are the operands of the
comparison. ARG1 must be a TREE_REAL_CST.
@@ -9073,36 +9073,36 @@ fold_comparison (location_t loc, enum tr
}
/* Simplify comparison of something with itself. (For IEEE
floating-point, we can only do some of these simplifications.) */
if (operand_equal_p (arg0, arg1, 0))
{
switch (code)
{
case EQ_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ || ! HONOR_NANS (element_mode (arg0)))
return constant_boolean_node (1, type);
break;
case GE_EXPR:
case LE_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ || ! HONOR_NANS (element_mode (arg0)))
return constant_boolean_node (1, type);
return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
case NE_EXPR:
/* For NE, we can only do this simplification if integer
or we don't honor IEEE floating point NaNs. */
if (FLOAT_TYPE_P (TREE_TYPE (arg0))
- && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ && HONOR_NANS (element_mode (arg0)))
break;
/* ... fall through ... */
case GT_EXPR:
case LT_EXPR:
return constant_boolean_node (0, type);
default:
gcc_unreachable ();
}
}
@@ -9961,22 +9961,22 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type, marg),
fold_convert_loc (loc, type,
parg1)));
}
}
else
{
/* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y )
to __complex__ ( x, y ). This is not the same for SNaNs or
if signed zeros are involved. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ if (!HONOR_SNANS (element_mode (arg0))
+ && !HONOR_SIGNED_ZEROS (element_mode (arg0))
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
bool arg0rz = false, arg0iz = false;
if ((arg0r && (arg0rz = real_zerop (arg0r)))
|| (arg0i && (arg0iz = real_zerop (arg0i))))
{
tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
@@ -10398,22 +10398,22 @@ fold_binary_loc (location_t loc,
tem = fold_build2_loc (loc, BIT_XOR_EXPR, type,
TREE_OPERAND (arg0, 0), mask1);
return fold_build2_loc (loc, MINUS_EXPR, type, tem, mask1);
}
}
}
/* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
__complex__ ( x, -y ). This is not the same for SNaNs or if
signed zeros are involved. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ if (!HONOR_SNANS (element_mode (arg0))
+ && !HONOR_SIGNED_ZEROS (element_mode (arg0))
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
bool arg0rz = false, arg0iz = false;
if ((arg0r && (arg0rz = real_zerop (arg0r)))
|| (arg0i && (arg0iz = real_zerop (arg0i))))
{
tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
@@ -10602,22 +10602,22 @@ fold_binary_loc (location_t loc,
if (tem != NULL_TREE)
{
tem = fold_convert_loc (loc, type, tem);
return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
}
}
/* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
This is not the same for NaNs or if signed zeros are
involved. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ if (!HONOR_NANS (element_mode (arg0))
+ && !HONOR_SIGNED_ZEROS (element_mode (arg0))
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == COMPLEX_CST
&& real_zerop (TREE_REALPART (arg1)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
if (real_onep (TREE_IMAGPART (arg1)))
return
fold_build2_loc (loc, COMPLEX_EXPR, type,
negate_expr (fold_build1_loc (loc, IMAGPART_EXPR,
rtype, arg0)),
@@ -10650,21 +10650,21 @@ fold_binary_loc (location_t loc,
/* Optimizations of root(...)*root(...). */
if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
{
tree rootfn, arg;
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg10 = CALL_EXPR_ARG (arg1, 0);
/* Optimize sqrt(x)*sqrt(x) as x. */
if (BUILTIN_SQRT_P (fcode0)
&& operand_equal_p (arg00, arg10, 0)
- && ! HONOR_SNANS (TYPE_MODE (type)))
+ && ! HONOR_SNANS (element_mode (type)))
return arg00;
/* Optimize root(x)*root(y) as root(x*y). */
rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10);
return build_call_expr_loc (loc, rootfn, 1, arg);
}
/* Optimize expN(x)*expN(y) as expN(x+y). */
if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
@@ -11298,21 +11298,21 @@ fold_binary_loc (location_t loc,
}
}
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
/* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
- prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
+ prec = element_precision (TREE_TYPE (TREE_OPERAND (arg0, 0)));
wide_int mask = wide_int::from (arg1, prec, UNSIGNED);
if (mask == -1)
return
fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
}
/* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
This results in more efficient code for machines without a NOR
@@ -11534,42 +11534,42 @@ fold_binary_loc (location_t loc,
/* Optimize sin(x)/tan(x) as cos(x) if we don't care about
NaNs or Infinities. */
if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN)
|| (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF)
|| (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL)))
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
- && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
+ if (! HONOR_NANS (element_mode (arg00))
+ && ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
return build_call_expr_loc (loc, cosfn, 1, arg00);
}
}
/* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
NaNs or Infinities. */
if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN)
|| (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
|| (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
- && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
+ if (! HONOR_NANS (element_mode (arg00))
+ && ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
{
tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
return fold_build2_loc (loc, RDIV_EXPR, type,
build_real (type, dconst1),
tmp);
@@ -12928,21 +12928,21 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
build2 (GE_EXPR, type,
TREE_OPERAND (arg0, 0), tem),
build2 (LE_EXPR, type,
TREE_OPERAND (arg0, 0), arg1));
/* Convert ABS_EXPR<x> >= 0 to true. */
strict_overflow_p = false;
if (code == GE_EXPR
&& (integer_zerop (arg1)
- || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+ || (! HONOR_NANS (element_mode (arg0))
&& real_zerop (arg1)))
&& tree_expr_nonnegative_warnv_p (arg0, &strict_overflow_p))
{
if (strict_overflow_p)
fold_overflow_warning (("assuming signed overflow does not occur "
"when simplifying comparison of "
"absolute value and zero"),
WARN_STRICT_OVERFLOW_CONDITIONAL);
return omit_one_operand_loc (loc, type,
constant_boolean_node (true, type),
@@ -12980,25 +12980,25 @@ fold_binary_loc (location_t loc,
otherwise Y might be >= # of bits in X's type and thus e.g.
(unsigned char) (1 << Y) for Y 15 might be 0.
If the cast is widening, then 1 << Y should have unsigned type,
otherwise if Y is number of bits in the signed shift type minus 1,
we can't optimize this. E.g. (unsigned long long) (1 << Y) for Y
31 might be 0xffffffff80000000. */
if ((code == LT_EXPR || code == GE_EXPR)
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& CONVERT_EXPR_P (arg1)
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
- && (TYPE_PRECISION (TREE_TYPE (arg1))
- >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))
+ && (element_precision (TREE_TYPE (arg1))
+ >= element_precision (TREE_TYPE (TREE_OPERAND (arg1, 0))))
&& (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))
- || (TYPE_PRECISION (TREE_TYPE (arg1))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
+ || (element_precision (TREE_TYPE (arg1))
+ == element_precision (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
{
tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
TREE_OPERAND (TREE_OPERAND (arg1, 0), 1));
return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
fold_convert_loc (loc, TREE_TYPE (arg0), tem),
build_zero_cst (TREE_TYPE (arg0)));
}
return NULL_TREE;
@@ -13315,32 +13315,32 @@ fold_ternary_loc (location_t loc, enum t
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
of B and C. Signed zeros prevent all of these transformations,
for reasons given above each one.
Also try swapping the arguments and inverting the conditional. */
if (COMPARISON_CLASS_P (arg0)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
arg1, TREE_OPERAND (arg0, 1))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
+ && !HONOR_SIGNED_ZEROS (element_mode (arg1)))
{
tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
if (tem)
return tem;
}
if (COMPARISON_CLASS_P (arg0)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
op2,
TREE_OPERAND (arg0, 1))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
+ && !HONOR_SIGNED_ZEROS (element_mode (op2)))
{
location_t loc0 = expr_location_or (arg0, loc);
tem = fold_invert_truthvalue (loc0, arg0);
if (tem && COMPARISON_CLASS_P (tem))
{
tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
if (tem)
return tem;
}
}
@@ -14827,21 +14827,21 @@ tree_call_nonnegative_warnv_p (tree type
CASE_INT_FN (BUILT_IN_POPCOUNT):
CASE_INT_FN (BUILT_IN_CLZ):
CASE_INT_FN (BUILT_IN_CLRSB):
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
/* Always true. */
return true;
CASE_FLT_FN (BUILT_IN_SQRT):
/* sqrt(-0.0) is -0.0. */
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ if (!HONOR_SIGNED_ZEROS (element_mode (type)))
return true;
return tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_ASINH):
CASE_FLT_FN (BUILT_IN_ATAN):
CASE_FLT_FN (BUILT_IN_ATANH):
CASE_FLT_FN (BUILT_IN_CBRT):
CASE_FLT_FN (BUILT_IN_CEIL):
CASE_FLT_FN (BUILT_IN_ERF):
@@ -16093,21 +16093,21 @@ fold_strip_sign_ops (tree exp)
switch (TREE_CODE (exp))
{
case ABS_EXPR:
case NEGATE_EXPR:
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
return arg0 ? arg0 : TREE_OPERAND (exp, 0);
case MULT_EXPR:
case RDIV_EXPR:
- if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp))))
+ if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (exp)))
return NULL_TREE;
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
if (arg0 != NULL_TREE || arg1 != NULL_TREE)
return fold_build2_loc (loc, TREE_CODE (exp), TREE_TYPE (exp),
arg0 ? arg0 : TREE_OPERAND (exp, 0),
arg1 ? arg1 : TREE_OPERAND (exp, 1));
break;
case COMPOUND_EXPR:
Index: gcc/match.pd
===================================================================
--- gcc/match.pd (revision 217614)
+++ gcc/match.pd (working copy)
@@ -19,21 +19,21 @@ FITNESS FOR A PARTICULAR PURPOSE. See t
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* Generic tree predicates we inherit. */
(define_predicates
integer_onep integer_zerop integer_all_onesp integer_minus_onep
- integer_each_onep
+ integer_each_onep integer_truep
real_zerop real_onep real_minus_onep
CONSTANT_CLASS_P
tree_expr_nonnegative_p)
/* Operator lists. */
(define_operator_list tcc_comparison
lt le eq ne ge gt unordered ordered unlt unle ungt unge uneq ltgt)
(define_operator_list inverted_tcc_comparison
ge gt ne eq lt le ordered unordered ge gt le lt ltgt uneq)
(define_operator_list inverted_tcc_comparison_with_nans
@@ -66,102 +66,104 @@ along with GCC; see the file COPYING3.
(if (fold_real_zero_addition_p (type, @1, 1))
(non_lvalue @0)))
/* Simplify x - x.
This is unsafe for certain floats even in non-IEEE formats.
In IEEE, it is unsafe because it does wrong for NaNs.
Also note that operand_equal_p is always false if an operand
is volatile. */
(simplify
(minus @0 @0)
- (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
+ (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (element_mode (type)))
{ build_zero_cst (type); }))
(simplify
(mult @0 integer_zerop@1)
@1)
/* Maybe fold x * 0 to 0. The expressions aren't the same
when x is NaN, since x * 0 is also NaN. Nor are they the
same in modes with signed zeros, since multiplying a
negative value by 0 gives -0, not +0. */
(simplify
(mult @0 real_zerop@1)
- (if (!HONOR_NANS (TYPE_MODE (type))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ (if (!HONOR_NANS (element_mode (type))
+ && !HONOR_SIGNED_ZEROS (element_mode (type)))
@1))
/* In IEEE floating point, x*1 is not equivalent to x for snans.
Likewise for complex arithmetic with signed zeros. */
(simplify
(mult @0 real_onep)
- (if (!HONOR_SNANS (TYPE_MODE (type))
- && (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ (if (!HONOR_SNANS (element_mode (type))
+ && (!HONOR_SIGNED_ZEROS (element_mode (type))
|| !COMPLEX_FLOAT_TYPE_P (type)))
(non_lvalue @0)))
/* Transform x * -1.0 into -x. */
(simplify
(mult @0 real_minus_onep)
- (if (!HONOR_SNANS (TYPE_MODE (type))
- && (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ (if (!HONOR_SNANS (element_mode (type))
+ && (!HONOR_SIGNED_ZEROS (element_mode (type))
|| !COMPLEX_FLOAT_TYPE_P (type)))
(negate @0)))
/* Make sure to preserve divisions by zero. This is the reason why
we don't simplify x / x to 1 or 0 / x to 0. */
(for op (mult trunc_div ceil_div floor_div round_div exact_div)
(simplify
(op @0 integer_onep)
(non_lvalue @0)))
/* X / -1 is -X. */
(for div (trunc_div ceil_div floor_div round_div exact_div)
(simplify
- (div @0 INTEGER_CST@1)
- (if (!TYPE_UNSIGNED (type)
- && wi::eq_p (@1, -1))
+ (div @0 integer_minus_onep@1)
+ (if (!TYPE_UNSIGNED (type))
(negate @0))))
/* For unsigned integral types, FLOOR_DIV_EXPR is the same as
TRUNC_DIV_EXPR. Rewrite into the latter in this case. */
(simplify
(floor_div @0 @1)
- (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
+ (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ && TYPE_UNSIGNED (type))
(trunc_div @0 @1)))
/* Optimize A / A to 1.0 if we don't care about
- NaNs or Infinities. Skip the transformation
- for non-real operands. */
+ NaNs or Infinities. */
(simplify
(rdiv @0 @0)
- (if (SCALAR_FLOAT_TYPE_P (type)
- && ! HONOR_NANS (TYPE_MODE (type))
- && ! HONOR_INFINITIES (TYPE_MODE (type)))
- { build_real (type, dconst1); })
- /* The complex version of the above A / A optimization. */
- (if (COMPLEX_FLOAT_TYPE_P (type)
- && ! HONOR_NANS (TYPE_MODE (TREE_TYPE (type)))
- && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
- { build_complex (type, build_real (TREE_TYPE (type), dconst1),
- build_real (TREE_TYPE (type), dconst0)); }))
+ (if (FLOAT_TYPE_P (type)
+ && ! HONOR_NANS (element_mode (type))
+ && ! HONOR_INFINITIES (element_mode (type)))
+ { build_one_cst (type); }))
+
+/* Optimize -A / A to -1.0 if we don't care about
+ NaNs or Infinities. */
+(simplify
+ (rdiv:c @0 (negate @0))
+ (if (FLOAT_TYPE_P (type)
+ && ! HONOR_NANS (element_mode (type))
+ && ! HONOR_INFINITIES (element_mode (type)))
+ { build_minus_one_cst (type); }))
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
(simplify
(rdiv @0 real_onep)
- (if (!HONOR_SNANS (TYPE_MODE (type)))
+ (if (!HONOR_SNANS (element_mode (type)))
(non_lvalue @0)))
/* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
(simplify
(rdiv @0 real_minus_onep)
- (if (!HONOR_SNANS (TYPE_MODE (type)))
+ (if (!HONOR_SNANS (element_mode (type)))
(negate @0)))
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
so only do this if -freciprocal-math. We can actually
always safely do it if ARG1 is a power of two, but it's hard to
tell if it is or not in a portable manner. */
(for cst (REAL_CST COMPLEX_CST VECTOR_CST)
(simplify
(rdiv @0 cst@1)
@@ -184,23 +186,22 @@ along with GCC; see the file COPYING3.
(mod integer_zerop@0 @1)
/* But not for 0 % 0 so that we can get the proper warnings and errors. */
(if (!integer_zerop (@1))
@0))
/* X % 1 is always zero. */
(simplify
(mod @0 integer_onep)
{ build_zero_cst (type); })
/* X % -1 is zero. */
(simplify
- (mod @0 INTEGER_CST@1)
- (if (!TYPE_UNSIGNED (type)
- && wi::eq_p (@1, -1))
+ (mod @0 integer_minus_onep@1)
+ (if (!TYPE_UNSIGNED (type))
{ build_zero_cst (type); })))
/* X % -C is the same as X % C. */
(simplify
(trunc_mod @0 INTEGER_CST@1)
(if (TYPE_SIGN (type) == SIGNED
&& !TREE_OVERFLOW (@1)
&& wi::neg_p (@1)
&& !TYPE_OVERFLOW_TRAPS (type)
/* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
@@ -301,28 +302,25 @@ along with GCC; see the file COPYING3.
(if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
(for op (tcc_comparison truth_and truth_andif truth_or truth_orif truth_xor)
(match truth_valued_p
(op @0 @1)))
(match truth_valued_p
(truth_not @0))
(match (logical_inverted_value @0)
(bit_not truth_valued_p@0))
(match (logical_inverted_value @0)
- (eq @0 integer_zerop)
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
+ (eq @0 integer_zerop))
(match (logical_inverted_value @0)
- (ne truth_valued_p@0 integer_onep)
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
+ (ne truth_valued_p@0 integer_truep))
(match (logical_inverted_value @0)
- (bit_xor truth_valued_p@0 integer_onep)
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
+ (bit_xor truth_valued_p@0 integer_truep))
/* X & !X -> 0. */
(simplify
(bit_and:c @0 (logical_inverted_value @0))
{ build_zero_cst (type); })
/* X | !X and X ^ !X -> 1, , if X is truth-valued. */
(for op (bit_ior bit_xor)
(simplify
(op:c truth_valued_p@0 (logical_inverted_value @0))
{ constant_boolean_node (true, type); }))
@@ -485,21 +483,21 @@ along with GCC; see the file COPYING3.
/* ~A + 1 -> -A */
(simplify
(plus (bit_not @0) integer_each_onep)
(negate @0))
/* (T)(P + A) - (T)P -> (T) A */
(for add (plus pointer_plus)
(simplify
(minus (convert (add @0 @1))
(convert @0))
- (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
/* For integer types, if A has a smaller type
than T the result depends on the possible
overflow in P + A.
E.g. T=size_t, A=(unsigned)429497295, P>0.
However, if an overflow in P + A would cause
undefined behavior, we can assume that there
is no overflow. */
|| (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
/* For pointer types, if the conversion of A to the
@@ -618,33 +616,33 @@ along with GCC; see the file COPYING3.
(for icvt (convert float)
(simplify
(ocvt (icvt@1 @0))
(with
{
tree inside_type = TREE_TYPE (@0);
tree inter_type = TREE_TYPE (@1);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type);
- int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
+ int inside_vec = VECTOR_TYPE_P (inside_type);
unsigned int inside_prec = TYPE_PRECISION (inside_type);
int inside_unsignedp = TYPE_UNSIGNED (inside_type);
int inter_int = INTEGRAL_TYPE_P (inter_type);
int inter_ptr = POINTER_TYPE_P (inter_type);
int inter_float = FLOAT_TYPE_P (inter_type);
- int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
+ int inter_vec = VECTOR_TYPE_P (inter_type);
unsigned int inter_prec = TYPE_PRECISION (inter_type);
int inter_unsignedp = TYPE_UNSIGNED (inter_type);
int final_int = INTEGRAL_TYPE_P (type);
int final_ptr = POINTER_TYPE_P (type);
int final_float = FLOAT_TYPE_P (type);
- int final_vec = TREE_CODE (type) == VECTOR_TYPE;
+ int final_vec = VECTOR_TYPE_P (type);
unsigned int final_prec = TYPE_PRECISION (type);
int final_unsignedp = TYPE_UNSIGNED (type);
}
/* In addition to the cases of two conversions in a row
handled below, if we are converting something to its own
type via an object of identical or wider precision, neither
conversion is needed. */
(if (((GIMPLE && useless_type_conversion_p (type, inside_type))
|| (GENERIC
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
@@ -658,22 +656,22 @@ along with GCC; see the file COPYING3.
former is wider than the latter and doesn't change the signedness
(for integers). Avoid this if the final type is a pointer since
then we sometimes need the middle conversion. Likewise if the
final type has a precision not equal to the size of its mode. */
(if (((inter_int && inside_int)
|| (inter_float && inside_float)
|| (inter_vec && inside_vec))
&& inter_prec >= inside_prec
&& (inter_float || inter_vec
|| inter_unsignedp == inside_unsignedp)
- && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type))
+ && ! (final_prec != element_precision (type)
+ && element_mode (type) == element_mode (inter_type))
&& ! final_ptr
&& (! final_vec || inter_prec == inside_prec))
(ocvt @0))
/* If we have a sign-extension of a zero-extended value, we can
replace that by a single zero-extension. Likewise if the
final conversion does not change precision we can drop the
intermediate conversion. */
(if (inside_int && inter_int && final_int
&& ((inside_prec < inter_prec && inter_prec < final_prec
@@ -837,26 +835,26 @@ along with GCC; see the file COPYING3.
(simplify
(cnd @0 (cnd @0 @1 @2) @3)
(cnd @0 @1 @3))
(simplify
(cnd @0 @1 (cnd @0 @2 @3))
(cnd @0 @1 @3))
/* A ? B : B -> B. */
(simplify
(cnd @0 @1 @1)
- @1))
+ @1)
-/* !A ? B : C -> A ? C : B. */
-(simplify
- (cond (logical_inverted_value truth_valued_p@0) @1 @2)
- (cond @0 @2 @1))
+ /* !A ? B : C -> A ? C : B. */
+ (simplify
+ (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
+ (cnd @0 @2 @1)))
/* Simplifications of comparisons. */
/* We can simplify a logical negation of a comparison to the
inverted comparison. As we cannot compute an expression
operator using invert_tree_comparison we have to simulate
that with expression code iteration. */
(for cmp (tcc_comparison)
icmp (inverted_tcc_comparison)
@@ -868,24 +866,23 @@ along with GCC; see the file COPYING3.
For now implement what forward_propagate_comparison did. */
(simplify
(bit_not (cmp @0 @1))
(if (VECTOR_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))
/* Comparison inversion may be impossible for trapping math,
invert_tree_comparison will tell us. But we can't use
a computed operator in the replacement tree thus we have
to play the trick below. */
(with { enum tree_code ic = invert_tree_comparison
- (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
+ (cmp, HONOR_NANS (element_mode (@0))); }
(if (ic == icmp)
(icmp @0 @1))
(if (ic == ncmp)
(ncmp @0 @1)))))
(simplify
- (bit_xor (cmp @0 @1) integer_onep)
- (if (INTEGRAL_TYPE_P (type))
- (with { enum tree_code ic = invert_tree_comparison
- (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
- (if (ic == icmp)
- (icmp @0 @1))
- (if (ic == ncmp)
- (ncmp @0 @1))))))
+ (bit_xor (cmp @0 @1) integer_truep)
+ (with { enum tree_code ic = invert_tree_comparison
+ (cmp, HONOR_NANS (element_mode (@0))); }
+ (if (ic == icmp)
+ (icmp @0 @1))
+ (if (ic == ncmp)
+ (ncmp @0 @1)))))
Index: gcc/tree.c
===================================================================
--- gcc/tree.c (revision 217614)
+++ gcc/tree.c (working copy)
@@ -2268,20 +2268,34 @@ integer_nonzerop (const_tree expr)
{
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == INTEGER_CST
&& !wi::eq_p (expr, 0))
|| (TREE_CODE (expr) == COMPLEX_CST
&& (integer_nonzerop (TREE_REALPART (expr))
|| integer_nonzerop (TREE_IMAGPART (expr)))));
}
+/* Return 1 if EXPR is the integer constant one. For vector,
+ return 1 if every piece is the integer constant minus one
+ (representing the value TRUE). */
+
+int
+integer_truep (const_tree expr)
+{
+ STRIP_NOPS (expr);
+
+ if (TREE_CODE (expr) == VECTOR_CST)
+ return integer_all_onesp (expr);
+ return integer_onep (expr);
+}
+
/* Return 1 if EXPR is the fixed-point constant zero. */
int
fixed_zerop (const_tree expr)
{
return (TREE_CODE (expr) == FIXED_CST
&& TREE_FIXED_CST (expr).data.is_zero ());
}
/* Return the power of two represented by a tree node known to be a
@@ -12297,11 +12311,21 @@ get_base_address (tree t)
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
/* ??? Either the alias oracle or all callers need to properly deal
with WITH_SIZE_EXPRs before we can look through those. */
if (TREE_CODE (t) == WITH_SIZE_EXPR)
return NULL_TREE;
return t;
}
+machine_mode
+element_mode (const_tree t)
+{
+ if (!TYPE_P (t))
+ t = TREE_TYPE (t);
+ if (VECTOR_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)
+ t = TREE_TYPE (t);
+ return TYPE_MODE (t);
+}
+
#include "gt-tree.h"
Index: gcc/tree.h
===================================================================
--- gcc/tree.h (revision 217614)
+++ gcc/tree.h (working copy)
@@ -1557,20 +1557,22 @@ extern void protected_set_expr_location
#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.next_variant)
#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.main_variant)
#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type_common.context)
#define TYPE_MODE(NODE) \
(VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
? vector_type_mode (NODE) : (NODE)->type_common.mode)
#define SET_TYPE_MODE(NODE, MODE) \
(TYPE_CHECK (NODE)->type_common.mode = (MODE))
+extern machine_mode element_mode (const_tree t);
+
/* The "canonical" type for this type node, which is used by frontends to
compare the type for equality with another type. If two types are
equal (based on the semantics of the language), then they will have
equivalent TYPE_CANONICAL entries.
As a special case, if TYPE_CANONICAL is NULL_TREE, and thus
TYPE_STRUCTURAL_EQUALITY_P is true, then it cannot
be used for comparison against other types. Instead, the type is
said to require structural equality checks, described in
TYPE_STRUCTURAL_EQUALITY_P.
@@ -3992,20 +3994,25 @@ extern int integer_minus_onep (const_tre
/* integer_pow2p (tree x) is nonzero is X is an integer constant with
exactly one bit 1. */
extern int integer_pow2p (const_tree);
/* integer_nonzerop (tree x) is nonzero if X is an integer constant
with a nonzero value. */
extern int integer_nonzerop (const_tree);
+/* integer_truep (tree x) is nonzero if X is an integer constant of value 1 or
+ a vector where each element is an integer constant of value -1. */
+
+extern int integer_truep (const_tree);
+
extern bool cst_and_fits_in_hwi (const_tree);
extern tree num_ending_zeros (const_tree);
/* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
value 0. */
extern int fixed_zerop (const_tree);
/* staticp (tree x) is nonzero if X is a reference to data allocated
at a fixed address in memory. Returns the outermost data. */