https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94216
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #1) > I wonder if we shouldn't do: > --- gcc/fold-const.c.jj 2020-03-18 12:47:36.000000000 +0100 > +++ gcc/fold-const.c 2020-03-18 17:34:14.586455801 +0100 > @@ -82,6 +82,7 @@ along with GCC; see the file COPYING3. > #include "attribs.h" > #include "tree-vector-builder.h" > #include "vec-perm-indices.h" > +#include "tree-ssa.h" > > /* Nonzero if we are folding constants inside an initializer; zero > otherwise. */ > @@ -10262,6 +10263,10 @@ fold_binary_loc (location_t loc, enum tr > switch (code) > { > case MEM_REF: > + STRIP_USELESS_TYPE_CONVERSION (arg0); We already applied STRIP_NOPS to arg0 > + if (arg0 != op0) > + return fold_build2 (MEM_REF, type, arg0, op1); > + > /* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2]. */ > if (TREE_CODE (arg0) == ADDR_EXPR > && TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF) > to catch all similar issues. Otherwise, we'd need to strip the useless type > conversion at least in the case which triggers this: > return fold_build2 (MEM_REF, type, > build_fold_addr_expr (base), > int_const_binop (PLUS_EXPR, arg1, > size_int (coffset))); > a few lines below this, where build_fold_addr_expr now returns a NOP_EXPR > that we really want to strip again, even when op0 wasn't a NOP_EXPR. True. But note there could be a not useless type conversion here, for example for MEM<void (*)()> [&a] and void *a for example. Here I think the better fix is (again) to use build1 and then in case the base was a MEM_REF recurse to the preceeding pattern. I'm testing such a patch.