This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fold-const patch
- To: egcs-patches at egcs dot cygnus dot com
- Subject: Fold-const patch
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Fri, 17 Dec 1999 01:31:46 +0100
Hi
This patch makes fold_const more serious about optimizing artihmetic
expressions. It adds functions simplify_negate_expr and simplify_bit_not_expr,
that construct negated (not-ed) expression when it is possible to do so cheaply
(i.e w/o adding extra tree node). Using it fold_const can convert subs to adds
and vice versa, propagate nots outside multiply and real divide etc.
Also some code duplication is avoided.
Note that I am not 100% sure that all the operations are valid for IEEE fp, but
I believe so, because IEEE fp behaves quite nicely to negate operation.
I didn't added any transformations that wasn't already done, only extended them
(by accepting not only NEGATE as subexpression, but any expression cheap to negate).
PS:
(OOPS. I see I forgot the prototype. I will add it...)
Čt prosinec 16 14:47:26 CET 1999 Jan Hubicka <hubicka@freesoft.cz>
* fold_const.c (simplify_negate_expr): New.
(simplify_bit_not_expr): New. (simplify_negate): Use
simplify_negate_expr. (fold): Optimize BIT_NOT_EXPR using
simplify_bit_not_expr; likewise NEGATE_EXPR; optimize MINUS_EXPR to
PLUS_EXPR when second operand can be negates; be more aggresive about
propagating NEGATES outside MULT and RDIV; propagate NOTs outside XOR;
optimize away XOR, AND and OR when operands are equal.
*** fold-const.c.noo Thu Dec 16 09:54:45 1999
--- fold-const.c Thu Dec 16 14:57:15 1999
*************** real_hex_to_f (s, mode)
*** 1205,1215 ****
#endif /* no REAL_ARITHMETIC */
! /* Given T, an expression, return the negation of T. Allow for T to be
! null, in which case return null. */
static tree
! negate_expr (t)
tree t;
{
tree type;
--- 1205,1215 ----
#endif /* no REAL_ARITHMETIC */
! /* Given T, an expression, return the negation of T if it is possible to do it
! without extra NEGATE operator. Return NULL_TREE otherwise. */
static tree
! simplify_negate_expr (t)
tree t;
{
tree type;
*************** negate_expr (t)
*** 1234,1239 ****
--- 1234,1247 ----
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
+ case BIT_NOT_EXPR:
+ {
+ tree m1 = build_int_2 (1, 0);
+ TREE_TYPE (m1) = type;
+
+ return convert (type, fold (build (PLUS_EXPR, TREE_TYPE (t),
+ TREE_OPERAND (t, 0), m1)));
+ }
case MINUS_EXPR:
/* - (A - B) -> B - A */
if (! FLOAT_TYPE_P (type) || flag_fast_math)
*************** negate_expr (t)
*** 1242,1252 ****
--- 1250,1361 ----
TREE_OPERAND (t, 1),
TREE_OPERAND (t, 0))));
break;
+ case PLUS_EXPR:
+ /* - ((- A) + B) -> (A - B) */
+ if (! FLOAT_TYPE_P (type) || flag_fast_math)
+ {
+ tree tmp = simplify_negate_expr (TREE_OPERAND (t, 0));
+ if (tmp != NULL_TREE)
+ return convert (type,
+ fold (build (MINUS_EXPR, TREE_TYPE (t),
+ tmp,
+ TREE_OPERAND (t, 1))));
+ tmp = simplify_negate_expr (TREE_OPERAND (t, 1));
+ if (tmp != NULL_TREE)
+ return convert (type,
+ fold (build (MINUS_EXPR, TREE_TYPE (t),
+ tmp,
+ TREE_OPERAND (t, 0))));
+ }
+ break;
default:
break;
}
+ return NULL_TREE;
+ }
+
+ /* Given T, an expression, return the ~T if it is possible to do it
+ without extra BIT_NOT operator. Return NULL_TREE otherwise. */
+
+ static tree
+ simplify_bit_not_expr (t)
+ tree t;
+ {
+ tree type;
+ tree tem;
+
+ 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 (BIT_NOT_EXPR, type, t)))
+ && !TREE_OVERFLOW (tem))
+ return tem;
+ break;
+
+ case BIT_NOT_EXPR:
+ return convert (type, TREE_OPERAND (t, 0));
+
+ case NEGATE_EXPR:
+ {
+ tree m1 = build_int_2 (~0, ~0);
+ TREE_TYPE (m1) = type;
+ force_fit_type (m1, 0);
+
+ return convert (type, fold (build (PLUS_EXPR, TREE_TYPE (t),
+ TREE_OPERAND (t, 0), m1)));
+ }
+ case BIT_XOR_EXPR:
+ {
+ tree tmp = simplify_bit_not_expr (TREE_OPERAND (t, 0));
+ if (tmp)
+ return convert (type,
+ fold (build (BIT_XOR_EXPR, TREE_TYPE (t),
+ tmp,
+ TREE_OPERAND (t, 1))));
+ tmp = simplify_bit_not_expr (TREE_OPERAND (t, 1));
+ if (tmp)
+ return convert (type,
+ fold (build (BIT_XOR_EXPR, TREE_TYPE (t),
+ tmp,
+ TREE_OPERAND (t, 0))));
+ }
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+ }
+ /* Given T, an expression, return the negation of T. Allow for T to be
+ null, in which case return null. */
+
+ static tree
+ negate_expr (t)
+ tree t;
+ {
+ tree type;
+ tree tem;
+
+ if (t == 0)
+ return 0;
+
+ tem = simplify_negate_expr(t);
+ if (tem != NULL_TREE)
+ return tem;
+
+ type = TREE_TYPE (t);
+ STRIP_SIGN_NOPS (t);
+
return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (t), t));
}
*************** fold (expr)
*** 5075,5088 ****
else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
}
- else if (TREE_CODE (arg0) == NEGATE_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) || flag_fast_math))
! return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
! TREE_OPERAND (arg0, 0));
return t;
--- 5184,5194 ----
else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
}
! /* Avoid infinite recursion. */
! if (TREE_CODE (arg0) != INTEGER_CST && TREE_CODE (arg0) != REAL_CST
! && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! return t1;
return t;
*************** fold (expr)
*** 5148,5155 ****
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
}
! else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
! return TREE_OPERAND (arg0, 0);
return t;
case PLUS_EXPR:
--- 5254,5264 ----
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
}
!
! /* Avoid infinite recursion. */
! if (TREE_CODE (arg0) != INTEGER_CST && TREE_CODE (arg0) != REAL_CST
! && (t1 = simplify_bit_not_expr (arg0)) != NULL_TREE)
! return t1;
return t;
case PLUS_EXPR:
*************** fold (expr)
*** 5405,5420 ****
return t;
case MINUS_EXPR:
! /* A - (-B) -> A + B */
! if (TREE_CODE (arg1) == NEGATE_EXPR)
! return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
! /* (-A) - CST -> (-CST) - A for floating point (what about ints ?) */
! if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
! return
! fold (build (MINUS_EXPR, type,
! build_real (TREE_TYPE (arg1),
! REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
! TREE_OPERAND (arg0, 0)));
if (! FLOAT_TYPE_P (type))
{
--- 5514,5523 ----
return t;
case MINUS_EXPR:
! /* Convert MINUS to PLUS if possible. */
! t1 = simplify_negate_expr (arg1);
! if (t1 != NULL_TREE)
! return fold (build (PLUS_EXPR, type, arg0, t1));
if (! FLOAT_TYPE_P (type))
{
*************** fold (expr)
*** 5423,5428 ****
--- 5526,5538 ----
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
+ /* Try to convert (-A) - B to -(A + B) in hope that more powerfull
+ optimizations for PLUS will be done or NOT will be eliminated later. */
+ if (TREE_CODE (arg0) == NEGATE_EXPR)
+ return fold (build1 (NEGATE_EXPR, type,
+ fold (build (PLUS_EXPR, type,
+ TREE_OPERAND (arg0, 0), arg1))));
+
/* (A * C) - (B * C) -> (A-B) * C. Since we are most concerned
about the case where C is a constant, just try one of the
four possibilities. */
*************** fold (expr)
*** 5462,5470 ****
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
! TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
{
--- 5572,5583 ----
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
! if (TREE_CODE (arg0) == NEGATE_EXPR
! && (t1 = simplify_negate_expr (arg1)) != NULL_TREE)
! return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0), t1));
! if (TREE_CODE (arg1) == NEGATE_EXPR
! && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! return fold (build (MULT_EXPR, type, t1, TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
{
*************** fold (expr)
*** 5515,5521 ****
bit_ior:
if (integer_all_onesp (arg1))
return omit_one_operand (type, arg1, arg0);
! if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
--- 5628,5634 ----
bit_ior:
if (integer_all_onesp (arg1))
return omit_one_operand (type, arg1, arg0);
! if (integer_zerop (arg1) || operand_equal_p (arg0, arg1, 0))
return non_lvalue (convert (type, arg0));
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
*************** fold (expr)
*** 5545,5550 ****
--- 5658,5665 ----
return non_lvalue (convert (type, arg0));
if (integer_all_onesp (arg1))
return fold (build1 (BIT_NOT_EXPR, type, arg0));
+ if (operand_equal_p (arg0, arg1, 0))
+ return convert (type, integer_zero_node);
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
*************** fold (expr)
*** 5562,5574 ****
goto bit_ior;
}
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_AND_EXPR:
bit_and:
! if (integer_all_onesp (arg1))
return non_lvalue (convert (type, arg0));
if (integer_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
--- 5677,5701 ----
goto bit_ior;
}
+ /* Propagate NOTs outside XOR. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR)
+ return fold (build1 (BIT_NOT_EXPR, type,
+ fold (build (BIT_XOR_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ arg1))));
+ if (TREE_CODE (arg1) == BIT_NOT_EXPR)
+ return fold (build1 (BIT_NOT_EXPR, type,
+ fold (build (BIT_XOR_EXPR, type,
+ arg0,
+ TREE_OPERAND (arg1, 0)))));
+
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_AND_EXPR:
bit_and:
! if (integer_all_onesp (arg1) || operand_equal_p (arg0, arg1, 0))
return non_lvalue (convert (type, arg0));
if (integer_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
*************** fold (expr)
*** 5635,5643 ****
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* (-A) / (-B) -> A / B */
! if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! 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. */
--- 5762,5773 ----
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* (-A) / (-B) -> A / B */
! if (TREE_CODE (arg0) == NEGATE_EXPR
! && (t1 = simplify_negate_expr (arg1)) != NULL_TREE)
! return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0), t1));
! if (TREE_CODE (arg1) == NEGATE_EXPR
! && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! return fold (build (RDIV_EXPR, type, t1, 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. */