Commit ef659ec0 by Tom Wood

*** empty log message ***

From-SVN: r1301
parent 5a7ec9d9
...@@ -2304,7 +2304,125 @@ all_ones_mask_p (mask, size) ...@@ -2304,7 +2304,125 @@ all_ones_mask_p (mask, size)
size_int (precision - size)), 0); size_int (precision - size)), 0);
} }
/* Try to optimize a range test.
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
TRUTH_ANDIF_EXPR, TRUTH_AND_EXPR, TRUTH_ORIF_EXPR, or TRUTH_OR_EXPR.
TYPE is the type of the result.
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
larger than HI_CST (they may be equal).
We return the simplified tree or 0 if no optimization is possible. */
tree
range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst)
enum tree_code jcode, lo_code, hi_code;
tree type, var, lo_cst, hi_cst;
{
tree utype;
enum tree_code rcode;
/* See if this is a range test and normalize the constant terms. */
if (jcode == TRUTH_ANDIF_EXPR || jcode == TRUTH_AND_EXPR)
{
switch (lo_code)
{
case NE_EXPR:
/* See if we have VAR != CST && VAR != CST+1. */
if (! (hi_code == NE_EXPR
&& TREE_INT_CST_LOW (hi_cst) - TREE_INT_CST_LOW (lo_cst) == 1
&& tree_int_cst_equal (integer_one_node,
const_binop (MINUS_EXPR,
hi_cst, lo_cst))))
return 0;
rcode = GT_EXPR;
break;
case GT_EXPR:
case GE_EXPR:
if (hi_code == LT_EXPR)
hi_cst = const_binop (MINUS_EXPR, hi_cst, integer_one_node);
else if (hi_code != LE_EXPR)
return 0;
if (lo_code == GT_EXPR)
lo_cst = const_binop (PLUS_EXPR, lo_cst, integer_one_node);
/* We now have VAR >= LO_CST && VAR <= HI_CST. */
rcode = LE_EXPR;
break;
default:
return 0;
}
}
else
{
switch (lo_code)
{
case EQ_EXPR:
/* See if we have VAR == CST || VAR == CST+1. */
if (! (hi_code == EQ_EXPR
&& TREE_INT_CST_LOW (hi_cst) - TREE_INT_CST_LOW (lo_cst) == 1
&& tree_int_cst_equal (integer_one_node,
const_binop (MINUS_EXPR,
hi_cst, lo_cst))))
return 0;
rcode = LE_EXPR;
break;
case LE_EXPR:
case LT_EXPR:
if (hi_code == GE_EXPR)
hi_cst = const_binop (MINUS_EXPR, hi_cst, integer_one_node);
else if (hi_code != GT_EXPR)
return 0;
if (lo_code == LE_EXPR)
lo_cst = const_binop (PLUS_EXPR, lo_cst, integer_one_node);
/* We now have VAR < LO_CST || VAR > HI_CST. */
rcode = GT_EXPR;
break;
default:
return 0;
}
}
/* When normalizing, it is possible to both increment the smaller constant
and decrement the larger constant. See if they are still ordered. */
if (tree_int_cst_lt (lo_cst, hi_cst))
return 0;
/* The range test is invalid if subtracting the two constants results
in overflow. This can happen in traditional mode. */
if (! int_fits_type_p (hi_cst, TREE_TYPE (var))
|| ! int_fits_type_p (lo_cst, TREE_TYPE (var)))
return 0;
utype = TREE_TYPE (var);
if (! TREE_UNSIGNED (utype))
{
utype = unsigned_type (utype);
var = convert (utype, var);
}
return fold (convert (type,
build (rcode, utype,
build (MINUS_EXPR, utype, var, lo_cst),
const_binop (MINUS_EXPR, hi_cst, lo_cst))));
}
/* Try to merge two comparisons to the same innermost item. /* Try to merge two comparisons to the same innermost item.
Also look for range tests like "ch >= '0' && ch <= '9'".
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
...@@ -2355,15 +2473,44 @@ merge_component_references (code, truth_type, lhs, rhs) ...@@ -2355,15 +2473,44 @@ merge_component_references (code, truth_type, lhs, rhs)
int first_bit, end_bit; int first_bit, end_bit;
int volatilep = 0; int volatilep = 0;
/* Start by getting the comparison codes and seeing if we may be able /* Start by getting the comparison codes and seeing if this looks like
to do something. Then get all the parameters for each side. Fail a range test. Fail if anything is volatile. */
if anything is volatile. */
lcode = TREE_CODE (lhs); lcode = TREE_CODE (lhs);
rcode = TREE_CODE (rhs); rcode = TREE_CODE (rhs);
if (TREE_SIDE_EFFECTS (lhs)
|| TREE_SIDE_EFFECTS (rhs)
|| TREE_CODE_CLASS (lcode) != '<'
|| TREE_CODE_CLASS (rcode) != '<')
return 0;
if (TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
&& operand_equal_p (TREE_OPERAND (lhs, 0),
TREE_OPERAND (rhs, 0), 0))
{
if (tree_int_cst_lt (TREE_OPERAND (lhs, 1), TREE_OPERAND (rhs, 1)))
result = range_test (code, truth_type, lcode, rcode,
TREE_OPERAND (lhs, 0),
TREE_OPERAND (lhs, 1),
TREE_OPERAND (rhs, 1));
else
result = range_test (code, truth_type, rcode, lcode,
TREE_OPERAND (lhs, 0),
TREE_OPERAND (rhs, 1),
TREE_OPERAND (lhs, 1));
/* If this isn't a range test, it also isn't a comparison that
can be merged. */
return result;
}
/* See if the comparisons can be merged. Then get all the parameters for
each side. */
if ((lcode != EQ_EXPR && lcode != NE_EXPR) if ((lcode != EQ_EXPR && lcode != NE_EXPR)
|| (rcode != EQ_EXPR && rcode != NE_EXPR) || (rcode != EQ_EXPR && rcode != NE_EXPR))
|| TREE_SIDE_EFFECTS (lhs) || TREE_SIDE_EFFECTS (rhs))
return 0; return 0;
ll_inner = decode_field_reference (TREE_OPERAND (lhs, 0), ll_inner = decode_field_reference (TREE_OPERAND (lhs, 0),
......
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