/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "flags.h"
#include "tree.h"
#include "real.h"
static tree fold_convert PARAMS ((tree, tree));
static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
+static int comparison_to_compcode PARAMS ((enum tree_code));
+static enum tree_code compcode_to_comparison PARAMS ((int));
static int truth_value_p PARAMS ((enum tree_code));
static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
PARAMS ((enum tree_code, tree, tree, tree, int));
static bool fold_real_zero_addition_p PARAMS ((tree, tree, int));
-#if defined(HOST_EBCDIC)
-/* bit 8 is significant in EBCDIC */
-#define CHARMASK 0xff
-#else
-#define CHARMASK 0x7f
-#endif
+/* The following constants represent a bit based encoding of GCC's
+ comparison operators. This encoding simplifies transformations
+ on relational comparison operators, such as AND and OR. */
+#define COMPCODE_FALSE 0
+#define COMPCODE_LT 1
+#define COMPCODE_EQ 2
+#define COMPCODE_LE 3
+#define COMPCODE_GT 4
+#define COMPCODE_NE 5
+#define COMPCODE_GE 6
+#define COMPCODE_TRUE 7
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is
nonzero, a signed overflow has already occurred in calculating T, so
- propagate it.
-
- Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
- if it exists. */
+ propagate it. */
int
force_fit_type (t, overflow)
if (TREE_CODE (t) == REAL_CST)
{
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
- overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
return overflow;
}
int num_hi_sig, den_hi_sig;
unsigned HOST_WIDE_INT quo_est, scale;
- /* Find the highest non-zero divisor digit. */
+ /* Find the highest nonzero divisor digit. */
for (i = 4 - 1;; i--)
if (den[i] != 0)
{
if (TREE_CODE (t1) == code || TREE_CODE (t2) == code
|| TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR)
{
- if (TREE_CODE (t1) == NEGATE_EXPR)
- return build (MINUS_EXPR, type, convert (type, t2),
- convert (type, TREE_OPERAND (t1, 0)));
- else if (TREE_CODE (t2) == NEGATE_EXPR)
- return build (MINUS_EXPR, type, convert (type, t1),
- convert (type, TREE_OPERAND (t2, 0)));
- else
- return build (code, type, convert (type, t1), convert (type, t2));
+ if (code == PLUS_EXPR)
+ {
+ if (TREE_CODE (t1) == NEGATE_EXPR)
+ return build (MINUS_EXPR, type, convert (type, t2),
+ convert (type, TREE_OPERAND (t1, 0)));
+ else if (TREE_CODE (t2) == NEGATE_EXPR)
+ return build (MINUS_EXPR, type, convert (type, t1),
+ convert (type, TREE_OPERAND (t2, 0)));
+ }
+ return build (code, type, convert (type, t1), convert (type, t2));
}
return fold (build (code, type, convert (type, t1), convert (type, t2)));
tree t = (tree) x;
return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
- ^ (hashval_t) ((long) TREE_TYPE (t) >> 3)
+ ^ htab_hash_pointer (TREE_TYPE (t))
^ (TREE_OVERFLOW (t) << 20));
}
-/* Return non-zero if the value represented by *X (an INTEGER_CST tree node)
+/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */
static int
}
}
+
+/* Convert a comparison tree code from an enum tree_code representation
+ into a compcode bit-based encoding. This function is the inverse of
+ compcode_to_comparison. */
+
+static int
+comparison_to_compcode (code)
+ enum tree_code code;
+{
+ switch (code)
+ {
+ case LT_EXPR:
+ return COMPCODE_LT;
+ case EQ_EXPR:
+ return COMPCODE_EQ;
+ case LE_EXPR:
+ return COMPCODE_LE;
+ case GT_EXPR:
+ return COMPCODE_GT;
+ case NE_EXPR:
+ return COMPCODE_NE;
+ case GE_EXPR:
+ return COMPCODE_GE;
+ default:
+ abort ();
+ }
+}
+
+/* Convert a compcode bit-based encoding of a comparison operator back
+ to GCC's enum tree_code representation. This function is the
+ inverse of comparison_to_compcode. */
+
+static enum tree_code
+compcode_to_comparison (code)
+ int code;
+{
+ switch (code)
+ {
+ case COMPCODE_LT:
+ return LT_EXPR;
+ case COMPCODE_EQ:
+ return EQ_EXPR;
+ case COMPCODE_LE:
+ return LE_EXPR;
+ case COMPCODE_GT:
+ return GT_EXPR;
+ case COMPCODE_NE:
+ return NE_EXPR;
+ case COMPCODE_GE:
+ return GE_EXPR;
+ default:
+ abort ();
+ }
+}
+
/* Return nonzero if CODE is a tree code that represents a truth value. */
static int
}
\f
/* Return nonzero if two operands are necessarily equal.
- If ONLY_CONST is non-zero, only return non-zero for constants.
+ If ONLY_CONST is nonzero, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
it does not test whether they are equal using C's == operation.
The distinction is important for IEEE floating point, because
/* See if ARG is an expression that is either a comparison or is performing
arithmetic on comparisons. The comparisons must only be comparing
two different values, which will be stored in *CVAL1 and *CVAL2; if
- they are non-zero it means that some operands have already been found.
+ they are nonzero it means that some operands have already been found.
No variables may be used anywhere else in the expression except in the
comparisons. If SAVE_P is true it means we removed a SAVE_EXPR around
the expression and save_expr needs to be called with CVAL1 and CVAL2.
}
\f
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
- starting at BITPOS. The field is unsigned if UNSIGNEDP is non-zero. */
+ starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
static tree
make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
return inner;
}
-/* Return non-zero if MASK represents a mask of SIZE ones in the low-order
+/* Return nonzero if MASK represents a mask of SIZE ones in the low-order
bit positions. */
static int
int width;
tree t;
- /* Tree EXP must have a integral type. */
+ /* Tree EXP must have an integral type. */
t = TREE_TYPE (exp);
if (! INTEGRAL_TYPE_P (t))
return NULL_TREE;
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
: TYPE_MAX_VALUE (type);
- high_positive = fold (build (RSHIFT_EXPR, type,
- convert (type, high_positive),
- convert (type, integer_one_node)));
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
+ high_positive = fold (build (RSHIFT_EXPR, type,
+ convert (type, high_positive),
+ convert (type, integer_one_node)));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
rl_arg = TREE_OPERAND (rhs, 0);
rr_arg = TREE_OPERAND (rhs, 1);
+ /* Simplify (x<y) && (x==y) into (x<=y) and related optimizations. */
+ if (simple_operand_p (ll_arg)
+ && simple_operand_p (lr_arg)
+ && !FLOAT_TYPE_P (TREE_TYPE (ll_arg)))
+ {
+ int compcode;
+
+ if (operand_equal_p (ll_arg, rl_arg, 0)
+ && operand_equal_p (lr_arg, rr_arg, 0))
+ {
+ int lcompcode, rcompcode;
+
+ lcompcode = comparison_to_compcode (lcode);
+ rcompcode = comparison_to_compcode (rcode);
+ compcode = (code == TRUTH_AND_EXPR)
+ ? lcompcode & rcompcode
+ : lcompcode | rcompcode;
+ }
+ else if (operand_equal_p (ll_arg, rr_arg, 0)
+ && operand_equal_p (lr_arg, rl_arg, 0))
+ {
+ int lcompcode, rcompcode;
+
+ rcode = swap_tree_comparison (rcode);
+ lcompcode = comparison_to_compcode (lcode);
+ rcompcode = comparison_to_compcode (rcode);
+ compcode = (code == TRUTH_AND_EXPR)
+ ? lcompcode & rcompcode
+ : lcompcode | rcompcode;
+ }
+ else
+ compcode = -1;
+
+ if (compcode == COMPCODE_TRUE)
+ return convert (truth_type, integer_one_node);
+ else if (compcode == COMPCODE_FALSE)
+ return convert (truth_type, integer_zero_node);
+ else if (compcode != -1)
+ return build (compcode_to_comparison (compcode),
+ truth_type, ll_arg, lr_arg);
+ }
+
/* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison
return 0;
}
+ /* After this point all optimizations will generate bit-field
+ references, which we might not want. */
+ if (! (*lang_hooks.can_use_bit_fields_p) ())
+ return 0;
+
/* See if we can find a mode that contains both fields being compared on
the left. If we can't, fail. Otherwise, update all constants and masks
to be relative to a field of that size. */
break;
case CONVERT_EXPR: case NON_LVALUE_EXPR: case NOP_EXPR:
- /* If op0 is an expression, and is unsigned, and the type is
- smaller than ctype, then we cannot widen the expression. */
+ /* If op0 is an expression ... */
if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
- && TREE_UNSIGNED (TREE_TYPE (op0))
- && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
- && (GET_MODE_SIZE (TYPE_MODE (ctype))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+ /* ... and is unsigned, and its type is smaller than ctype,
+ then we cannot pass through as widening. */
+ && ((TREE_UNSIGNED (TREE_TYPE (op0))
+ && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
+ && (GET_MODE_SIZE (TYPE_MODE (ctype))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+ /* ... or its type is larger than ctype,
+ then we cannot pass through this truncation. */
+ || (GET_MODE_SIZE (TYPE_MODE (ctype))
+ < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))))
break;
/* Pass the constant down and see if we can make a simplification. If
t2 = extract_muldiv (op1, c, code, wide_type);
if (t1 != 0 && t2 != 0
&& (code == MULT_EXPR
- /* If not multiplication, we can only do this if either operand
- is divisible by c. */
- || multiple_of_p (ctype, op0, c)
- || multiple_of_p (ctype, op1, c)))
+ /* If not multiplication, we can only do this if both operands
+ are divisible by c. */
+ || (multiple_of_p (ctype, op0, c)
+ && multiple_of_p (ctype, op1, c))))
return fold (build (tcode, ctype, convert (ctype, t1),
convert (ctype, t2)));
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
- expression, and ARG to `a'. If COND_FIRST_P is non-zero, then the
+ expression, and ARG to `a'. If COND_FIRST_P is nonzero, then the
COND is the first argument to CODE; otherwise (as in the example
given here), it is the second argument. TYPE is the type of the
original expression. */
/* And these are the types of the expressions. */
tree lhs_type = type;
tree rhs_type = type;
+ int save = 0;
if (cond_first_p)
{
we simply build `a, throw 3'. */
if (VOID_TYPE_P (TREE_TYPE (true_value)))
{
- lhs_code = COMPOUND_EXPR;
- if (!cond_first_p)
- lhs_type = void_type_node;
+ if (! cond_first_p)
+ {
+ lhs_code = COMPOUND_EXPR;
+ lhs_type = void_type_node;
+ }
+ else
+ lhs = true_value;
}
if (VOID_TYPE_P (TREE_TYPE (false_value)))
{
- rhs_code = COMPOUND_EXPR;
- if (!cond_first_p)
- rhs_type = void_type_node;
+ if (! cond_first_p)
+ {
+ rhs_code = COMPOUND_EXPR;
+ rhs_type = void_type_node;
+ }
+ else
+ rhs = false_value;
}
}
else
if an arm is a COND_EXPR since we get exponential behavior
in that case. */
- if (TREE_CODE (arg) != SAVE_EXPR && ! TREE_CONSTANT (arg)
- && (*lang_hooks.decls.global_bindings_p) () == 0
- && ((TREE_CODE (arg) != VAR_DECL
- && TREE_CODE (arg) != PARM_DECL)
- || TREE_SIDE_EFFECTS (arg)))
+ if (TREE_CODE (arg) == SAVE_EXPR)
+ save = 1;
+ else if (lhs == 0 && rhs == 0
+ && !TREE_CONSTANT (arg)
+ && (*lang_hooks.decls.global_bindings_p) () == 0
+ && ((TREE_CODE (arg) != VAR_DECL && TREE_CODE (arg) != PARM_DECL)
+ || TREE_SIDE_EFFECTS (arg)))
{
if (TREE_CODE (true_value) != COND_EXPR)
lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
if ((lhs == 0 || ! TREE_CONSTANT (lhs))
&& (rhs == 0 || !TREE_CONSTANT (rhs)))
- arg = save_expr (arg), lhs = rhs = 0;
+ {
+ arg = save_expr (arg);
+ lhs = rhs = 0;
+ save = 1;
+ }
}
if (lhs == 0)
test = fold (build (COND_EXPR, type, test, lhs, rhs));
- if (TREE_CODE (arg) == SAVE_EXPR)
+ if (save)
return build (COMPOUND_EXPR, type,
convert (void_type_node, arg),
strip_compound_expr (test, arg));
TYPE, X + ADDEND is the same as X. If NEGATE, return true if X -
ADDEND is the same as X.
- X + 0 and X - 0 both give X when X is NaN, infinite, or non-zero
+ X + 0 and X - 0 both give X when X is NaN, infinite, or nonzero
and finite. The problematic cases are when X is zero, and its mode
has signed zeros. In the case of rounding towards -infinity,
X - 0 is not the same as X because 0 - 0 is -0. In other rounding
fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COND_EXPR)
{
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg02 = TREE_OPERAND (arg0, 2);
+ if (! VOID_TYPE_P (TREE_TYPE (arg01)))
+ arg01 = fold (build1 (code, type, arg01));
+ if (! VOID_TYPE_P (TREE_TYPE (arg02)))
+ arg02 = fold (build1 (code, type, arg02));
t = fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build1 (code, type, TREE_OPERAND (arg0, 1))),
- fold (build1 (code, type, TREE_OPERAND (arg0, 2)))));
+ arg01, arg02));
/* If this was a conversion, and all we did was to move into
inside the COND_EXPR, bring it back out. But leave it if
&& TREE_CODE (t) == COND_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) == code
&& TREE_CODE (TREE_OPERAND (t, 2)) == code
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 1))
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 2))
&& (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))
== TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0)))
&& ! (INTEGRAL_TYPE_P (TREE_TYPE (t))
else if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<')
{
- if (TREE_CODE (arg1) == COMPOUND_EXPR)
+ if (TREE_CODE (arg1) == COMPOUND_EXPR
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg1, 0))
+ && ! TREE_SIDE_EFFECTS (arg0))
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
fold (build (code, type,
arg0, TREE_OPERAND (arg1, 1))));
}
else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
+ else
+ {
+ /* fabs(sqrt(x)) = sqrt(x) and fabs(exp(x)) = exp(x). */
+ enum built_in_function fcode = builtin_mathfn_code (arg0);
+ if (fcode == BUILT_IN_SQRT
+ || fcode == BUILT_IN_SQRTF
+ || fcode == BUILT_IN_SQRTL
+ || fcode == BUILT_IN_EXP
+ || fcode == BUILT_IN_EXPF
+ || fcode == BUILT_IN_EXPL)
+ t = arg0;
+ }
return t;
case CONJ_EXPR:
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
- /* In IEEE floating point, x*1 is not equivalent to x for snans.
- However, ANSI says we can drop signals,
- so we can do this anyway. */
- if (real_onep (arg1))
+ /* In IEEE floating point, x*1 is not equivalent to x for snans. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_onep (arg1))
return non_lvalue (convert (type, arg0));
- /* Transform x * -1.0 into -x. This should be safe for NaNs,
- signed zeros and signed infinities, but is currently
- restricted to "unsafe math optimizations" just in case. */
- if (flag_unsafe_math_optimizations
+ /* Transform x * -1.0 into -x. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_minus_onep (arg1))
return fold (build1 (NEGATE_EXPR, type, arg0));
tree arg = save_expr (arg0);
return build (PLUS_EXPR, type, arg, arg);
}
+
+ if (flag_unsafe_math_optimizations)
+ {
+ enum built_in_function fcode0 = builtin_mathfn_code (arg0);
+ enum built_in_function fcode1 = builtin_mathfn_code (arg1);
+
+ /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y). */
+ if ((fcode0 == BUILT_IN_SQRT && fcode1 == BUILT_IN_SQRT)
+ || (fcode0 == BUILT_IN_SQRTF && fcode1 == BUILT_IN_SQRTF)
+ || (fcode0 == BUILT_IN_SQRTL && fcode1 == BUILT_IN_SQRTL))
+ {
+ tree sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arg = build (MULT_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ return fold (build_function_call_expr (sqrtfn, arglist));
+ }
+
+ /* Optimize exp(x)*exp(y) as exp(x+y). */
+ if ((fcode0 == BUILT_IN_EXP && fcode1 == BUILT_IN_EXP)
+ || (fcode0 == BUILT_IN_EXPF && fcode1 == BUILT_IN_EXPF)
+ || (fcode0 == BUILT_IN_EXPL && fcode1 == BUILT_IN_EXPL))
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arg = build (PLUS_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ return fold (build_function_call_expr (expfn, arglist));
+ }
+ }
}
goto associate;
return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0)));
- /* In IEEE floating point, x/1 is not equivalent to x for snans.
- However, ANSI says we can drop signals, so we can do this anyway. */
- if (real_onep (arg1))
+ /* In IEEE floating point, x/1 is not equivalent to x for snans. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_onep (arg1))
return non_lvalue (convert (type, arg0));
/* If ARG1 is a constant, we can convert this to a multiply by the
TREE_OPERAND (arg1, 0)),
TREE_OPERAND (arg1, 1)));
}
+
+ /* Optimize x/exp(y) into x*exp(-y). */
+ if (flag_unsafe_math_optimizations)
+ {
+ enum built_in_function fcode = builtin_mathfn_code (arg1);
+ if (fcode == BUILT_IN_EXP
+ || fcode == BUILT_IN_EXPF
+ || fcode == BUILT_IN_EXPL)
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
+ tree arg = build1 (NEGATE_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ arg1 = build_function_call_expr (expfn, arglist);
+ return fold (build (MULT_EXPR, type, arg0, arg1));
+ }
+ }
goto binary;
case TRUNC_DIV_EXPR:
goto binary;
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
+ if (integer_all_onesp (arg0))
+ return omit_one_operand (type, arg0, arg1);
+ goto shift;
+
+ case RSHIFT_EXPR:
+ /* Optimize -1 >> x for arithmetic right shifts. */
+ if (integer_all_onesp (arg0) && ! TREE_UNSIGNED (type))
+ return omit_one_operand (type, arg0, arg1);
+ /* ... fall through ... */
+
+ case LSHIFT_EXPR:
+ shift:
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
+ if (integer_zerop (arg0))
+ return omit_one_operand (type, arg0, arg1);
+
/* Since negative shift count is not well-defined,
don't try to compute it in the compiler. */
if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0)
}
}
+ /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
+ This transformation affects the cases which are handled in later
+ optimizations involving comparisons with non-negative constants. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg0) != INTEGER_CST
+ && tree_int_cst_sgn (arg1) > 0)
+ {
+ switch (code)
+ {
+ case GE_EXPR:
+ code = GT_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+
+ case LT_EXPR:
+ code = LE_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
/* Comparisons with the highest or lowest possible integer of
- the specified size will have known values and an unsigned
- <= 0x7fffffff can be simplified. */
+ the specified size will have known values. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
+ unsigned HOST_WIDE_INT signed_max;
+ unsigned HOST_WIDE_INT max, min;
+
+ signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
+
+ if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+ {
+ max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+ min = 0;
+ }
+ else
+ {
+ max = signed_max;
+ min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ }
+
if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ && TREE_INT_CST_LOW (arg1) == max)
+ switch (code)
{
case GT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
-
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
+ code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
+ /* The GE_EXPR and LT_EXPR cases above are not normally
+ reached because of previous transformations. */
+
default:
break;
}
-
- else if (TREE_INT_CST_HIGH (arg1) == -1
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ else if (TREE_INT_CST_HIGH (arg1) == 0
+ && TREE_INT_CST_LOW (arg1) == max - 1)
+ switch (code)
+ {
+ case GT_EXPR:
+ code = EQ_EXPR;
+ arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ case LE_EXPR:
+ code = NE_EXPR;
+ arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ default:
+ break;
+ }
+ else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (arg1) == min)
+ switch (code)
{
case LT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
convert (type, integer_one_node),
arg0);
case GT_EXPR:
+ code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
+ else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (arg1) == min + 1)
+ switch (code)
+ {
+ case GE_EXPR:
+ code = NE_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ case LT_EXPR:
+ code = EQ_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ default:
+ break;
+ }
else if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
+ && TREE_INT_CST_LOW (arg1) == signed_max
&& TREE_UNSIGNED (TREE_TYPE (arg1))
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
- if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ if (code == LE_EXPR || code == GT_EXPR)
{
tree st0, st1;
st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
return fold
- (build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
+ (build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
type, convert (st0, arg0),
convert (st1, integer_zero_node)));
}
}
- else if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
- {
- case GT_EXPR:
- return omit_one_operand (type,
- convert (type, integer_zero_node),
- arg0);
- case GE_EXPR:
- TREE_SET_CODE (t, EQ_EXPR);
- break;
-
- case LE_EXPR:
- return omit_one_operand (type,
- convert (type, integer_one_node),
- arg0);
- case LT_EXPR:
- TREE_SET_CODE (t, NE_EXPR);
- break;
-
- default:
- break;
- }
}
}
- /* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive. */
- if (TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) != INTEGER_CST
- && tree_int_cst_sgn (arg1) > 0)
- {
- switch (TREE_CODE (t))
- {
- case GE_EXPR:
- code = GT_EXPR;
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
-
- case LT_EXPR:
- code = LE_EXPR;
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
-
- default:
- break;
- }
- }
-
- /* An unsigned comparison against 0 can be simplified. */
- if (integer_zerop (arg1)
- && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
- || POINTER_TYPE_P (TREE_TYPE (arg1)))
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
- {
- switch (TREE_CODE (t))
- {
- case GT_EXPR:
- code = NE_EXPR;
- TREE_SET_CODE (t, NE_EXPR);
- break;
- case LE_EXPR:
- code = EQ_EXPR;
- TREE_SET_CODE (t, EQ_EXPR);
- break;
- case GE_EXPR:
- return omit_one_operand (type,
- convert (type, integer_one_node),
- arg0);
- case LT_EXPR:
- return omit_one_operand (type,
- convert (type, integer_zero_node),
- arg0);
- default:
- break;
- }
- }
-
/* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
a MINUS_EXPR of a constant, we can convert it into a comparison with
a revised constant as long as no overflow occurs. */
}
/* If this is a comparison of a field, we may be able to simplify it. */
- if ((TREE_CODE (arg0) == COMPONENT_REF
+ if (((TREE_CODE (arg0) == COMPONENT_REF
+ && (*lang_hooks.can_use_bit_fields_p) ())
|| TREE_CODE (arg0) == BIT_FIELD_REF)
&& (code == EQ_EXPR || code == NE_EXPR)
/* Handle the constant case even without -O
/* Avoid adding NOP_EXPRs in case this is an lvalue. */
if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
- comp_type = type;
+ {
+ comp_type = type;
+ comp_op0 = arg1;
+ comp_op1 = arg2;
+ }
switch (comp_code)
{
&& type == TREE_TYPE (arg0))
return pedantic_non_lvalue (arg0);
+ /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
+ over COND_EXPR in cases such as floating point comparisons. */
+ if (integer_zerop (TREE_OPERAND (t, 1))
+ && integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0)))
+ return pedantic_non_lvalue (convert (type,
+ invert_truthvalue (arg0)));
+
/* Look for expressions of the form A & 2 ? 2 : 0. The result of this
operation is simply A & 2. */
arg1, 1))
return pedantic_non_lvalue (convert (type, TREE_OPERAND (arg0, 0)));
+ /* Convert A ? B : 0 into A && B if A and B are truth values. */
+ if (integer_zerop (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ return pedantic_non_lvalue (fold (build (TRUTH_ANDIF_EXPR, type,
+ arg0, arg1)));
+
+ /* Convert A ? B : 1 into !A || B if A and B are truth values. */
+ if (integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ {
+ /* Only perform transformation if ARG0 is easily inverted. */
+ tem = invert_truthvalue (arg0);
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return pedantic_non_lvalue (fold (build (TRUTH_ORIF_EXPR, type,
+ tem, arg1)));
+ }
+
return t;
case COMPOUND_EXPR: