summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/fold-const.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
committerobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
commitc8f5fc7032940ad6633f932ac40cade82ec4d0cc (patch)
tree29a0f0a6c79a69ecc64f612947a0fe5904311713 /contrib/gcc/fold-const.c
parentc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (diff)
downloadFreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.zip
FreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.tar.gz
Gcc 3.1.0 pre-release from the FSF anoncvs repo on 9-May-2002 15:57:15 EDT.
Diffstat (limited to 'contrib/gcc/fold-const.c')
-rw-r--r--contrib/gcc/fold-const.c142
1 files changed, 113 insertions, 29 deletions
diff --git a/contrib/gcc/fold-const.c b/contrib/gcc/fold-const.c
index 2f0d4ace..2169998 100644
--- a/contrib/gcc/fold-const.c
+++ b/contrib/gcc/fold-const.c
@@ -64,7 +64,7 @@ static void exact_real_inverse_1 PARAMS ((PTR));
#endif
static tree negate_expr PARAMS ((tree));
static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
- int));
+ tree *, int));
static tree associate_trees PARAMS ((tree, tree, enum tree_code, tree));
static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int));
static void const_binop_1 PARAMS ((PTR));
@@ -109,10 +109,6 @@ static int count_cond PARAMS ((tree, int));
static tree fold_binary_op_with_conditional_arg
PARAMS ((enum tree_code, tree, tree, tree, int));
-#ifndef BRANCH_COST
-#define BRANCH_COST 1
-#endif
-
#if defined(HOST_EBCDIC)
/* bit 8 is significant in EBCDIC */
#define CHARMASK 0xff
@@ -1389,13 +1385,16 @@ negate_expr (t)
combined with CODE to make IN. "constant" means an expression with
TREE_CONSTANT but that isn't an actual constant. CODE must be a
commutative arithmetic operation. Store the constant part into *CONP,
- the literal in &LITP and return the variable part. If a part isn't
+ the literal in *LITP and return the variable part. If a part isn't
present, set it to null. If the tree does not decompose in this way,
return the entire tree as the variable part and the other parts as null.
If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR. In that
- case, we negate an operand that was subtracted. If NEGATE_P is true, we
- are negating all of IN.
+ case, we negate an operand that was subtracted. Except if it is a
+ literal for which we use *MINUS_LITP instead.
+
+ If NEGATE_P is true, we are negating all of IN, again except a literal
+ for which we use *MINUS_LITP instead.
If IN is itself a literal or constant, return it as appropriate.
@@ -1403,16 +1402,17 @@ negate_expr (t)
same type as IN, but they will have the same signedness and mode. */
static tree
-split_tree (in, code, conp, litp, negate_p)
+split_tree (in, code, conp, litp, minus_litp, negate_p)
tree in;
enum tree_code code;
- tree *conp, *litp;
+ tree *conp, *litp, *minus_litp;
int negate_p;
{
tree var = 0;
*conp = 0;
*litp = 0;
+ *minus_litp = 0;
/* Strip any conversions that don't change the machine mode or signedness. */
STRIP_SIGN_NOPS (in);
@@ -1454,9 +1454,12 @@ split_tree (in, code, conp, litp, negate_p)
var = op1, neg_var_p = neg1_p;
/* Now do any needed negations. */
- if (neg_litp_p) *litp = negate_expr (*litp);
- if (neg_conp_p) *conp = negate_expr (*conp);
- if (neg_var_p) var = negate_expr (var);
+ if (neg_litp_p)
+ *minus_litp = *litp, *litp = 0;
+ if (neg_conp_p)
+ *conp = negate_expr (*conp);
+ if (neg_var_p)
+ var = negate_expr (var);
}
else if (TREE_CONSTANT (in))
*conp = in;
@@ -1465,9 +1468,12 @@ split_tree (in, code, conp, litp, negate_p)
if (negate_p)
{
- var = negate_expr (var);
+ if (*litp)
+ *minus_litp = *litp, *litp = 0;
+ else if (*minus_litp)
+ *litp = *minus_litp, *minus_litp = 0;
*conp = negate_expr (*conp);
- *litp = negate_expr (*litp);
+ var = negate_expr (var);
}
return var;
@@ -1475,9 +1481,7 @@ split_tree (in, code, conp, litp, negate_p)
/* Re-associate trees split by the above function. T1 and T2 are either
expressions to associate or null. Return the new expression, if any. If
- we build an operation, do it in TYPE and with CODE, except if CODE is a
- MINUS_EXPR, in which case we use PLUS_EXPR since split_tree will already
- have taken care of the negations. */
+ we build an operation, do it in TYPE and with CODE. */
static tree
associate_trees (t1, t2, code, type)
@@ -1490,9 +1494,6 @@ associate_trees (t1, t2, code, type)
else if (t2 == 0)
return t1;
- if (code == MINUS_EXPR)
- code = PLUS_EXPR;
-
/* If either input is CODE, a PLUS_EXPR, or a MINUS_EXPR, don't
try to fold this since we will have infinite recursion. But do
deal with any NEGATE_EXPRs. */
@@ -2427,6 +2428,27 @@ operand_equal_p (arg0, arg1, only_const)
&& REAL_VALUES_IDENTICAL (TREE_REAL_CST (arg0),
TREE_REAL_CST (arg1)));
+ case VECTOR_CST:
+ {
+ tree v1, v2;
+
+ if (TREE_CONSTANT_OVERFLOW (arg0)
+ || TREE_CONSTANT_OVERFLOW (arg1))
+ return 0;
+
+ v1 = TREE_VECTOR_CST_ELTS (arg0);
+ v2 = TREE_VECTOR_CST_ELTS (arg1);
+ while (v1 && v2)
+ {
+ if (!operand_equal_p (v1, v2, only_const))
+ return 0;
+ v1 = TREE_CHAIN (v1);
+ v2 = TREE_CHAIN (v2);
+ }
+
+ return 1;
+ }
+
case COMPLEX_CST:
return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
only_const)
@@ -4442,8 +4464,8 @@ optimize_minmax_comparison (t)
other operations already in T. WIDE_TYPE, if non-null, is a type that
should be used for the computation if wider than our type.
- For example, if we are dividing (X * 8) + (Y + 16) by 4, we can return
- (X * 2) + (Y + 4). We must, however, be assured that either the original
+ For example, if we are dividing (X * 8) + (Y * 16) by 4, we can return
+ (X * 2) + (Y * 4). We must, however, be assured that either the original
expression would not overflow or that overflow is undefined for the type
in the language in question.
@@ -5184,6 +5206,7 @@ fold (expr)
{
case INTEGER_CST:
case REAL_CST:
+ case VECTOR_CST:
case STRING_CST:
case COMPLEX_CST:
case CONSTRUCTOR:
@@ -5658,24 +5681,68 @@ fold (expr)
&& (! FLOAT_TYPE_P (type)
|| (flag_unsafe_math_optimizations && code == MULT_EXPR)))
{
- tree var0, con0, lit0, var1, con1, lit1;
+ tree var0, con0, lit0, minus_lit0;
+ tree var1, con1, lit1, minus_lit1;
/* Split both trees into variables, constants, and literals. Then
associate each group together, the constants with literals,
then the result with variables. This increases the chances of
literals being recombined later and of generating relocatable
expressions for the sum of a constant and literal. */
- var0 = split_tree (arg0, code, &con0, &lit0, 0);
- var1 = split_tree (arg1, code, &con1, &lit1, code == MINUS_EXPR);
+ var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
+ var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
+ code == MINUS_EXPR);
/* Only do something if we found more than two objects. Otherwise,
nothing has changed and we risk infinite recursion. */
- if (2 < ((var0 != 0) + (var1 != 0) + (con0 != 0) + (con1 != 0)
- + (lit0 != 0) + (lit1 != 0)))
+ if (2 < ((var0 != 0) + (var1 != 0)
+ + (con0 != 0) + (con1 != 0)
+ + (lit0 != 0) + (lit1 != 0)
+ + (minus_lit0 != 0) + (minus_lit1 != 0)))
{
+ /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
+ if (code == MINUS_EXPR)
+ code = PLUS_EXPR;
+
var0 = associate_trees (var0, var1, code, type);
con0 = associate_trees (con0, con1, code, type);
lit0 = associate_trees (lit0, lit1, code, type);
+ minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
+
+ /* Preserve the MINUS_EXPR if the negative part of the literal is
+ greater than the positive part. Otherwise, the multiplicative
+ folding code (i.e extract_muldiv) may be fooled in case
+ unsigned constants are substracted, like in the following
+ example: ((X*2 + 4) - 8U)/2. */
+ if (minus_lit0 && lit0)
+ {
+ if (tree_int_cst_lt (lit0, minus_lit0))
+ {
+ minus_lit0 = associate_trees (minus_lit0, lit0,
+ MINUS_EXPR, type);
+ lit0 = 0;
+ }
+ else
+ {
+ lit0 = associate_trees (lit0, minus_lit0,
+ MINUS_EXPR, type);
+ minus_lit0 = 0;
+ }
+ }
+ if (minus_lit0)
+ {
+ if (con0 == 0)
+ return convert (type, associate_trees (var0, minus_lit0,
+ MINUS_EXPR, type));
+ else
+ {
+ con0 = associate_trees (con0, minus_lit0,
+ MINUS_EXPR, type);
+ return convert (type, associate_trees (var0, con0,
+ PLUS_EXPR, type));
+ }
+ }
+
con0 = associate_trees (con0, lit0, code, type);
return convert (type, associate_trees (var0, con0, code, type));
}
@@ -7090,7 +7157,7 @@ fold (expr)
STRIP_NOPS (arg2);
- /* If we have A op 0 ? A : -A, this is A, -A, abs (A), or abs (-A),
+ /* If we have A op 0 ? A : -A, this is A, -A, abs (A), or -abs (A),
depending on the comparison operation. */
if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
? real_zerop (TREE_OPERAND (arg0, 1))
@@ -7586,6 +7653,23 @@ rtl_expr_nonnegative_p (r)
return CONST_DOUBLE_HIGH (r) >= 0;
return 0;
+ case CONST_VECTOR:
+ {
+ int units, i;
+ rtx elt;
+
+ units = CONST_VECTOR_NUNITS (r);
+
+ for (i = 0; i < units; ++i)
+ {
+ elt = CONST_VECTOR_ELT (r, i);
+ if (!rtl_expr_nonnegative_p (elt))
+ return 0;
+ }
+
+ return 1;
+ }
+
case SYMBOL_REF:
case LABEL_REF:
/* These are always nonnegative. */
OpenPOWER on IntegriCloud