Commit b2215d83 by Tom Wood

*** empty log message ***

From-SVN: r1378
parent ac075f04
...@@ -2215,7 +2215,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs) ...@@ -2215,7 +2215,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
rhs); rhs);
} }
/* Subroutine for the following routine: decode a field reference. /* Subroutine for fold_truthop: decode a field reference.
If EXP is a comparison reference, we return the innermost reference. If EXP is a comparison reference, we return the innermost reference.
...@@ -2303,14 +2303,39 @@ all_ones_mask_p (mask, size) ...@@ -2303,14 +2303,39 @@ all_ones_mask_p (mask, size)
size_int (precision - size)), size_int (precision - size)),
size_int (precision - size)), 0); size_int (precision - size)), 0);
} }
/* Subroutine for fold_truthop: determine if an operand is simple enough
to be evaluated unconditionally. */
#ifdef __GNUC__
__inline
#endif
static int
simple_operand_p (exp)
tree exp;
{
/* Strip any conversions that don't change the machine mode. */
while ((TREE_CODE (exp) == NOP_EXPR
|| TREE_CODE (exp) == CONVERT_EXPR)
&& (TYPE_MODE (TREE_TYPE (exp))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
exp = TREE_OPERAND (exp, 0);
return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
|| (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
&& ! TREE_NONLOCAL (exp)));
}
/* Try to optimize a range test. /* Subroutine for fold_truthop: try to optimize a range test.
For example, "i >= 2 && i =< 9" can be done as "(unsigned) (i - 2) <= 7". For example, "i >= 2 && i =< 9" can be done as "(unsigned) (i - 2) <= 7".
JCODE is the logical combination of the two terms. It can be JCODE is the logical combination of the two terms. It is BIT_AND_EXPR
TRUTH_ANDIF_EXPR, TRUTH_AND_EXPR, TRUTH_ORIF_EXPR, or TRUTH_OR_EXPR. (representing TRUTH_ANDIF_EXPR and TRUTH_AND_EXPR) or BIT_IOR_EXPR
TYPE is the type of the result. (representing TRUTH_ORIF_EXPR and TRUTH_OR_EXPR). TYPE is the type of
the result.
VAR is the value being tested. LO_CODE and HI_CODE are the comparison VAR is the value being tested. LO_CODE and HI_CODE are the comparison
operators comparing VAR to LO_CST and HI_CST. LO_CST is known to be no operators comparing VAR to LO_CST and HI_CST. LO_CST is known to be no
...@@ -2328,7 +2353,7 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst) ...@@ -2328,7 +2353,7 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst)
/* See if this is a range test and normalize the constant terms. */ /* See if this is a range test and normalize the constant terms. */
if (jcode == TRUTH_ANDIF_EXPR || jcode == TRUTH_AND_EXPR) if (jcode == BIT_AND_EXPR)
{ {
switch (lo_code) switch (lo_code)
{ {
...@@ -2426,8 +2451,11 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst) ...@@ -2426,8 +2451,11 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst)
const_binop (MINUS_EXPR, hi_cst, lo_cst)))); const_binop (MINUS_EXPR, hi_cst, lo_cst))));
} }
/* Try to merge two comparisons to the same innermost item. /* Find ways of folding logical expressions of LHS and RHS:
Also look for range tests like "ch >= '0' && ch <= '9'". Try to merge two comparisons to the same innermost item.
Look for range tests like "ch >= '0' && ch <= '9'".
Look for combinations of simple terms on machines with expensive branches
and evaluate the RHS unconditionally.
For example, if we have p->a == 2 && p->b == 4 and we can make an For example, if we have p->a == 2 && p->b == 4 and we can make an
object large enough to span both A and B, we can do this with a comparison object large enough to span both A and B, we can do this with a comparison
...@@ -2448,7 +2476,7 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst) ...@@ -2448,7 +2476,7 @@ range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst)
We return the simplified tree or 0 if no optimization is possible. */ We return the simplified tree or 0 if no optimization is possible. */
static tree static tree
merge_component_references (code, truth_type, lhs, rhs) fold_truthop (code, truth_type, lhs, rhs)
enum tree_code code; enum tree_code code;
tree truth_type, lhs, rhs; tree truth_type, lhs, rhs;
{ {
...@@ -2461,9 +2489,9 @@ merge_component_references (code, truth_type, lhs, rhs) ...@@ -2461,9 +2489,9 @@ merge_component_references (code, truth_type, lhs, rhs)
convert EQ_EXPR to NE_EXPR so we need not reject the "wrong" convert EQ_EXPR to NE_EXPR so we need not reject the "wrong"
comparison for one-bit fields. */ comparison for one-bit fields. */
enum tree_code wanted_code enum tree_code wanted_code;
= (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR) ? EQ_EXPR : NE_EXPR;
enum tree_code lcode, rcode; enum tree_code lcode, rcode;
tree ll_arg, lr_arg, rl_arg, rr_arg;
tree ll_inner, lr_inner, rl_inner, rr_inner; tree ll_inner, lr_inner, rl_inner, rr_inner;
int ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos; int ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos;
int rl_bitsize, rl_bitpos, rr_bitsize, rr_bitpos; int rl_bitsize, rl_bitpos, rr_bitsize, rr_bitpos;
...@@ -2473,44 +2501,79 @@ merge_component_references (code, truth_type, lhs, rhs) ...@@ -2473,44 +2501,79 @@ merge_component_references (code, truth_type, lhs, rhs)
enum machine_mode ll_mode, lr_mode, rl_mode, rr_mode; enum machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
enum machine_mode lnmode, rnmode; enum machine_mode lnmode, rnmode;
tree ll_mask, lr_mask, rl_mask, rr_mask; tree ll_mask, lr_mask, rl_mask, rr_mask;
tree l_const = 0, r_const = 0; tree l_const, r_const;
tree type, result; tree type, result;
int first_bit, end_bit; int first_bit, end_bit;
int volatilep = 0; int volatilep;
/* Start by getting the comparison codes and seeing if this looks like /* Start by getting the comparison codes and seeing if this looks like
a range test. Fail if anything is volatile. */ a range test. Fail if anything is volatile. */
if (TREE_SIDE_EFFECTS (lhs)
|| TREE_SIDE_EFFECTS (rhs))
return 0;
lcode = TREE_CODE (lhs); lcode = TREE_CODE (lhs);
rcode = TREE_CODE (rhs); rcode = TREE_CODE (rhs);
if (TREE_SIDE_EFFECTS (lhs) if (TREE_CODE_CLASS (lcode) != '<'
|| TREE_SIDE_EFFECTS (rhs)
|| TREE_CODE_CLASS (lcode) != '<'
|| TREE_CODE_CLASS (rcode) != '<') || TREE_CODE_CLASS (rcode) != '<')
return 0; return 0;
if (TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST ? BIT_AND_EXPR : BIT_IOR_EXPR);
&& operand_equal_p (TREE_OPERAND (lhs, 0),
TREE_OPERAND (rhs, 0), 0)) ll_arg = TREE_OPERAND (lhs, 0);
lr_arg = TREE_OPERAND (lhs, 1);
rl_arg = TREE_OPERAND (rhs, 0);
rr_arg = TREE_OPERAND (rhs, 1);
if (TREE_CODE (lr_arg) == INTEGER_CST
&& TREE_CODE (rr_arg) == INTEGER_CST
&& operand_equal_p (ll_arg, rl_arg, 0))
{ {
if (tree_int_cst_lt (TREE_OPERAND (lhs, 1), TREE_OPERAND (rhs, 1))) if (tree_int_cst_lt (lr_arg, rr_arg))
result = range_test (code, truth_type, lcode, rcode, result = range_test (code, truth_type, lcode, rcode,
TREE_OPERAND (lhs, 0), ll_arg, lr_arg, rr_arg);
TREE_OPERAND (lhs, 1),
TREE_OPERAND (rhs, 1));
else else
result = range_test (code, truth_type, rcode, lcode, result = range_test (code, truth_type, rcode, lcode,
TREE_OPERAND (lhs, 0), ll_arg, rr_arg, lr_arg);
TREE_OPERAND (rhs, 1),
TREE_OPERAND (lhs, 1));
/* If this isn't a range test, it also isn't a comparison that /* If this isn't a range test, it also isn't a comparison that
can be merged. */ can be merged. However, it wins to evaluate the RHS unconditionally
on machines with expensive branches. */
if (result == 0 && BRANCH_COST >= 2)
{
if (TREE_CODE (ll_arg) != VAR_DECL
&& TREE_CODE (ll_arg) != PARM_DECL)
{
/* Avoid evaluating the variable part twice. */
ll_arg = save_expr (ll_arg);
lhs = build (lcode, TREE_TYPE (lhs), ll_arg, lr_arg);
rhs = build (rcode, TREE_TYPE (rhs), ll_arg, rr_arg);
}
return build (code, truth_type, lhs, rhs);
}
return result; return result;
} }
/* If the RHS can be evaluated unconditionally and all operands are
simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison
that can be merged. */
/* @@ I'm not sure it wins on the m88110 to do this if the comparisons
are with zero (tmw). */
if (BRANCH_COST >= 2
&& TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
&& simple_operand_p (rl_arg)
&& simple_operand_p (ll_arg)
&& simple_operand_p (rr_arg)
&& simple_operand_p (lr_arg))
return build (code, truth_type, lhs, rhs);
/* See if the comparisons can be merged. Then get all the parameters for /* See if the comparisons can be merged. Then get all the parameters for
each side. */ each side. */
...@@ -2518,16 +2581,17 @@ merge_component_references (code, truth_type, lhs, rhs) ...@@ -2518,16 +2581,17 @@ merge_component_references (code, truth_type, lhs, rhs)
|| (rcode != EQ_EXPR && rcode != NE_EXPR)) || (rcode != EQ_EXPR && rcode != NE_EXPR))
return 0; return 0;
ll_inner = decode_field_reference (TREE_OPERAND (lhs, 0), volatilep = 0;
ll_inner = decode_field_reference (ll_arg,
&ll_bitsize, &ll_bitpos, &ll_mode, &ll_bitsize, &ll_bitpos, &ll_mode,
&ll_unsignedp, &volatilep, &ll_mask); &ll_unsignedp, &volatilep, &ll_mask);
lr_inner = decode_field_reference (TREE_OPERAND (lhs, 1), lr_inner = decode_field_reference (lr_arg,
&lr_bitsize, &lr_bitpos, &lr_mode, &lr_bitsize, &lr_bitpos, &lr_mode,
&lr_unsignedp, &volatilep, &lr_mask); &lr_unsignedp, &volatilep, &lr_mask);
rl_inner = decode_field_reference (TREE_OPERAND (rhs, 0), rl_inner = decode_field_reference (rl_arg,
&rl_bitsize, &rl_bitpos, &rl_mode, &rl_bitsize, &rl_bitpos, &rl_mode,
&rl_unsignedp, &volatilep, &rl_mask); &rl_unsignedp, &volatilep, &rl_mask);
rr_inner = decode_field_reference (TREE_OPERAND (rhs, 1), rr_inner = decode_field_reference (rr_arg,
&rr_bitsize, &rr_bitpos, &rr_mode, &rr_bitsize, &rr_bitpos, &rr_mode,
&rr_unsignedp, &volatilep, &rr_mask); &rr_unsignedp, &volatilep, &rr_mask);
...@@ -2539,16 +2603,20 @@ merge_component_references (code, truth_type, lhs, rhs) ...@@ -2539,16 +2603,20 @@ merge_component_references (code, truth_type, lhs, rhs)
|| ! operand_equal_p (ll_inner, rl_inner, 0)) || ! operand_equal_p (ll_inner, rl_inner, 0))
return 0; return 0;
if (TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST if (TREE_CODE (lr_arg) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST) && TREE_CODE (rr_arg) == INTEGER_CST)
l_const = TREE_OPERAND (lhs, 1), r_const = TREE_OPERAND (rhs, 1); l_const = lr_arg, r_const = rr_arg;
else if (lr_inner == 0 || rr_inner == 0 else if (lr_inner == 0 || rr_inner == 0
|| ! operand_equal_p (lr_inner, rr_inner, 0)) || ! operand_equal_p (lr_inner, rr_inner, 0))
return 0; return 0;
else
l_const = r_const = 0;
/* If either comparison code is not correct for our logical operation, /* If either comparison code is not correct for our logical operation,
fail. However, we can convert a one-bit comparison against zero into fail. However, we can convert a one-bit comparison against zero into
the opposite comparison against that bit being set in the field. */ the opposite comparison against that bit being set in the field. */
wanted_code = (code == BIT_AND_EXPR ? EQ_EXPR : NE_EXPR);
if (lcode != wanted_code) if (lcode != wanted_code)
{ {
if (l_const && integer_zerop (l_const) && integer_pow2p (ll_mask)) if (l_const && integer_zerop (l_const) && integer_pow2p (ll_mask))
...@@ -3456,13 +3524,13 @@ fold (expr) ...@@ -3456,13 +3524,13 @@ fold (expr)
{ {
if (TREE_CODE (arg0) == code) if (TREE_CODE (arg0) == code)
{ {
tem = merge_component_references (code, type, tem = fold_truthop (code, type,
TREE_OPERAND (arg0, 1), arg1); TREE_OPERAND (arg0, 1), arg1);
if (tem) if (tem)
return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
} }
tem = merge_component_references (code, type, arg0, arg1); tem = fold_truthop (code, type, arg0, arg1);
if (tem) if (tem)
return tem; return tem;
} }
......
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