fold-const.c (tree_swap_operands_p): New function to determine the prefered ordering of operands.

* fold-const.c (tree_swap_operands_p): New function to determine
	the prefered ordering of operands.
	(fold): Numerous clean-ups.  Use tree_swap_operands_p when swapping
	operands to commutative, comparison or ternary operators.  Replace
	uses of TREE_SET_CODE with recursive call to fold.  Remove duplicate
	transformation of A ? B : C into !A ? C : B.

From-SVN: r71438
This commit is contained in:
Roger Sayle 2003-09-16 17:08:50 +00:00 committed by Roger Sayle
parent ae8803a8e1
commit 37af03cba8
2 changed files with 85 additions and 126 deletions

View File

@ -1,3 +1,12 @@
2003-09-16 Roger Sayle <roger@eyesopen.com>
* fold-const.c (tree_swap_operands_p): New function to determine
the prefered ordering of operands.
(fold): Numerous clean-ups. Use tree_swap_operands_p when swapping
operands to commutative, comparison or ternary operators. Replace
uses of TREE_SET_CODE with recursive call to fold. Remove duplicate
transformation of A ? B : C into !A ? C : B.
2003-09-16 Jakub Jelinek <jakub@redhat.com>
* config/linux.h (LINK_GCC_C_SEQUENCE_SPEC): Define.

View File

@ -108,6 +108,7 @@ static bool fold_real_zero_addition_p (tree, tree, int);
static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
tree, tree, tree);
static tree fold_inf_compare (enum tree_code, tree, tree, tree);
static bool tree_swap_operands_p (tree, tree);
/* The following constants represent a bit based encoding of GCC's
comparison operators. This encoding simplifies transformations
@ -4976,6 +4977,49 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
return NULL_TREE;
}
/* Test whether it is preferable two swap two operands, ARG0 and
ARG1, for example because ARG0 is an integer constant and ARG1
isn't. */
static bool
tree_swap_operands_p (tree arg0, tree arg1)
{
STRIP_SIGN_NOPS (arg0);
STRIP_SIGN_NOPS (arg1);
if (TREE_CODE (arg1) == INTEGER_CST)
return 0;
if (TREE_CODE (arg0) == INTEGER_CST)
return 1;
if (TREE_CODE (arg1) == REAL_CST)
return 0;
if (TREE_CODE (arg0) == REAL_CST)
return 1;
if (TREE_CODE (arg1) == COMPLEX_CST)
return 0;
if (TREE_CODE (arg0) == COMPLEX_CST)
return 1;
if (TREE_CONSTANT (arg1))
return 0;
if (TREE_CONSTANT (arg0))
return 1;
if (DECL_P (arg1))
return 0;
if (DECL_P (arg0))
return 1;
if (TREE_CODE (arg1) == SAVE_EXPR)
return 0;
if (TREE_CODE (arg0) == SAVE_EXPR)
return 1;
return 0;
}
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
@ -5035,8 +5079,7 @@ fold (tree expr)
subop = arg0;
if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
&& TREE_CODE (subop) != REAL_CST
)
&& TREE_CODE (subop) != REAL_CST)
/* Note that TREE_CONSTANT isn't enough:
static var addresses are constant but we can't
do arithmetic on them. */
@ -5088,16 +5131,8 @@ fold (tree expr)
if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
|| code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
|| code == BIT_AND_EXPR)
&& ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) != INTEGER_CST)
|| (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) != REAL_CST)))
{
tem = arg0; arg0 = arg1; arg1 = tem;
if (t == orig_t)
t = copy_node (t);
TREE_OPERAND (t, 0) = arg0;
TREE_OPERAND (t, 1) = arg1;
}
&& tree_swap_operands_p (arg0, arg1))
return fold (build (code, type, arg1, arg0));
/* Now WINS is set as described above,
ARG0 is the first operand of EXPR,
@ -6645,18 +6680,10 @@ fold (tree expr)
RROTATE_EXPR by a new constant. */
if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
{
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, RROTATE_EXPR);
code = RROTATE_EXPR;
TREE_OPERAND (t, 1) = arg1
= const_binop
(MINUS_EXPR,
convert (TREE_TYPE (arg1),
build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0)),
arg1, 0);
if (tree_int_cst_sgn (arg1) < 0)
return t;
tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
tem = convert (TREE_TYPE (arg1), tem);
tem = const_binop (MINUS_EXPR, tem, arg1, 0);
return fold (build (RROTATE_EXPR, type, arg0, tem));
}
/* If we have a rotate of a bit operation with the rotate count and
@ -6853,20 +6880,8 @@ fold (tree expr)
case LE_EXPR:
case GE_EXPR:
/* If one arg is a real or integer constant, put it last. */
if ((TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) != INTEGER_CST)
|| (TREE_CODE (arg0) == REAL_CST
&& TREE_CODE (arg0) != REAL_CST))
{
if (t == orig_t)
t = copy_node (t);
TREE_OPERAND (t, 0) = arg1;
TREE_OPERAND (t, 1) = arg0;
arg0 = TREE_OPERAND (t, 0);
arg1 = TREE_OPERAND (t, 1);
code = swap_tree_comparison (code);
TREE_SET_CODE (t, code);
}
if (tree_swap_operands_p (arg0, arg1))
return fold (build (swap_tree_comparison (code), type, arg1, arg0));
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
@ -7123,16 +7138,12 @@ fold (tree expr)
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;
return fold (build (GT_EXPR, type, arg0, arg1));
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;
return fold (build (LE_EXPR, type, arg0, arg1));
default:
break;
@ -7175,24 +7186,17 @@ fold (tree expr)
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, EQ_EXPR);
break;
return fold (build (EQ_EXPR, type, arg0, arg1));
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
code = NE_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, NE_EXPR);
break;
return fold (build (NE_EXPR, type, arg0, arg1));
/* The GE_EXPR and LT_EXPR cases above are not normally
reached because of previous transformations. */
reached because of previous transformations. */
default:
break;
@ -7202,15 +7206,11 @@ fold (tree expr)
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;
return fold (build (EQ_EXPR, type, arg0, arg1));
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;
return fold (build (NE_EXPR, type, arg0, arg1));
default:
break;
}
@ -7223,22 +7223,14 @@ fold (tree expr)
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, EQ_EXPR);
break;
return fold (build (EQ_EXPR, type, arg0, arg1));
case GE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case GT_EXPR:
code = NE_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, NE_EXPR);
break;
return fold (build (NE_EXPR, type, arg0, arg1));
default:
break;
@ -7248,15 +7240,11 @@ fold (tree expr)
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;
return fold (build (NE_EXPR, type, arg0, arg1));
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;
return fold (build (EQ_EXPR, type, arg0, arg1));
default:
break;
}
@ -7489,16 +7477,17 @@ fold (tree expr)
switch (code)
{
case EQ_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
|| ! HONOR_NANS (TYPE_MODE (TREE_TYPE (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))))
return constant_boolean_node (1, type);
code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, code);
break;
return fold (build (EQ_EXPR, type, arg0, arg1));
case NE_EXPR:
/* For NE, we can only do this simplification if integer
@ -7779,34 +7768,6 @@ fold (tree expr)
else if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
return pedantic_omit_one_operand (type, arg1, arg0);
/* If the second operand is zero, invert the comparison and swap
the second and third operands. Likewise if the second operand
is constant and the third is not or if the third operand is
equivalent to the first operand of the comparison. */
if (integer_zerop (arg1)
|| (TREE_CONSTANT (arg1) && ! TREE_CONSTANT (TREE_OPERAND (t, 2)))
|| (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (t, 2),
TREE_OPERAND (arg0, 1))))
{
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
anything. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
{
t = build (code, type, tem,
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
arg0 = tem;
/* arg1 should be the first argument of the new T. */
arg1 = TREE_OPERAND (t, 1);
STRIP_NOPS (arg1);
}
}
/* 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,
@ -7982,9 +7943,8 @@ fold (tree expr)
case EQ_EXPR:
/* We can replace A with C1 in this case. */
arg1 = convert (type, TREE_OPERAND (arg0, 1));
t = build (code, type, TREE_OPERAND (t, 0), arg1,
TREE_OPERAND (t, 2));
break;
return fold (build (code, type, TREE_OPERAND (t, 0), arg1,
TREE_OPERAND (t, 2)));
case LT_EXPR:
/* If C1 is C2 + 1, this is min(A, C2). */
@ -8034,11 +7994,7 @@ fold (tree expr)
/* If the second operand is simpler than the third, swap them
since that produces better jump optimization results. */
if ((TREE_CONSTANT (arg1) || DECL_P (arg1)
|| TREE_CODE (arg1) == SAVE_EXPR)
&& ! (TREE_CONSTANT (TREE_OPERAND (t, 2))
|| DECL_P (TREE_OPERAND (t, 2))
|| TREE_CODE (TREE_OPERAND (t, 2)) == SAVE_EXPR))
if (tree_swap_operands_p (TREE_OPERAND (t, 1), TREE_OPERAND (t, 2)))
{
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
@ -8046,14 +8002,8 @@ fold (tree expr)
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
{
t = build (code, type, tem,
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
arg0 = tem;
/* arg1 should be the first argument of the new T. */
arg1 = TREE_OPERAND (t, 1);
STRIP_NOPS (arg1);
}
return fold (build (code, type, tem,
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
}
/* Convert A ? 1 : 0 to simply A. */