https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87678

--- Comment #5 from Uroš Bizjak <ubizjak at gmail dot com> ---
(In reply to Segher Boessenkool from comment #4)
> It tries twice, first just the substitution, and then that modified with
> the REG_EQUAL.  You know a mem is not often valid in the resulting insn,
> but combine doesn't, and that is not the same thing as not having a mem
> in the inputs anyway!

I have traced this a bit through the combine.c. When creating the combined
pattern in subst (), there is following code at the end:

  for (i = 0; i < 4; i++)
    {
      /* If X is sufficiently simple, don't bother trying to do anything
         with it.  */
      if (code != CONST_INT && code != REG && code != CLOBBER)
        x = combine_simplify_rtx (x, op0_mode, in_dest, in_cond);

      if (GET_CODE (x) == code)
        break;

      code = GET_CODE (x);

      /* We no longer know the original mode of operand 0 since we
         have changed the form of X)  */
      op0_mode = VOIDmode;
    }

And going through combine_simplify_rtx:

    case RTX_COMM_ARITH:
    case RTX_BIN_ARITH:
      temp = simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
      break;

Following this to simplify_binary_operation, we have at the beginning:

  trueop0 = avoid_constant_pool_reference (op0);
  trueop1 = avoid_constant_pool_reference (op1);

  tem = simplify_const_binary_operation (code, mode, trueop0, trueop1);

Here, all hope is lost. avoid_constant_pool_reference *always* simplifies
memory fetch to a constant for constant pool symbol references, defeating all
chances of memory operand propagation.

Reply via email to