This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Using an automodified register twice in the same insn


Can a register be used more than once in an insn if one of those uses is
an auto-modification?  I've looked at this several times in the past and
never come to a conclusion.  doc/rtl.texi says:

  If a register used as the operand of these [auto-modification]
  expressions is used in another address in an insn, the original value
  of the register is used.  Uses of the register outside of an address
  are not permitted within the same insn as a use in an embedded side
  effect expression because such insns behave differently on different
  machines and hence must be treated as ambiguous and disallowed.

which suggests that, for example, (mem (reg X)) and (mem (pre_dec (reg X)))
can be used in the same insn, with the former reading the unmodified value
of X.  However, operands_match_p works differently.  It says that:

  a) an output (mem (reg X)) matches an input (mem (pre_* (reg X)))
  b) an output (mem (post_* (reg X))) matches an input (mem (reg X))

or, to quote:

  /* If two operands must match, because they are really a single
     operand of an assembler insn, then two postincrements are invalid
     because the assembler insn would increment only once.
     On the other hand, a postincrement matches ordinary indexing
     if the postincrement is the output operand.  */
  if (code == POST_DEC || code == POST_INC || code == POST_MODIFY)
    return operands_match_p (XEXP (x, 0), y);
  /* Two preincrements are invalid
     because the assembler insn would increment only once.
     On the other hand, a preincrement matches ordinary indexing
     if the preincrement is the input operand.
     In this case, return 2, since some callers need to do special
     things when this happens.  */
  if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC
      || GET_CODE (y) == PRE_MODIFY)
    return operands_match_p (x, XEXP (y, 0)) ? 2 : 0;

The implication of this code is that the memory being accessed is the
same for both input and output operands.  Case (a) then contradicts
rtl.texi: the output (mem (reg X)) has the modified value.

If I'm reading it right, I don't think case (a) of operands_match_p
makes much sense.  We shouldn't make the rtl semantics depend on whether
something is part of a matched operand.  The meaning of the rtl should
be inherent.

The rtl.texi definition sounds plausible, but implies that case (a)
should read:

  an output (mem (plus (reg X) (const_int Y))) matches an input
  (mem (pre_* (reg X))) given an appropriate constant Y.

which is a bit complicated.  But do we actually ever create such insns?
flow.c doesn't, and combine.c is careful not to combine instructions
that mention the same register if one of the instructions auto-modifies
the register.  combine.c does have a commented-out exception, but
ironically that exception isn't any of those mentioned above:

  /* If I3 has an inc, then give up if I1 or I2 uses the reg that is inc'd.
     We used to do this EXCEPT in one case: I3 has a post-inc in an
     output operand.  However, that exception can give rise to insns like
	mov r3,(r3)+
     which is a famous insn on the PDP-11 where the value of r3 used as the
     source was model-dependent.  Avoid this sort of thing.  */

#if 0
  if (!(GET_CODE (PATTERN (i3)) == SET
	&& REG_P (SET_SRC (PATTERN (i3)))
	&& MEM_P (SET_DEST (PATTERN (i3)))
	&& (GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0)) == POST_INC
	    || GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0)) == POST_DEC)))
    /* It's not the exception.  */
#endif

Can the insns be created in any other way?  Or have we effectively
settled on a situation where only the automodified use is allowed?

Richard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]