https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69553
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> --- So the issue is that &MEM[(const struct B[2] &)p1_2(D)][1] and &MEM[(const int[2] &)p1_2(D)][1] are considered equal even though we have int[] vs. B[] and thus different element sizes and different offsets (but same array indices) here. For COMPONENT_REFs we compare the FIELD_DECL but for ARRAY_REFs and also for IMAGPART_EXPR we fail to consider the element size. Not that comparing TYPE_PRECISION on MEM_REFs of ARRAY_TYPE makes any sense, or TYPE_UNSIGNED. So the old code had bugs as well here (consider array types with different low bound). Index: fold-const.c =================================================================== --- fold-const.c (revision 233447) +++ fold-const.c (working copy) @@ -3008,8 +3008,15 @@ operand_equal_p (const_tree arg0, const_ flags &= ~OEP_ADDRESS_OF; return OP_SAME (0); - case REALPART_EXPR: case IMAGPART_EXPR: + /* Require the same offset. */ + if (!operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)), + TYPE_SIZE (TREE_TYPE (arg1)), + flags & ~OEP_ADDRESS_OF))) + return 0; + + /* Fallthru. */ + case REALPART_EXPR: case VIEW_CONVERT_EXPR: return OP_SAME (0); @@ -3049,17 +3056,24 @@ operand_equal_p (const_tree arg0, const_ case ARRAY_REF: case ARRAY_RANGE_REF: - /* Operands 2 and 3 may be null. - Compare the array index by value if it is constant first as we - may have different types but same value here. */ if (!OP_SAME (0)) return 0; flags &= ~OEP_ADDRESS_OF; + /* Compare the array index by value if it is constant first as we + may have different types but same value here. + Compare low bound and element size as with OEP_ADDRESS_OF + we have to account for the offset of the ref. */ return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1)) || OP_SAME (1)) - && OP_SAME_WITH_NULL (2) - && OP_SAME_WITH_NULL (3)); + && operand_equal_p (array_ref_low_bound + (CONST_CAST_TREE (arg0)), + array_ref_low_bound + (CONST_CAST_TREE (arg1)), flags) + && operand_equal_p (array_ref_element_size + (CONST_CAST_TREE (arg0)), + array_ref_element_size + (CONST_CAST_TREE (arg1)), flags)); case COMPONENT_REF: /* Handle operand 2 the same as for ARRAY_REF. Operand 0