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.