> > * 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)
> > + {
>
> actually if OP2 is not NULL for both you can just compare that (and that's
> more correct then).
>
> > + 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);
>
> Why does the representative matter? For a 32bit bitfield if you'd
> have two addresses at 8bit boundary but different you'd make them
> equal this way. Soo ...
>
> > + /* Assume that different FIELD_DECLs never overlap within a
> > + RECORD_TYPE. */
> > + if (type0 == type1 && TREE_CODE (type0) == RECORD_TYPE)
> > + return false;
>
> this isn't really about "overlap", OEP_ADDRESS_OF is just about
> the address (not it's extent).
We discussed this with Jakub, so I have already tested version dropping
both of these, but indeed I should check for OPERAND2. Will do that
now.
Thanks!
Honza
>
> > + 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))
> > + return false;
>
> So this should suffice (on the original fields).
>
> > + }
> > + else
> > + return false;
> > + }
> > flags &= ~OEP_ADDRESS_OF;
> > return OP_SAME_WITH_NULL (2);
> >
> > @@ -3787,9 +3819,28 @@ operand_compare::hash_operand (const_tree t,
> > inchash::hash &hstate,
> > sflags = flags;
> > break;
> >
> > + case COMPONENT_REF:
> > + if (flags & OEP_ADDRESS_OF)
> > + {
> > + tree field = TREE_OPERAND (t, 1);
> > + tree type = DECL_CONTEXT (field);
> > +
> > + if (TREE_CODE (type) == RECORD_TYPE
> > + && DECL_BIT_FIELD_REPRESENTATIVE (field))
> > + field = DECL_BIT_FIELD_REPRESENTATIVE (field);
>
> see above.
>
> > + hash_operand (TREE_OPERAND (t, 0), hstate, flags);
> > + hash_operand (DECL_FIELD_OFFSET (field),
> > + hstate, flags & ~OEP_ADDRESS_OF);
> > + hash_operand (DECL_FIELD_BIT_OFFSET (field),
> > + hstate, flags & ~OEP_ADDRESS_OF);
> > + hash_operand (TREE_OPERAND (t, 2), hstate,
> > + flags & ~OEP_ADDRESS_OF);
>
> otherwise this looks ok.
>
> > + return;
> > + }
> > + break;
> > case ARRAY_REF:
> > case ARRAY_RANGE_REF:
> > - case COMPONENT_REF:
> > case BIT_FIELD_REF:
> > sflags &= ~OEP_ADDRESS_OF;
> > break;
> >
>
> --
> Richard Biener <[email protected]>
> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
> Germany; GF: Felix Imend