}
\f
/* Return nonzero if two operands (typically of the same tree node)
- are necessarily equal. If either argument has side-effects this
- function returns zero. FLAGS modifies behavior as follows:
+ are necessarily equal. FLAGS modifies behavior as follows:
If OEP_ONLY_CONST is set, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
to ensure that global memory is unchanged in between.
If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects,
- not values of expressions. OEP_CONSTANT_ADDRESS_OF in addition to
- OEP_ADDRESS_OF is used for ADDR_EXPR with TREE_CONSTANT flag set and we
- further ignore any side effects on SAVE_EXPRs then. */
+ not values of expressions.
+
+ Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
+ any operand with side effect. This is unnecesarily conservative in the
+ case we know that arg0 and arg1 are in disjoint code paths (such as in
+ ?: operator). In addition OEP_MATCH_SIDE_EFFECTS is used when comparing
+ addresses with TREE_CONSTANT flag set so we know that &var == &var
+ even if var is volatile. */
int
operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
/* Address of INTEGER_CST is not defined; check that we did not forget
- to drop the OEP_ADDRESS_OF/OEP_CONSTANT_ADDRESS_OF flags. */
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)));
+ to drop the OEP_ADDRESS_OF flags. */
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return tree_int_cst_equal (arg0, arg1);
}
they are necessarily equal as well. */
if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
&& (TREE_CODE (arg0) == SAVE_EXPR
- || (flags & OEP_CONSTANT_ADDRESS_OF)
+ || (flags & OEP_MATCH_SIDE_EFFECTS)
|| (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
TREE_STRING_LENGTH (arg0)));
case ADDR_EXPR:
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)));
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
flags | OEP_ADDRESS_OF
- | OEP_CONSTANT_ADDRESS_OF);
+ | OEP_MATCH_SIDE_EFFECTS);
case CONSTRUCTOR:
/* In GIMPLE empty constructors are allowed in initializers of
aggregates. */
/* If either of the pointer (or reference) expressions we are
dereferencing contain a side effect, these cannot be equal,
but their addresses can be. */
- if ((flags & OEP_CONSTANT_ADDRESS_OF) == 0
+ if ((flags & OEP_MATCH_SIDE_EFFECTS) == 0
&& (TREE_SIDE_EFFECTS (arg0)
|| TREE_SIDE_EFFECTS (arg1)))
return 0;
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF))
+ if (!(flags & OEP_ADDRESS_OF)
&& (TYPE_ALIGN (TREE_TYPE (arg0))
!= TYPE_ALIGN (TREE_TYPE (arg1))))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME (0);
case REALPART_EXPR:
case TARGET_MEM_REF:
case MEM_REF:
- if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)))
+ if (!(flags & OEP_ADDRESS_OF))
{
/* Require equal access sizes */
if (TYPE_SIZE (TREE_TYPE (arg0)) != TYPE_SIZE (TREE_TYPE (arg1))
!= TYPE_ALIGN (TREE_TYPE (arg1)))
return 0;
}
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return (OP_SAME (0) && OP_SAME (1)
/* TARGET_MEM_REF require equal extra operands. */
&& (TREE_CODE (arg0) != TARGET_MEM_REF
may have different types but same value here. */
if (!OP_SAME (0))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1))
|| OP_SAME (1))
if (!OP_SAME_WITH_NULL (0)
|| !OP_SAME (1))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
if (!OP_SAME (0))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME (1) && OP_SAME (2);
default:
{
case ADDR_EXPR:
/* Be sure we pass right ADDRESS_OF flag. */
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF
- | OEP_CONSTANT_ADDRESS_OF)));
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0),
flags | OEP_ADDRESS_OF);
return 0;
}
+ /* FIXME: We could skip this test for OEP_MATCH_SIDE_EFFECTS. */
{
unsigned int cef = call_expr_flags (arg0);
if (flags & OEP_PURE_SAME)