Hi,
with ipa-icf we often run into problem that operand_equal_p does not
match ADDR_EXPR that take address of fields from two different instances
of same class (at ideantical offsets).  Similar problem can also happen
for record types with LTO if they did not get tree merged.
This patch makes fold-const to compare offsets rather then pinter
equality of FIELD_DECLs. This is done in OEP_ADDRESS_OF mode only sinc
it is not TBAA safe and the TBAA side should be correctly solved by my
ICF patch.

Bootstrapped/regtested x86_64-linux, OK?

Honza

        * 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))
+                   return false;
+               }
+             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);
+
+                 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);
+                 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