Commit 3ea2c264 by Kazu Hirata Committed by Kazu Hirata

fold-const.c (fold_ternary): Unroll the "for" loop to extract operands.

	* fold-const.c (fold_ternary): Unroll the "for" loop to
	extract operands.

From-SVN: r95895
parent b120f3b7
2005-03-04 Kazu Hirata <kazu@cs.umass.edu>
* fold-const.c (fold_ternary): Unroll the "for" loop to
extract operands.
2005-03-04 Andrew Haley <aph@redhat.com> 2005-03-04 Andrew Haley <aph@redhat.com>
* unwind-dw2-fde-glibc.c (struct * unwind-dw2-fde-glibc.c (struct
......
...@@ -7024,41 +7024,38 @@ fold_ternary (tree expr) ...@@ -7024,41 +7024,38 @@ fold_ternary (tree expr)
const tree t = expr; const tree t = expr;
const tree type = TREE_TYPE (expr); const tree type = TREE_TYPE (expr);
tree tem; tree tem;
tree op0, op1, op2;
tree arg0 = NULL_TREE, arg1 = NULL_TREE; tree arg0 = NULL_TREE, arg1 = NULL_TREE;
enum tree_code code = TREE_CODE (t); enum tree_code code = TREE_CODE (t);
enum tree_code_class kind = TREE_CODE_CLASS (code); enum tree_code_class kind = TREE_CODE_CLASS (code);
int i;
gcc_assert (IS_EXPR_CODE_CLASS (kind) gcc_assert (IS_EXPR_CODE_CLASS (kind)
&& TREE_CODE_LENGTH (code) == 3); && TREE_CODE_LENGTH (code) == 3);
/* For now, we iterate only twice even though we are handling op0 = TREE_OPERAND (t, 0);
ternary expressions. This is because we haven't defined arg2 op1 = TREE_OPERAND (t, 1);
yet. */ op2 = TREE_OPERAND (t, 2);
for (i = 0; i < 2; i++)
{
tree op = TREE_OPERAND (t, i);
if (op == 0)
continue; /* Valid for CALL_EXPR, at least. */
/* Strip any conversions that don't change the mode. This is /* Strip any conversions that don't change the mode. This is safe
safe for every expression, except for a comparison expression for every expression, except for a comparison expression because
because its signedness is derived from its operands. So, in its signedness is derived from its operands. So, in the latter
the latter case, only strip conversions that don't change the case, only strip conversions that don't change the signedness.
signedness.
Note that this is done as an internal manipulation within the Note that this is done as an internal manipulation within the
constant folder, in order to find the simplest representation constant folder, in order to find the simplest representation of
of the arguments so that their form can be studied. In any the arguments so that their form can be studied. In any cases,
cases, the appropriate type conversions should be put back in the appropriate type conversions should be put back in the tree
the tree that will get out of the constant folder. */ that will get out of the constant folder. */
STRIP_NOPS (op); if (op0)
{
arg0 = op0;
STRIP_NOPS (arg0);
}
if (i == 0) if (op1)
arg0 = op; {
else if (i == 1) arg1 = op1;
arg1 = op; STRIP_NOPS (arg1);
} }
switch (code) switch (code)
...@@ -7078,7 +7075,7 @@ fold_ternary (tree expr) ...@@ -7078,7 +7075,7 @@ fold_ternary (tree expr)
so all simple results must be passed through pedantic_non_lvalue. */ so all simple results must be passed through pedantic_non_lvalue. */
if (TREE_CODE (arg0) == INTEGER_CST) if (TREE_CODE (arg0) == INTEGER_CST)
{ {
tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1)); tem = integer_zerop (arg0) ? op2 : op1;
/* Only optimize constant conditions when the selected branch /* Only optimize constant conditions when the selected branch
has the same type as the COND_EXPR. This avoids optimizing has the same type as the COND_EXPR. This avoids optimizing
away "c ? x : throw", where the throw has a void type. */ away "c ? x : throw", where the throw has a void type. */
...@@ -7087,7 +7084,7 @@ fold_ternary (tree expr) ...@@ -7087,7 +7084,7 @@ fold_ternary (tree expr)
return pedantic_non_lvalue (tem); return pedantic_non_lvalue (tem);
return t; return t;
} }
if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0)) if (operand_equal_p (arg1, op2, 0))
return pedantic_omit_one_operand (type, arg1, arg0); return pedantic_omit_one_operand (type, arg1, arg0);
/* If we have A op B ? A : C, we may be able to convert this to a /* If we have A op B ? A : C, we may be able to convert this to a
...@@ -7101,25 +7098,21 @@ fold_ternary (tree expr) ...@@ -7101,25 +7098,21 @@ fold_ternary (tree expr)
arg1, TREE_OPERAND (arg0, 1)) arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1)))) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{ {
tem = fold_cond_expr_with_comparison (type, arg0, tem = fold_cond_expr_with_comparison (type, arg0, op1, op2);
TREE_OPERAND (t, 1),
TREE_OPERAND (t, 2));
if (tem) if (tem)
return tem; return tem;
} }
if (COMPARISON_CLASS_P (arg0) if (COMPARISON_CLASS_P (arg0)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (t, 2), op2,
TREE_OPERAND (arg0, 1)) TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2))))) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
{ {
tem = invert_truthvalue (arg0); tem = invert_truthvalue (arg0);
if (COMPARISON_CLASS_P (tem)) if (COMPARISON_CLASS_P (tem))
{ {
tem = fold_cond_expr_with_comparison (type, tem, tem = fold_cond_expr_with_comparison (type, tem, op2, op1);
TREE_OPERAND (t, 2),
TREE_OPERAND (t, 1));
if (tem) if (tem)
return tem; return tem;
} }
...@@ -7127,8 +7120,7 @@ fold_ternary (tree expr) ...@@ -7127,8 +7120,7 @@ fold_ternary (tree expr)
/* If the second operand is simpler than the third, swap them /* If the second operand is simpler than the third, swap them
since that produces better jump optimization results. */ since that produces better jump optimization results. */
if (tree_swap_operands_p (TREE_OPERAND (t, 1), if (tree_swap_operands_p (op1, op2, false))
TREE_OPERAND (t, 2), false))
{ {
/* See if this can be inverted. If it can't, possibly because /* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do it was a floating-point inequality comparison, don't do
...@@ -7136,14 +7128,13 @@ fold_ternary (tree expr) ...@@ -7136,14 +7128,13 @@ fold_ternary (tree expr)
tem = invert_truthvalue (arg0); tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR) if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
return fold (build3 (code, type, tem, return fold (build3 (code, type, tem, op2, op1));
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
} }
/* Convert A ? 1 : 0 to simply A. */ /* Convert A ? 1 : 0 to simply A. */
if (integer_onep (TREE_OPERAND (t, 1)) if (integer_onep (op1)
&& integer_zerop (TREE_OPERAND (t, 2)) && integer_zerop (op2)
/* If we try to convert TREE_OPERAND (t, 0) to our type, the /* If we try to convert OP0 to our type, the
call to fold will try to move the conversion inside call to fold will try to move the conversion inside
a COND, which will recurse. In that case, the COND_EXPR a COND, which will recurse. In that case, the COND_EXPR
is probably the best choice, so leave it alone. */ is probably the best choice, so leave it alone. */
...@@ -7152,8 +7143,8 @@ fold_ternary (tree expr) ...@@ -7152,8 +7143,8 @@ fold_ternary (tree expr)
/* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
over COND_EXPR in cases such as floating point comparisons. */ over COND_EXPR in cases such as floating point comparisons. */
if (integer_zerop (TREE_OPERAND (t, 1)) if (integer_zerop (op1)
&& integer_onep (TREE_OPERAND (t, 2)) && integer_onep (op2)
&& truth_value_p (TREE_CODE (arg0))) && truth_value_p (TREE_CODE (arg0)))
return pedantic_non_lvalue (fold_convert (type, return pedantic_non_lvalue (fold_convert (type,
invert_truthvalue (arg0))); invert_truthvalue (arg0)));
...@@ -7161,7 +7152,7 @@ fold_ternary (tree expr) ...@@ -7161,7 +7152,7 @@ fold_ternary (tree expr)
/* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */ /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
if (TREE_CODE (arg0) == LT_EXPR if (TREE_CODE (arg0) == LT_EXPR
&& integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (TREE_OPERAND (arg0, 1))
&& integer_zerop (TREE_OPERAND (t, 2)) && integer_zerop (op2)
&& (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1))) && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
return fold_convert (type, fold (build2 (BIT_AND_EXPR, return fold_convert (type, fold (build2 (BIT_AND_EXPR,
TREE_TYPE (tem), tem, arg1))); TREE_TYPE (tem), tem, arg1)));
...@@ -7170,7 +7161,7 @@ fold_ternary (tree expr) ...@@ -7170,7 +7161,7 @@ fold_ternary (tree expr)
already handled above. */ already handled above. */
if (TREE_CODE (arg0) == BIT_AND_EXPR if (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)) && integer_onep (TREE_OPERAND (arg0, 1))
&& integer_zerop (TREE_OPERAND (t, 2)) && integer_zerop (op2)
&& integer_pow2p (arg1)) && integer_pow2p (arg1))
{ {
tree tem = TREE_OPERAND (arg0, 0); tree tem = TREE_OPERAND (arg0, 0);
...@@ -7187,7 +7178,7 @@ fold_ternary (tree expr) ...@@ -7187,7 +7178,7 @@ fold_ternary (tree expr)
is probably obsolete because the first operand should be a is probably obsolete because the first operand should be a
truth value (that's why we have the two cases above), but let's truth value (that's why we have the two cases above), but let's
leave it in until we can confirm this for all front-ends. */ leave it in until we can confirm this for all front-ends. */
if (integer_zerop (TREE_OPERAND (t, 2)) if (integer_zerop (op2)
&& TREE_CODE (arg0) == NE_EXPR && TREE_CODE (arg0) == NE_EXPR
&& integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (TREE_OPERAND (arg0, 1))
&& integer_pow2p (arg1) && integer_pow2p (arg1)
...@@ -7198,13 +7189,13 @@ fold_ternary (tree expr) ...@@ -7198,13 +7189,13 @@ fold_ternary (tree expr)
TREE_OPERAND (arg0, 0))); TREE_OPERAND (arg0, 0)));
/* Convert A ? B : 0 into A && B if A and B are truth values. */ /* Convert A ? B : 0 into A && B if A and B are truth values. */
if (integer_zerop (TREE_OPERAND (t, 2)) if (integer_zerop (op2)
&& truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1))) && truth_value_p (TREE_CODE (arg1)))
return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1)); return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
/* Convert A ? B : 1 into !A || B if A and B are truth values. */ /* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (TREE_OPERAND (t, 2)) if (integer_onep (op2)
&& truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1))) && truth_value_p (TREE_CODE (arg1)))
{ {
...@@ -7217,30 +7208,27 @@ fold_ternary (tree expr) ...@@ -7217,30 +7208,27 @@ fold_ternary (tree expr)
/* Convert A ? 0 : B into !A && B if A and B are truth values. */ /* Convert A ? 0 : B into !A && B if A and B are truth values. */
if (integer_zerop (arg1) if (integer_zerop (arg1)
&& truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (TREE_OPERAND (t, 2)))) && truth_value_p (TREE_CODE (op2)))
{ {
/* Only perform transformation if ARG0 is easily inverted. */ /* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0); tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR) if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
return fold (build2 (TRUTH_ANDIF_EXPR, type, tem, return fold (build2 (TRUTH_ANDIF_EXPR, type, tem, op2));
TREE_OPERAND (t, 2)));
} }
/* Convert A ? 1 : B into A || B if A and B are truth values. */ /* Convert A ? 1 : B into A || B if A and B are truth values. */
if (integer_onep (arg1) if (integer_onep (arg1)
&& truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (TREE_OPERAND (t, 2)))) && truth_value_p (TREE_CODE (op2)))
return fold (build2 (TRUTH_ORIF_EXPR, type, arg0, return fold (build2 (TRUTH_ORIF_EXPR, type, arg0, op2));
TREE_OPERAND (t, 2)));
return t; return t;
case CALL_EXPR: case CALL_EXPR:
/* Check for a built-in function. */ /* Check for a built-in function. */
if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR if (TREE_CODE (op0) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
== FUNCTION_DECL) && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
{ {
tree tmp = fold_builtin (t, false); tree tmp = fold_builtin (t, false);
if (tmp) if (tmp)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment