return (TREE_CODE (orig) == VECTOR_TYPE
&& tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
- default:
+ case REAL_TYPE:
+ case FIXED_POINT_TYPE:
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ case VOID_TYPE:
return TREE_CODE (type) == TREE_CODE (orig);
+
+ default:
+ return false;
}
}
Note that all these transformations are correct if A is
NaN, since the two alternatives (A and -A) are also NaNs. */
- if ((FLOAT_TYPE_P (TREE_TYPE (arg01))
- ? real_zerop (arg01)
- : integer_zerop (arg01))
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ && (FLOAT_TYPE_P (TREE_TYPE (arg01))
+ ? real_zerop (arg01)
+ : integer_zerop (arg01))
&& ((TREE_CODE (arg2) == NEGATE_EXPR
&& operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
/* In the case that A is of the form X-Y, '-A' (arg2) may
both transformations are correct when A is NaN: A != 0
is then true, and A == 0 is false. */
- if (integer_zerop (arg01) && integer_zerop (arg2))
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ && integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
return pedantic_non_lvalue (fold_convert (type, arg1));
a number and A is not. The conditions in the original
expressions will be false, so all four give B. The min()
and max() versions would give a NaN instead. */
- if (operand_equal_for_comparison_p (arg01, arg2, arg00)
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
+ && operand_equal_for_comparison_p (arg01, arg2, arg00)
/* Avoid these transformations if the COND_EXPR may be used
as an lvalue in the C++ front-end. PR c++/19199. */
&& (in_gimple_form
case VIEW_CONVERT_EXPR:
if (TREE_TYPE (op0) == type)
return op0;
- if (TREE_CODE (op0) == VIEW_CONVERT_EXPR
- || (TREE_CODE (op0) == NOP_EXPR
- && INTEGRAL_TYPE_P (TREE_TYPE (op0))
- && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
- && TYPE_PRECISION (TREE_TYPE (op0))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
+ if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
+ return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+
+ /* For integral conversions with the same precision or pointer
+ conversions use a NOP_EXPR instead. */
+ if ((INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0))
+ /* Do not muck with VIEW_CONVERT_EXPRs that convert from
+ a sub-type to its base type as generated by the Ada FE. */
+ && !TREE_TYPE (TREE_TYPE (op0)))
+ || (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (op0))))
+ return fold_convert (type, op0);
+
+ /* Strip inner integral conversions that do not change the precision. */
+ if ((TREE_CODE (op0) == NOP_EXPR
+ || TREE_CODE (op0) == CONVERT_EXPR)
+ && INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
+ && (TYPE_PRECISION (TREE_TYPE (op0))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+
return fold_view_convert_expr (type, op0);
case NEGATE_EXPR:
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.
Similar logic is present in nonzero_address in rtlanal.h.
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
change *STRICT_OVERFLOW_P. */
-bool
-tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
+static bool
+tree_unary_nonzero_warnv_p (enum tree_code code, tree type, tree op0,
+ bool *strict_overflow_p)
{
- tree type = TREE_TYPE (t);
- bool sub_strict_overflow_p;
+ switch (code)
+ {
+ case ABS_EXPR:
+ return tree_expr_nonzero_warnv_p (op0,
+ strict_overflow_p);
- /* Doing something useful for floating point would need more work. */
- if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
- return false;
+ case NOP_EXPR:
+ {
+ tree inner_type = TREE_TYPE (op0);
+ tree outer_type = type;
- 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);
+ return (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
+ && tree_expr_nonzero_warnv_p (op0,
+ strict_overflow_p));
+ }
+ break;
- case ABS_EXPR:
- return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
+ case NON_LVALUE_EXPR:
+ return tree_expr_nonzero_warnv_p (op0,
strict_overflow_p);
- case INTEGER_CST:
- return !integer_zerop (t);
+ default:
+ 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 PLUS_EXPR:
if (TYPE_OVERFLOW_UNDEFINED (type))
/* With the presence of negative values it is hard
to say something. */
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)
- || !tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
+ || !tree_expr_nonnegative_warnv_p (op1,
&sub_strict_overflow_p))
return false;
/* One of operands must be positive and the other non-negative. */
/* We don't set *STRICT_OVERFLOW_P here: even if this value
overflows, on a twos-complement machine the sum of two
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)
- || tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
+ || tree_expr_nonzero_warnv_p (op1,
strict_overflow_p));
}
break;
case MULT_EXPR:
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)
- && tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
+ && tree_expr_nonzero_warnv_p (op1,
strict_overflow_p))
{
*strict_overflow_p = true;
}
break;
- case NOP_EXPR:
- {
- tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
- tree outer_type = TREE_TYPE (t);
+ case MIN_EXPR:
+ sub_strict_overflow_p = false;
+ if (tree_expr_nonzero_warnv_p (op0,
+ &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)
- && tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
- strict_overflow_p));
- }
+ case MAX_EXPR:
+ sub_strict_overflow_p = false;
+ 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;
+ }
+
+ 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 ADDR_EXPR:
+ case INTEGER_CST:
+ return !integer_zerop (t);
+
+ case ADDR_EXPR:
{
tree base = get_base_address (TREE_OPERAND (t, 0));
}
break;
- case MIN_EXPR:
- 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;
- }
+ default:
break;
+ }
+ return false;
+}
- case MAX_EXPR:
- sub_strict_overflow_p = false;
- if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
- &sub_strict_overflow_p))
- {
- if (sub_strict_overflow_p)
- *strict_overflow_p = true;
+/* 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.
- /* When both operands are nonzero, then MAX must be too. */
- if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
- strict_overflow_p))
- return true;
+ 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. */
- /* MAX where operand 0 is positive is positive. */
- return tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0),
+bool
+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);
- }
- /* MAX where operand 1 is positive is positive. */
- else if (tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
- &sub_strict_overflow_p)
- && tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
- &sub_strict_overflow_p))
- {
- if (sub_strict_overflow_p)
- *strict_overflow_p = true;
- return true;
- }
+ case tcc_constant:
+ case tcc_declaration:
+ case tcc_reference:
+ return tree_single_nonzero_warnv_p (t, strict_overflow_p);
+
+ default:
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 MODIFY_EXPR:
strict_overflow_p);
case SAVE_EXPR:
- case NON_LVALUE_EXPR:
return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
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:
return alloca_call_p (t);