Hi,
this is updated patch I am re-testing and plan to commit if it suceeds.

        * fold-const.c (operand_compare::operand_equal_p): Compare
        offsets of fields in component_refs when comparing addresses.
        (operand_compare::hash_operand): Likewise.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c47557daeba..273ee25ceda 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3312,11 +3312,36 @@ 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;
-         flags &= ~OEP_ADDRESS_OF;
-         return OP_SAME_WITH_NULL (2);
+         /* 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)
+               {
+                 if (TREE_OPERAND (arg0, 2)
+                     || TREE_OPERAND (arg1, 2))
+                   {
+                     flags &= ~OEP_ADDRESS_OF;
+                     return OP_SAME_WITH_NULL (2);
+                   }
+                 tree field0 = TREE_OPERAND (arg0, 1);
+                 tree field1 = TREE_OPERAND (arg1, 1);
+
+                 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;
+               }
+             else
+               return false;
+           }
+         return true;
 
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
@@ -3787,9 +3812,26 @@ operand_compare::hash_operand (const_tree t, 
inchash::hash &hstate,
              sflags = flags;
              break;
 
+           case COMPONENT_REF:
+             if (sflags & OEP_ADDRESS_OF)
+               {
+                 hash_operand (TREE_OPERAND (t, 0), hstate, flags);
+                 if (TREE_OPERAND (t, 2))
+                   hash_operand (TREE_OPERAND (t, 2), hstate,
+                                 flags & ~OEP_ADDRESS_OF);
+                 else
+                   {
+                     tree field = TREE_OPERAND (t, 1);
+                     hash_operand (DECL_FIELD_OFFSET (field),
+                                   hstate, flags & ~OEP_ADDRESS_OF);
+                     hash_operand (DECL_FIELD_BIT_OFFSET (field),
+                                   hstate, flags & ~OEP_ADDRESS_OF);
+                   }
+                 return;
+               }
+             break;
            case ARRAY_REF:
            case ARRAY_RANGE_REF:
-           case COMPONENT_REF:
            case BIT_FIELD_REF:
              sflags &= ~OEP_ADDRESS_OF;
              break;

Reply via email to