On Thu, Nov 12, 2020 at 10:36:28AM +0100, Jan Hubicka wrote:
>       * fold-const.c (operand_compare::operand_equal_p): When comparing 
> addresses
>       look info field offsets for COMPONENT_REFs.
>       (operand_compare::hash_operand): Likewise.
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index c47557daeba..a4e8cccb1b7 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -3312,9 +3312,41 @@ operand_compare::operand_equal_p (const_tree arg0, 
> const_tree arg1,
>       case COMPONENT_REF:
>         /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
>            may be NULL when we're called to compare MEM_EXPRs.  */
> -       if (!OP_SAME_WITH_NULL (0)
> -           || !OP_SAME (1))
> +       if (!OP_SAME_WITH_NULL (0))
>           return false;
> +       /* Most of time we only need to compare FIELD_DECLs for equality.
> +          However when determining address look into actual offsets.
> +          These may match for unions and unshared record types.  */
> +       if (!OP_SAME (1))
> +         {
> +           if (flags & OEP_ADDRESS_OF)
> +             {
> +               tree field0 = TREE_OPERAND (arg0, 1);
> +               tree field1 = TREE_OPERAND (arg1, 1);
> +               tree type0 = DECL_CONTEXT (field0);
> +               tree type1 = DECL_CONTEXT (field1);
> +
> +               if (TREE_CODE (type0) == RECORD_TYPE
> +                   && DECL_BIT_FIELD_REPRESENTATIVE (field0))
> +                 field0 = DECL_BIT_FIELD_REPRESENTATIVE (field0);
> +               if (TREE_CODE (type1) == RECORD_TYPE
> +                   && DECL_BIT_FIELD_REPRESENTATIVE (field1))
> +                 field1 = DECL_BIT_FIELD_REPRESENTATIVE (field1);
> +               /* Assume that different FIELD_DECLs never overlap within a
> +                  RECORD_TYPE.  */
> +               if (type0 == type1 && TREE_CODE (type0) == RECORD_TYPE)
> +                 return false;
> +               if (!operand_equal_p (DECL_FIELD_OFFSET (field0),
> +                                     DECL_FIELD_OFFSET (field1),
> +                                     flags & ~OEP_ADDRESS_OF)
> +                   || !operand_equal_p (DECL_FIELD_BIT_OFFSET (field0),
> +                                        DECL_FIELD_BIT_OFFSET (field1),
> +                                        flags & ~OEP_ADDRESS_OF))

If it is an address, why do you need to handle
DECL_BIT_FIELD_REPRESENTATIVE?  Taking address of a bit-field is not allowed.
Perhaps just return false if the fields are bit-fields (or assert they
aren't), and just compare DECL_FIELD*OFFSET of the fields themselves?

        Jakub

Reply via email to