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.