https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89698
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- So the issue may be that operand_equal_p (*(struct A *) VIEW_CONVERT_EXPR<void *>(vp), *(struct B *) VIEW_CONVERT_EXPR<void *>(vp), 0) == 1 where for INDIRECT_REF we just do case INDIRECT_REF: if (!(flags & OEP_ADDRESS_OF) && (TYPE_ALIGN (TREE_TYPE (arg0)) != TYPE_ALIGN (TREE_TYPE (arg1)))) return 0; flags &= ~OEP_ADDRESS_OF; return OP_SAME (0); and OP_SAME happily strips the pointer nop-conversion. For MEM_REF we do case MEM_REF: if (!(flags & OEP_ADDRESS_OF)) { ... /* Verify that access happens in similar types. */ if (!types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))) return 0; /* Verify that accesses are TBAA compatible. */ if (!alias_ptr_types_compatible_p (TREE_TYPE (TREE_OPERAND (arg0, 1)), TREE_TYPE (TREE_OPERAND (arg1, 1))) || (MR_DEPENDENCE_CLIQUE (arg0) != MR_DEPENDENCE_CLIQUE (arg1)) || (MR_DEPENDENCE_BASE (arg0) != MR_DEPENDENCE_BASE (arg1))) return 0; so even a basic check that the dereferences access compatible types would fix this. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 269641) +++ gcc/fold-const.c (working copy) @@ -3220,10 +3220,16 @@ operand_equal_p (const_tree arg0, const_ switch (TREE_CODE (arg0)) { case INDIRECT_REF: - if (!(flags & OEP_ADDRESS_OF) - && (TYPE_ALIGN (TREE_TYPE (arg0)) - != TYPE_ALIGN (TREE_TYPE (arg1)))) - return 0; + if (!(flags & OEP_ADDRESS_OF)) + { + if (TYPE_ALIGN (TREE_TYPE (arg0)) + != TYPE_ALIGN (TREE_TYPE (arg1))) + return 0; + /* Verify that the access types are compatible. */ + if (TYPE_MAIN_VARIANT (TREE_TYPE (arg0)) + != TYPE_MAIN_VARIANT (TREE_TYPE (arg1))) + return 0; + } flags &= ~OEP_ADDRESS_OF; return OP_SAME (0);