fold-const.c (negate_expr, [...]): New.

* fold-const.c (negate_expr, associate_trees, extract_muldiv): New.
	(split_tree): Completely rework to make more general.
	(make_range, fold): Call negate_expr.
	(fold, case NEGATE_EXPR): Simplify -(a-b) is -ffast-math.
	(fold, associate): Call new split_tree and associate_trees.
	(fold, case MULT_EXPR, case *_{DIV,MOD}_EXPR): Call extract_muldiv.

From-SVN: r30673
This commit is contained in:
Richard Kenner 1999-11-27 13:50:13 +00:00 committed by Richard Kenner
parent a8b64d6cf4
commit 1baa375fea
2 changed files with 448 additions and 368 deletions

View File

@ -1,3 +1,12 @@
Sat Nov 27 08:38:26 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* fold-const.c (negate_expr, associate_trees, extract_muldiv): New.
(split_tree): Completely rework to make more general.
(make_range, fold): Call negate_expr.
(fold, case NEGATE_EXPR): Simplify -(a-b) is -ffast-math.
(fold, associate): Call new split_tree and associate_trees.
(fold, case MULT_EXPR, case *_{DIV,MOD}_EXPR): Call extract_muldiv.
1999-11-26 Bernd Schmidt <bernds@cygnus.co.uk>
* loop.c (try_copy_prop): Avoid GNU C extension.

View File

@ -61,8 +61,10 @@ int div_and_round_double PROTO((enum tree_code, int, HOST_WIDE_INT,
HOST_WIDE_INT, HOST_WIDE_INT *,
HOST_WIDE_INT *, HOST_WIDE_INT *,
HOST_WIDE_INT *));
static int split_tree PROTO((tree, enum tree_code, tree *,
tree *, int *));
static tree negate_expr PROTO((tree));
static tree split_tree PROTO((tree, enum tree_code, tree *, tree *,
int));
static tree associate_trees PROTO((tree, tree, enum tree_code, tree));
static tree int_const_binop PROTO((enum tree_code, tree, tree, int, int));
static tree const_binop PROTO((enum tree_code, tree, tree, int));
static tree fold_convert PROTO((tree, tree));
@ -93,6 +95,7 @@ static tree fold_range_test PROTO((tree));
static tree unextend PROTO((tree, int, int, tree));
static tree fold_truthop PROTO((enum tree_code, tree, tree, tree));
static tree optimize_minmax_comparison PROTO((tree));
static tree extract_muldiv PROTO((tree, tree, enum tree_code, tree));
static tree strip_compound_expr PROTO((tree, tree));
static int multiple_of_p PROTO((tree, tree, tree));
static tree constant_boolean_node PROTO((int, tree));
@ -1199,93 +1202,181 @@ real_hex_to_f (s, mode)
#endif /* no REAL_ARITHMETIC */
/* Split a tree IN into a constant and a variable part
that could be combined with CODE to make IN.
CODE must be a commutative arithmetic operation.
Store the constant part into *CONP and the variable in &VARP.
Return 1 if this was done; zero means the tree IN did not decompose
this way.
/* Given T, an expression, return the negation of T. Allow for T to be
null, in which case return null. */
If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR.
Therefore, we must tell the caller whether the variable part
was subtracted. We do this by storing 1 or -1 into *VARSIGNP.
The value stored is the coefficient for the variable term.
The constant term we return should always be added;
we negate it if necessary. */
static tree
negate_expr (t)
tree t;
{
tree type;
tree tem;
static int
split_tree (in, code, varp, conp, varsignp)
if (t == 0)
return 0;
type = TREE_TYPE (t);
STRIP_SIGN_NOPS (t);
switch (TREE_CODE (t))
{
case INTEGER_CST:
case REAL_CST:
if (! TREE_UNSIGNED (type)
&& 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
&& ! TREE_OVERFLOW (tem))
return tem;
break;
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
case MINUS_EXPR:
/* - (A - B) -> B - A */
if (! FLOAT_TYPE_P (type) || flag_fast_math)
return convert (type,
fold (build (MINUS_EXPR, TREE_TYPE (t),
TREE_OPERAND (t, 1),
TREE_OPERAND (t, 0))));
break;
default:
break;
}
return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (t), t));
}
/* Split a tree IN into a constant, literal and variable parts that could be
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
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.
If IN is itself a literal or constant, return it as appropriate.
Note that we do not guarantee that any of the three values will be the
same type as IN, but they will have the same signedness and mode. */
static tree
split_tree (in, code, conp, litp, negate_p)
tree in;
enum tree_code code;
tree *varp, *conp;
int *varsignp;
tree *conp, *litp;
int negate_p;
{
register tree outtype = TREE_TYPE (in);
*varp = 0;
tree orig_in = in;
tree type = TREE_TYPE (in);
tree var = 0;
*conp = 0;
*litp = 0;
/* Strip any conversions that don't change the machine mode. */
while ((TREE_CODE (in) == NOP_EXPR
|| TREE_CODE (in) == CONVERT_EXPR)
&& (TYPE_MODE (TREE_TYPE (in))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (in, 0)))))
in = TREE_OPERAND (in, 0);
/* Strip any conversions that don't change the machine mode or signedness. */
STRIP_SIGN_NOPS (in);
if (TREE_CODE (in) == code
|| (! FLOAT_TYPE_P (TREE_TYPE (in))
/* We can associate addition and subtraction together
(even though the C standard doesn't say so)
for integers because the value is not affected.
For reals, the value might be affected, so we can't. */
&& ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
|| (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))
if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST)
*litp = in;
else if (TREE_CONSTANT (in))
*conp = in;
else if (TREE_CODE (in) == code
|| (! FLOAT_TYPE_P (TREE_TYPE (in))
/* We can associate addition and subtraction together (even
though the C standard doesn't say so) for integers because
the value is not affected. For reals, the value might be
affected, so we can't. */
&& ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
|| (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))
{
enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0));
if (code == INTEGER_CST)
{
*conp = TREE_OPERAND (in, 0);
*varp = TREE_OPERAND (in, 1);
if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)
&& TREE_TYPE (*varp) != outtype)
*varp = convert (outtype, *varp);
*varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;
return 1;
}
if (TREE_CONSTANT (TREE_OPERAND (in, 1)))
{
*conp = TREE_OPERAND (in, 1);
*varp = TREE_OPERAND (in, 0);
*varsignp = 1;
if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)
&& TREE_TYPE (*varp) != outtype)
*varp = convert (outtype, *varp);
if (TREE_CODE (in) == MINUS_EXPR)
{
/* If operation is subtraction and constant is second,
must negate it to get an additive constant.
And this cannot be done unless it is a manifest constant.
It could also be the address of a static variable.
We cannot negate that, so give up. */
if (TREE_CODE (*conp) == INTEGER_CST)
/* Subtracting from integer_zero_node loses for long long. */
*conp = fold (build1 (NEGATE_EXPR, TREE_TYPE (*conp), *conp));
else
return 0;
}
return 1;
}
if (TREE_CONSTANT (TREE_OPERAND (in, 0)))
{
*conp = TREE_OPERAND (in, 0);
*varp = TREE_OPERAND (in, 1);
if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)
&& TREE_TYPE (*varp) != outtype)
*varp = convert (outtype, *varp);
*varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;
return 1;
}
tree op0 = TREE_OPERAND (in, 0);
tree op1 = TREE_OPERAND (in, 1);
int neg1_p = TREE_CODE (in) == MINUS_EXPR;
int neg_litp_p = 0, neg_conp_p = 0, neg_var_p = 0;
/* First see if either of the operands is a literal, then a constant. */
if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)
*litp = op0, op0 = 0;
else if (TREE_CODE (op1) == INTEGER_CST || TREE_CODE (op1) == REAL_CST)
*litp = op1, neg_litp_p = neg1_p, op1 = 0;
if (op0 != 0 && TREE_CONSTANT (op0))
*conp = op0, op0 = 0;
else if (op1 != 0 && TREE_CONSTANT (op1))
*conp = op1, neg_conp_p = neg1_p, op1 = 0;
/* If we haven't dealt with either operand, this is not a case we can
decompose. Otherwise, VAR is either of the ones remaining, if any. */
if (op0 != 0 && op1 != 0)
var = in;
else if (op0 != 0)
var = op0;
else
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);
}
return 0;
else
var = in;
if (negate_p)
{
var = negate_expr (var);
*conp = negate_expr (*conp);
*litp = negate_expr (*litp);
}
return var;
}
/* 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. */
static tree
associate_trees (t1, t2, code, type)
tree t1, t2;
enum tree_code code;
tree type;
{
tree tem;
if (t1 == 0)
return t2;
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. */
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));
}
return fold (build (code, type, convert (type, t1), convert (type, t2)));
}
/* Combine two integer constants ARG1 and ARG2 under operation CODE
@ -3249,7 +3340,7 @@ make_range (exp, pin_p, plow, phigh)
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
exp = build (MINUS_EXPR, type, build1 (NEGATE_EXPR, type, arg0),
exp = build (MINUS_EXPR, type, negate_expr (arg0),
convert (type, integer_one_node));
continue;
@ -4154,6 +4245,213 @@ optimize_minmax_comparison (t)
}
}
/* T is an integer expression that is being multiplied, divided, or taken a
modulus (CODE says which and what kind of divide or modulus) by a
constant C. See if we can eliminate that operation by folding it with
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 also canonicalize (X + 7) * 4 into X * 4 + 28
in the hope that either the machine has a multiply-accumulate insn
or that this is part of an addressing calculation.
If we return a non-null expression, it is an equivalent form of the
original computation, but need not be in the original type. */
static tree
extract_muldiv (t, c, code, wide_type)
tree t;
tree c;
enum tree_code code;
tree wide_type;
{
tree type = TREE_TYPE (t);
enum tree_code tcode = TREE_CODE (t);
tree ctype = (wide_type != 0 && (GET_MODE_SIZE (TYPE_MODE (wide_type))
> GET_MODE_SIZE (TYPE_MODE (type)))
? wide_type : type);
tree t1, t2;
int same_p = tcode == code;
int cancel_p
= (code == MULT_EXPR && tcode == EXACT_DIV_EXPR) || tcode == MULT_EXPR;
tree op0, op1;
/* Don't deal with constants of zero here; they confuse the code below. */
if (integer_zerop (c))
return 0;
if (TREE_CODE_CLASS (tcode) == '1')
op0 = TREE_OPERAND (t, 0);
if (TREE_CODE_CLASS (tcode) == '2')
op0 = TREE_OPERAND (t, 0), op1 = TREE_OPERAND (t, 1);
/* Note that we need not handle conditional operations here since fold
already handles those cases. So just do arithmetic here. */
switch (tcode)
{
case INTEGER_CST:
/* For a constant, we can always simplify if we are a multiply
or (for divide and modulus) if it is a multiple of our constant. */
if (code == MULT_EXPR
|| integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c, 0)))
return const_binop (code, convert (ctype, t), convert (ctype, c), 0);
break;
case CONVERT_EXPR: case NON_LVALUE_EXPR: case NOP_EXPR:
/* Pass the constant down and see if we can make a simplification. If
we can, replace this expression with a conversion of that result to
our type. */
if (0 != (t1 = extract_muldiv (op0, convert (TREE_TYPE (op0), c), code,
code == MULT_EXPR ? ctype : NULL_TREE)))
return t1;
break;
case NEGATE_EXPR: case ABS_EXPR:
if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
return fold (build1 (tcode, ctype, convert (ctype, t1)));
break;
case MIN_EXPR: case MAX_EXPR:
/* MIN (a, b) / 5 -> MIN (a / 5, b / 5) */
if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0
&& (t2 = extract_muldiv (op1, c, code, wide_type)) != 0)
return fold (build (tcode, ctype, convert (ctype, t1),
convert (ctype, t2)));
break;
case WITH_RECORD_EXPR:
if ((t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code, wide_type)) != 0)
return build (WITH_RECORD_EXPR, TREE_TYPE (t1), t1,
TREE_OPERAND (t, 1));
break;
case SAVE_EXPR:
/* If this has not been evaluated, we can see if we can do
something inside it and make a new one. */
if (SAVE_EXPR_RTL (t) == 0
&& 0 != (t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code,
wide_type)))
return save_expr (t1);
break;
case LSHIFT_EXPR: case RSHIFT_EXPR:
/* If the second operand is constant, this is a multiplication
or floor division, by a power of two, so we can treat it that
way unless the multiplier or divisor overflows. */
if (TREE_CODE (op1) == INTEGER_CST
&& 0 != (t1 = convert (ctype,
const_binop (LSHIFT_EXPR, size_one_node,
op1, 0)))
&& ! TREE_OVERFLOW (t1))
return extract_muldiv (build (tcode == LSHIFT_EXPR
? MULT_EXPR : FLOOR_DIV_EXPR,
ctype, convert (ctype, op0), t1),
c, code, wide_type);
break;
case PLUS_EXPR: case MINUS_EXPR:
/* See if we can eliminate the operation on both sides. If we can, we
can return a new PLUS or MINUS. If we can't, the only remaining
cases where we can do anything are if the second operand is a
constant. */
t1 = extract_muldiv (op0, c, code, wide_type);
t2 = extract_muldiv (op1, c, code, wide_type);
if (t1 != 0 && t2 != 0)
return fold (build (tcode, ctype, convert (ctype, t1),
convert (ctype, t2)));
else if (TREE_CODE (op1) != INTEGER_CST)
break;
/* If we were able to eliminate our operation from the first side,
apply our operation to the second side and reform the PLUS or
MINUS. */
if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR)
&& 0 != (t2 = const_binop (code, convert (ctype, op1),
convert (ctype, c), 0))
&& ! TREE_OVERFLOW (t2))
return fold (build (tcode, ctype, convert (ctype, t1), t2));
/* The last case is if we are a multiply. In that case, we can
apply the distributive law to commute the multiply and addition
if the multiplication of the constants doesn't overflow. */
if (code == MULT_EXPR
&& 0 != (t1 = const_binop (code, convert (ctype, op1),
convert (ctype, c), 0))
&& ! TREE_OVERFLOW (t1))
return fold (build (tcode, ctype, fold (build (code, ctype,
convert (ctype, op0),
convert (ctype, c))),
t1));
break;
case MULT_EXPR:
/* We have a special case here if we are doing something like
(C * 8) % 4 since we know that's zero. */
if ((code == TRUNC_MOD_EXPR || code == CEIL_MOD_EXPR
|| code == FLOOR_MOD_EXPR || code == ROUND_MOD_EXPR)
&& TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
&& integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
return omit_one_operand (type, integer_zero_node, op0);
/* ... fall through ... */
case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR: case EXACT_DIV_EXPR:
/* If we can extract our operation from the LHS, do so and return a
new operation. Likewise for the RHS from a MULT_EXPR. Otherwise,
do something only if the second operand is a constant. */
if (same_p
&& (t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
return fold (build (tcode, ctype, convert (ctype, t1),
convert (ctype, op1)));
else if (tcode == MULT_EXPR && code == MULT_EXPR
&& (t1 = extract_muldiv (op1, c, code, wide_type)) != 0)
return fold (build (tcode, ctype, convert (ctype, op0),
convert (ctype, t1)));
else if (TREE_CODE (op1) != INTEGER_CST)
return 0;
/* If these are the same operation types, we can associate them
assuming no overflow. */
if (tcode == code
&& 0 != (t1 = const_binop (MULT_EXPR, convert (ctype, op1),
convert (ctype, c), 0))
&& ! TREE_OVERFLOW (t1))
return fold (build (tcode, ctype, convert (ctype, op0), t1));
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
multiple of the other, in which case we replace this with either an
operation or CODE or TCODE. */
if ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
|| (tcode == MULT_EXPR
&& code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR))
{
if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
return fold (build (tcode, ctype, convert (ctype, op0),
convert (ctype,
const_binop (TRUNC_DIV_EXPR,
op1, c, 0))));
else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0)))
return fold (build (code, ctype, convert (ctype, op0),
convert (ctype,
const_binop (TRUNC_DIV_EXPR,
c, op1, 0))));
}
break;
default:
break;
}
return 0;
}
/* If T contains a COMPOUND_EXPR which was inserted merely to evaluate
S, a SAVE_EXPR, return the expression actually being evaluated. Note
that we may sometimes modify the tree. */
@ -4772,7 +5070,8 @@ fold (expr)
return TREE_OPERAND (arg0, 0);
/* Convert - (a - b) to (b - a) for non-floating-point. */
else if (TREE_CODE (arg0) == MINUS_EXPR && ! FLOAT_TYPE_P (type))
else if (TREE_CODE (arg0) == MINUS_EXPR
&& (! FLOAT_TYPE_P (type) || flag_fast_math))
return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg0, 0));
@ -4816,14 +5115,10 @@ fold (expr)
else if (TREE_CODE (arg0) == COMPLEX_EXPR)
return build (COMPLEX_EXPR, TREE_TYPE (arg0),
TREE_OPERAND (arg0, 0),
fold (build1 (NEGATE_EXPR,
TREE_TYPE (TREE_TYPE (arg0)),
TREE_OPERAND (arg0, 1))));
negate_expr (TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == COMPLEX_CST)
return build_complex (type, TREE_OPERAND (arg0, 0),
fold (build1 (NEGATE_EXPR,
TREE_TYPE (TREE_TYPE (arg0)),
TREE_OPERAND (arg0, 1))));
negate_expr (TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
return fold (build (TREE_CODE (arg0), type,
fold (build1 (CONJ_EXPR, type,
@ -5047,109 +5342,41 @@ fold (expr)
}
}
associate:
/* In most languages, can't associate operations on floats
through parentheses. Rather than remember where the parentheses
were, we don't associate floats at all. It shouldn't matter much.
However, associating multiplications is only very slightly
inaccurate, so do that if -ffast-math is specified. */
if (FLOAT_TYPE_P (type)
&& ! (flag_fast_math && code == MULT_EXPR))
goto binary;
/* In most languages, can't associate operations on floats through
parentheses. Rather than remember where the parentheses were, we
don't associate floats at all. It shouldn't matter much. However,
associating multiplications is only very slightly inaccurate, so do
that if -ffast-math is specified. */
/* The varsign == -1 cases happen only for addition and subtraction.
It says that the arg that was split was really CON minus VAR.
The rest of the code applies to all associative operations. */
if (!wins)
if (! wins
&& (! FLOAT_TYPE_P (type)
|| (flag_fast_math && code != MULT_EXPR)))
{
tree var, con;
int varsign;
tree var0, con0, lit0, var1, con1, lit1;
if (split_tree (arg0, code, &var, &con, &varsign))
/* 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);
/* 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 (varsign == -1)
{
/* EXPR is (CON-VAR) +- ARG1. */
/* If it is + and VAR==ARG1, return just CONST. */
if (code == PLUS_EXPR && operand_equal_p (var, arg1, 0))
return convert (TREE_TYPE (t), con);
/* If ARG0 is a constant, don't change things around;
instead keep all the constant computations together. */
if (TREE_CONSTANT (arg0))
return t;
/* Otherwise return (CON +- ARG1) - VAR. */
t = build (MINUS_EXPR, type,
fold (build (code, type, con, arg1)), var);
}
else
{
/* EXPR is (VAR+CON) +- ARG1. */
/* If it is - and VAR==ARG1, return just CONST. */
if (code == MINUS_EXPR && operand_equal_p (var, arg1, 0))
return convert (TREE_TYPE (t), con);
/* If ARG0 is a constant, don't change things around;
instead keep all the constant computations together. */
if (TREE_CONSTANT (arg0))
return t;
/* Otherwise return VAR +- (ARG1 +- CON). */
tem = fold (build (code, type, arg1, con));
t = build (code, type, var, tem);
if (integer_zerop (tem)
&& (code == PLUS_EXPR || code == MINUS_EXPR))
return convert (type, var);
/* If we have x +/- (c - d) [c an explicit integer]
change it to x -/+ (d - c) since if d is relocatable
then the latter can be a single immediate insn
and the former cannot. */
if (TREE_CODE (tem) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (tem, 0)) == INTEGER_CST)
{
tree tem1 = TREE_OPERAND (tem, 1);
TREE_OPERAND (tem, 1) = TREE_OPERAND (tem, 0);
TREE_OPERAND (tem, 0) = tem1;
TREE_SET_CODE (t,
(code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR));
}
}
return t;
}
if (split_tree (arg1, code, &var, &con, &varsign))
{
if (TREE_CONSTANT (arg1))
return t;
if (varsign == -1)
TREE_SET_CODE (t,
(code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR));
/* EXPR is ARG0 +- (CON +- VAR). */
if (TREE_CODE (t) == MINUS_EXPR
&& operand_equal_p (var, arg0, 0))
{
/* If VAR and ARG0 cancel, return just CON or -CON. */
if (code == PLUS_EXPR)
return convert (TREE_TYPE (t), con);
return fold (build1 (NEGATE_EXPR, TREE_TYPE (t),
convert (TREE_TYPE (t), con)));
}
t = build (TREE_CODE (t), type,
fold (build (code, TREE_TYPE (t), arg0, con)), var);
if (integer_zerop (TREE_OPERAND (t, 0))
&& TREE_CODE (t) == PLUS_EXPR)
return convert (TREE_TYPE (t), var);
return t;
var0 = associate_trees (var0, var1, code, type);
con0 = associate_trees (con0, con1, code, type);
lit0 = associate_trees (lit0, lit1, code, type);
con0 = associate_trees (con0, lit0, code, type);
return convert (type, associate_trees (var0, con0, code, type));
}
}
binary:
#if defined (REAL_IS_NOT_DOUBLE) && ! defined (REAL_ARITHMETIC)
if (TREE_CODE (arg1) == REAL_CST)
@ -5183,7 +5410,7 @@ fold (expr)
if (! FLOAT_TYPE_P (type))
{
if (! wins && integer_zerop (arg0))
return build1 (NEGATE_EXPR, type, arg1);
return negate_expr (arg1);
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
@ -5206,7 +5433,7 @@ fold (expr)
{
/* Except with IEEE floating point, 0-x equals -x. */
if (! wins && real_zerop (arg0))
return build1 (NEGATE_EXPR, type, arg1);
return negate_expr (arg1);
/* Except with IEEE floating point, x-0 equals x. */
if (real_zerop (arg1))
return non_lvalue (convert (type, arg0));
@ -5237,14 +5464,6 @@ fold (expr)
if (integer_onep (arg1))
return non_lvalue (convert (type, arg0));
/* ((A / C) * C) is A if the division is an
EXACT_DIV_EXPR. Since C is normally a constant,
just check for one of the four possibilities. */
if (TREE_CODE (arg0) == EXACT_DIV_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
return TREE_OPERAND (arg0, 0);
/* (a * (1 << b)) is (a << b) */
if (TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
@ -5254,6 +5473,12 @@ fold (expr)
&& integer_onep (TREE_OPERAND (arg0, 0)))
return fold (build (LSHIFT_EXPR, type, arg1,
TREE_OPERAND (arg0, 1)));
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
code, NULL_TREE)))
return convert (type, tem);
}
else
{
@ -5455,129 +5680,10 @@ fold (expr)
&& multiple_of_p (type, arg0, arg1))
return fold (build (EXACT_DIV_EXPR, type, arg0, arg1));
/* If we have ((a / C1) / C2) where both division are the same type, try
to simplify. First see if C1 * C2 overflows or not. */
if (TREE_CODE (arg0) == code && TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree new_divisor;
new_divisor = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 1), arg1, 0);
tem = const_binop (FLOOR_DIV_EXPR, new_divisor, arg1, 0);
if (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) == TREE_INT_CST_LOW (tem)
&& TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == TREE_INT_CST_HIGH (tem))
{
/* If no overflow, divide by C1*C2. */
return fold (build (code, type, TREE_OPERAND (arg0, 0), new_divisor));
}
}
/* Look for ((a * C1) / C3) or (((a * C1) + C2) / C3),
where C1 % C3 == 0 or C3 % C1 == 0. We can simplify these
expressions, which often appear in the offsets or sizes of
objects with a varying size. Only deal with positive divisors
and multiplicands. If C2 is negative, we must have C2 % C3 == 0.
Look for NOPs and SAVE_EXPRs inside. */
if (TREE_CODE (arg1) == INTEGER_CST
&& tree_int_cst_sgn (arg1) >= 0)
{
int have_save_expr = 0;
tree c2 = integer_zero_node;
tree xarg0 = arg0;
if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
STRIP_NOPS (xarg0);
/* Look inside the dividend and simplify using EXACT_DIV_EXPR
if possible. */
if (TREE_CODE (xarg0) == MULT_EXPR
&& multiple_of_p (type, TREE_OPERAND (xarg0, 0), arg1))
{
tree t;
t = fold (build (MULT_EXPR, type,
fold (build (EXACT_DIV_EXPR, type,
TREE_OPERAND (xarg0, 0), arg1)),
TREE_OPERAND (xarg0, 1)));
if (have_save_expr)
t = save_expr (t);
return t;
}
if (TREE_CODE (xarg0) == MULT_EXPR
&& multiple_of_p (type, TREE_OPERAND (xarg0, 1), arg1))
{
tree t;
t = fold (build (MULT_EXPR, type,
fold (build (EXACT_DIV_EXPR, type,
TREE_OPERAND (xarg0, 1), arg1)),
TREE_OPERAND (xarg0, 0)));
if (have_save_expr)
t = save_expr (t);
return t;
}
if (TREE_CODE (xarg0) == PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST)
c2 = TREE_OPERAND (xarg0, 1), xarg0 = TREE_OPERAND (xarg0, 0);
else if (TREE_CODE (xarg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST
/* If we are doing this computation unsigned, the negate
is incorrect. */
&& ! TREE_UNSIGNED (type))
{
c2 = fold (build1 (NEGATE_EXPR, type, TREE_OPERAND (xarg0, 1)));
xarg0 = TREE_OPERAND (xarg0, 0);
}
if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
STRIP_NOPS (xarg0);
if (TREE_CODE (xarg0) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (xarg0, 1)) >= 0
&& (integer_zerop (const_binop (TRUNC_MOD_EXPR,
TREE_OPERAND (xarg0, 1), arg1, 1))
|| integer_zerop (const_binop (TRUNC_MOD_EXPR, arg1,
TREE_OPERAND (xarg0, 1), 1)))
&& (tree_int_cst_sgn (c2) >= 0
|| integer_zerop (const_binop (TRUNC_MOD_EXPR, c2,
arg1, 1))))
{
tree outer_div = integer_one_node;
tree c1 = TREE_OPERAND (xarg0, 1);
tree c3 = arg1;
/* If C3 > C1, set them equal and do a divide by
C3/C1 at the end of the operation. */
if (tree_int_cst_lt (c1, c3))
outer_div = const_binop (code, c3, c1, 0), c3 = c1;
/* The result is A * (C1/C3) + (C2/C3). */
t = fold (build (PLUS_EXPR, type,
fold (build (MULT_EXPR, type,
TREE_OPERAND (xarg0, 0),
const_binop (code, c1, c3, 1))),
const_binop (code, c2, c3, 1)));
if (! integer_onep (outer_div))
t = fold (build (code, type, t, convert (type, outer_div)));
if (have_save_expr)
t = save_expr (t);
return t;
}
}
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
code, NULL_TREE)))
return convert (type, tem);
goto binary;
@ -5590,39 +5696,10 @@ fold (expr)
if (integer_zerop (arg1))
return t;
/* Look for ((a * C1) % C3) or (((a * C1) + C2) % C3),
where C1 % C3 == 0. Handle similarly to the division case,
but don't bother with SAVE_EXPRs. */
if (TREE_CODE (arg1) == INTEGER_CST
&& ! integer_zerop (arg1))
{
tree c2 = integer_zero_node;
tree xarg0 = arg0;
if (TREE_CODE (xarg0) == PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST)
c2 = TREE_OPERAND (xarg0, 1), xarg0 = TREE_OPERAND (xarg0, 0);
else if (TREE_CODE (xarg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST
&& ! TREE_UNSIGNED (type))
{
c2 = fold (build1 (NEGATE_EXPR, type, TREE_OPERAND (xarg0, 1)));
xarg0 = TREE_OPERAND (xarg0, 0);
}
STRIP_NOPS (xarg0);
if (TREE_CODE (xarg0) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (xarg0, 1)) == INTEGER_CST
&& integer_zerop (const_binop (TRUNC_MOD_EXPR,
TREE_OPERAND (xarg0, 1),
arg1, 1))
&& tree_int_cst_sgn (c2) >= 0)
/* The result is (C2%C3). */
return omit_one_operand (type, const_binop (code, c2, arg1, 1),
TREE_OPERAND (xarg0, 0));
}
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
code, NULL_TREE)))
return convert (type, tem);
goto binary;
@ -6046,8 +6123,7 @@ fold (expr)
else if ((code == EQ_EXPR || code == NE_EXPR)
&& TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = fold (build1 (NEGATE_EXPR, TREE_TYPE (arg1),
arg1)))
&& 0 != (tem = negate_expr (arg1))
&& TREE_CODE (tem) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (tem))
return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
@ -6086,17 +6162,14 @@ fold (expr)
and a comparison, and is probably faster. */
else if (code == LE_EXPR && TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (arg0) == ABS_EXPR
&& ! TREE_SIDE_EFFECTS (arg0))
{
tree inner = TREE_OPERAND (arg0, 0);
tem = fold (build1 (NEGATE_EXPR, TREE_TYPE (arg1), arg1));
if (TREE_CODE (tem) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (tem))
return fold (build (TRUTH_ANDIF_EXPR, type,
build (GE_EXPR, type, inner, tem),
build (LE_EXPR, type, inner, arg1)));
}
&& ! TREE_SIDE_EFFECTS (arg0)
&& (0 != (tem = negate_expr (arg1)))
&& TREE_CODE (tem) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (tem))
return fold (build (TRUTH_ANDIF_EXPR, type,
build (GE_EXPR, type, TREE_OPERAND (arg0, 0), tem),
build (LE_EXPR, type,
TREE_OPERAND (arg0, 0), arg1)));
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
@ -6635,8 +6708,7 @@ fold (expr)
switch (comp_code)
{
case EQ_EXPR:
return pedantic_non_lvalue
(fold (build1 (NEGATE_EXPR, type, arg1)));
return pedantic_non_lvalue (negate_expr (arg1));
case NE_EXPR:
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
@ -6651,11 +6723,10 @@ fold (expr)
if (TREE_UNSIGNED (TREE_TYPE (arg1)))
arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
return pedantic_non_lvalue
(fold (build1 (NEGATE_EXPR, type,
convert (type,
fold (build1 (ABS_EXPR,
TREE_TYPE (arg1),
arg1))))));
(negate_expr (convert (type,
fold (build1 (ABS_EXPR,
TREE_TYPE (arg1),
arg1)))));
default:
abort ();
}