> > * 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 <rguent...@suse.de> > SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, > Germany; GF: Felix Imend