Commit 74dd418c by Rafael Avila de Espindola Committed by Rafael Espindola

fold-const.c (tree_unary_nonzero_warnv_p): New.

2008-03-04  Rafael Espindola  <espindola@google.com>

	   * fold-const.c (tree_unary_nonzero_warnv_p): New.
	   (tree_binary_nonzero_warnv_p): New.
	   (tree_single_nonzero_warnv_p): New.
	   (tree_expr_nonzero_warnv_p): Redefine using the new functions.

From-SVN: r132866
parent 5ce0e197
2008-03-04 Rafael Espindola <espindola@google.com>
* fold-const.c (tree_unary_nonzero_warnv_p): New.
(tree_binary_nonzero_warnv_p): New.
(tree_single_nonzero_warnv_p): New.
(tree_expr_nonzero_warnv_p): Redefine using the new functions.
2008-03-04 Uros Bizjak <ubizjak@gmail.com> 2008-03-04 Uros Bizjak <ubizjak@gmail.com>
PR middle-end/35456 PR middle-end/35456
......
...@@ -14409,7 +14409,8 @@ tree_expr_nonnegative_p (tree t) ...@@ -14409,7 +14409,8 @@ tree_expr_nonnegative_p (tree t)
return ret; return ret;
} }
/* Return true when T is an address and is known to be nonzero.
/* Return true when (CODE OP0) is an address and is known to be nonzero.
For floating point we further ensure that T is not denormal. For floating point we further ensure that T is not denormal.
Similar logic is present in nonzero_address in rtlanal.h. Similar logic is present in nonzero_address in rtlanal.h.
...@@ -14417,30 +14418,55 @@ tree_expr_nonnegative_p (tree t) ...@@ -14417,30 +14418,55 @@ tree_expr_nonnegative_p (tree t)
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
change *STRICT_OVERFLOW_P. */ change *STRICT_OVERFLOW_P. */
bool static bool
tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) tree_unary_nonzero_warnv_p (enum tree_code code, tree type, tree op0,
bool *strict_overflow_p)
{ {
tree type = TREE_TYPE (t); switch (code)
bool sub_strict_overflow_p; {
case ABS_EXPR:
return tree_expr_nonzero_warnv_p (op0,
strict_overflow_p);
/* Doing something useful for floating point would need more work. */ case NOP_EXPR:
if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) {
return false; tree inner_type = TREE_TYPE (op0);
tree outer_type = type;
switch (TREE_CODE (t)) return (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
{ && tree_expr_nonzero_warnv_p (op0,
case SSA_NAME: strict_overflow_p));
/* Query VRP to see if it has recorded any information about }
the range of this object. */ break;
return ssa_name_nonzero_p (t);
case ABS_EXPR: case NON_LVALUE_EXPR:
return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), return tree_expr_nonzero_warnv_p (op0,
strict_overflow_p); strict_overflow_p);
case INTEGER_CST: default:
return !integer_zerop (t); break;
}
return false;
}
/* Return true when (CODE OP0 OP1) is an address and is known to be nonzero.
For floating point we further ensure that T is not denormal.
Similar logic is present in nonzero_address in rtlanal.h.
If the return value is based on the assumption that signed overflow
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
change *STRICT_OVERFLOW_P. */
static bool
tree_binary_nonzero_warnv_p (enum tree_code code,
tree type,
tree op0,
tree op1, bool *strict_overflow_p)
{
bool sub_strict_overflow_p;
switch (code)
{
case POINTER_PLUS_EXPR: case POINTER_PLUS_EXPR:
case PLUS_EXPR: case PLUS_EXPR:
if (TYPE_OVERFLOW_UNDEFINED (type)) if (TYPE_OVERFLOW_UNDEFINED (type))
...@@ -14448,18 +14474,18 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) ...@@ -14448,18 +14474,18 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
/* With the presence of negative values it is hard /* With the presence of negative values it is hard
to say something. */ to say something. */
sub_strict_overflow_p = false; sub_strict_overflow_p = false;
if (!tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0), if (!tree_expr_nonnegative_warnv_p (op0,
&sub_strict_overflow_p) &sub_strict_overflow_p)
|| !tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1), || !tree_expr_nonnegative_warnv_p (op1,
&sub_strict_overflow_p)) &sub_strict_overflow_p))
return false; return false;
/* One of operands must be positive and the other non-negative. */ /* One of operands must be positive and the other non-negative. */
/* We don't set *STRICT_OVERFLOW_P here: even if this value /* We don't set *STRICT_OVERFLOW_P here: even if this value
overflows, on a twos-complement machine the sum of two overflows, on a twos-complement machine the sum of two
nonnegative numbers can never be zero. */ nonnegative numbers can never be zero. */
return (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), return (tree_expr_nonzero_warnv_p (op0,
strict_overflow_p) strict_overflow_p)
|| tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1), || tree_expr_nonzero_warnv_p (op1,
strict_overflow_p)); strict_overflow_p));
} }
break; break;
...@@ -14467,9 +14493,9 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) ...@@ -14467,9 +14493,9 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
case MULT_EXPR: case MULT_EXPR:
if (TYPE_OVERFLOW_UNDEFINED (type)) if (TYPE_OVERFLOW_UNDEFINED (type))
{ {
if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), if (tree_expr_nonzero_warnv_p (op0,
strict_overflow_p) strict_overflow_p)
&& tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1), && tree_expr_nonzero_warnv_p (op1,
strict_overflow_p)) strict_overflow_p))
{ {
*strict_overflow_p = true; *strict_overflow_p = true;
...@@ -14478,18 +14504,83 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) ...@@ -14478,18 +14504,83 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
} }
break; break;
case NOP_EXPR: case MIN_EXPR:
{ sub_strict_overflow_p = false;
tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0)); if (tree_expr_nonzero_warnv_p (op0,
tree outer_type = TREE_TYPE (t); &sub_strict_overflow_p)
&& tree_expr_nonzero_warnv_p (op1,
&sub_strict_overflow_p))
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
}
break;
return (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type) case MAX_EXPR:
&& tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), sub_strict_overflow_p = false;
strict_overflow_p)); if (tree_expr_nonzero_warnv_p (op0,
} &sub_strict_overflow_p))
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
/* When both operands are nonzero, then MAX must be too. */
if (tree_expr_nonzero_warnv_p (op1,
strict_overflow_p))
return true;
/* MAX where operand 0 is positive is positive. */
return tree_expr_nonnegative_warnv_p (op0,
strict_overflow_p);
}
/* MAX where operand 1 is positive is positive. */
else if (tree_expr_nonzero_warnv_p (op1,
&sub_strict_overflow_p)
&& tree_expr_nonnegative_warnv_p (op1,
&sub_strict_overflow_p))
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
return true;
}
break;
case BIT_IOR_EXPR:
return (tree_expr_nonzero_warnv_p (op1,
strict_overflow_p)
|| tree_expr_nonzero_warnv_p (op0,
strict_overflow_p));
default:
break; break;
}
case ADDR_EXPR: return false;
}
/* Return true when T is an address and is known to be nonzero.
For floating point we further ensure that T is not denormal.
Similar logic is present in nonzero_address in rtlanal.h.
If the return value is based on the assumption that signed overflow
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
change *STRICT_OVERFLOW_P. */
static bool
tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
{
bool sub_strict_overflow_p;
switch (TREE_CODE (t))
{
case SSA_NAME:
/* Query VRP to see if it has recorded any information about
the range of this object. */
return ssa_name_nonzero_p (t);
case INTEGER_CST:
return !integer_zerop (t);
case ADDR_EXPR:
{ {
tree base = get_base_address (TREE_OPERAND (t, 0)); tree base = get_base_address (TREE_OPERAND (t, 0));
...@@ -14520,46 +14611,75 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) ...@@ -14520,46 +14611,75 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
} }
break; break;
case MIN_EXPR: default:
sub_strict_overflow_p = false;
if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
&sub_strict_overflow_p)
&& tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
&sub_strict_overflow_p))
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
}
break; break;
}
return false;
}
case MAX_EXPR: /* Return true when T is an address and is known to be nonzero.
sub_strict_overflow_p = false; For floating point we further ensure that T is not denormal.
if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), Similar logic is present in nonzero_address in rtlanal.h.
&sub_strict_overflow_p))
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
/* When both operands are nonzero, then MAX must be too. */ If the return value is based on the assumption that signed overflow
if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1), is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
strict_overflow_p)) change *STRICT_OVERFLOW_P. */
return true;
/* MAX where operand 0 is positive is positive. */ bool
return tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0), tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
{
tree type = TREE_TYPE (t);
enum tree_code code;
/* Doing something useful for floating point would need more work. */
if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
return false;
code = TREE_CODE (t);
switch (TREE_CODE_CLASS (code))
{
case tcc_unary:
return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
strict_overflow_p);
case tcc_binary:
case tcc_comparison:
return tree_binary_nonzero_warnv_p (code, type,
TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1),
strict_overflow_p); strict_overflow_p);
} case tcc_constant:
/* MAX where operand 1 is positive is positive. */ case tcc_declaration:
else if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1), case tcc_reference:
&sub_strict_overflow_p) return tree_single_nonzero_warnv_p (t, strict_overflow_p);
&& tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
&sub_strict_overflow_p)) default:
{
if (sub_strict_overflow_p)
*strict_overflow_p = true;
return true;
}
break; break;
}
switch (code)
{
case TRUTH_NOT_EXPR:
return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
strict_overflow_p);
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
return tree_binary_nonzero_warnv_p (code, type,
TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1),
strict_overflow_p);
case COND_EXPR:
case CONSTRUCTOR:
case OBJ_TYPE_REF:
case ASSERT_EXPR:
case ADDR_EXPR:
case WITH_SIZE_EXPR:
case EXC_PTR_EXPR:
case SSA_NAME:
case FILTER_EXPR:
return tree_single_nonzero_warnv_p (t, strict_overflow_p);
case COMPOUND_EXPR: case COMPOUND_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
...@@ -14569,16 +14689,9 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) ...@@ -14569,16 +14689,9 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
strict_overflow_p); strict_overflow_p);
case SAVE_EXPR: case SAVE_EXPR:
case NON_LVALUE_EXPR:
return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0), return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
strict_overflow_p); strict_overflow_p);
case BIT_IOR_EXPR:
return (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
strict_overflow_p)
|| tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
strict_overflow_p));
case CALL_EXPR: case CALL_EXPR:
return alloca_call_p (t); return alloca_call_p (t);
......
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