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]

Address side effect patches


Here are somes patches to GCC (ss-980513) that I have written to
improve the generation of side-effect addressing modes for GCC.  I
have been using them successfully for several months with the
TMS320C4x Digital Signal Processor port of GCC I have been developing.
However, I am going to be extremely busy over the next couple of
months and haven't the time to submit the patches in bite size
manageable chunks or to massage them for EGCS.  I've submitted this to
the general lists hoping that someone with a little time on their hands
could give them a spin and polish them if required.


In summary, the patches include support for:
1) targets with asymmetrical autoincrement addressing modes,
2) post/pre-modify addressing modes (more generalised autoincrement),
3) converting multiple memory references into autoincrement (automodify)
   address side effects to satisfy desired increment,
4) utilisation of `update' patterns not obvious to combiner.


I have supported targets with asymmetrical autoincrement addressing
modes (such as post-increment on read but post-decrement on write) by
adding a number of new macros, such as HAVE_POST_INCREMENT_READ and
HAVE_POST_INCREMENT_WRITE.  Note that most targets need only define
HAVE_POST_INCREMENT which is equivalent to defining both
HAVE_POST_INCREMENT_READ and HAVE_POST_INCREMENT_WRITE.


I have added a more general framework for address expressions with
side effects, such as the post-increment of an address register by
the contents of an index register or the pre-decrement of an address
register by an arbitrary (small) constant displacement.

There are four new target macros: HAVE_POST_MODIFY_DISP,
HAVE_PRE_MODIFY_DISP, HAVE_POST_MODIFY_REG, HAVE_PRE_MODIFY_REG and
two new RTL expressions post_modify and pre_modify, that have two
operands; a register and a general expression.  With post_modify, the
register is used as the address and then the register gets assigned
the result of the expression.  With pre_modify, the register gets
assigned the result of the expression and this then used as the memory
address.

For example, (mem:SF (post_modify:SI (reg:SI 42) (plus (reg:SI 42)
(reg:SI 48)))) indicates that register 42 is used as the address and
that it is then incremented by the contents of register 48.

Currently, only three forms of expression are supported for post_modify
and pre-modify:
(plus (reg base) (reg index))
(minus (reg base) (reg index))
(plus (reg base) (const_int))


I have also modified the flow pass to try to replace an increment of
an address register by a number of autoincrement (and/or automodify)
memory references using that register (the current behaviour only uses
a single memory reference).  This is very useful for pipelined digital
signal processors where it is undesirable to explicitly increment an
address register.  For example, *p; *(p + 1); p += 2 is now converted
to *p++; *p++.  Similarly, *(p + 1); *p; q = p + 2 is now converted to
q = p; *++q; *q++.  While the algorithm I used can generate quite good
sequences of address side effects, it could be improved if a better
flow graph was available and if there was a cost mechanism for
addressing modes.

In addition, if an address side effect cannot be used, I try using
`update' patterns which won't be utilised by the combiner since the
data flow is not obvious.


Michael.



Index: cse.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/cse.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 cse.c
--- cse.c	1998/03/20 05:06:50	1.1.1.1
+++ cse.c	1998/05/30 07:58:42
@@ -1989,6 +1989,8 @@ canon_hash (x, mode)
     case PRE_INC:
     case POST_DEC:
     case POST_INC:
+    case PRE_MODIFY:
+    case POST_MODIFY:
     case PC:
     case CC0:
     case CALL:
@@ -5736,6 +5738,10 @@ fold_rtx (x, insn)
 #endif
 #if defined(HAVE_PRE_DECREMENT) || defined(HAVE_POST_DECREMENT)
 		      || exact_log2 (- INTVAL (const_arg1)) >= 0
+#endif
+		      /* Can use any constant with pre or post modify. */
+#if defined(HAVE_PRE_MODIFY) || defined(HAVE_POST_MODIFY)
+		      || 1
 #endif
 		  ))
 		break;
Index: flow.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/flow.c,v
retrieving revision 1.1.1.2
retrieving revision 1.7
diff -p -u -r1.1.1.2 -r1.7
--- flow.c	1998/05/09 03:34:31	1.1.1.2
+++ flow.c	1998/05/30 08:03:39	1.7
@@ -181,6 +181,24 @@ reg_info *reg_n_info;
 
 static rtx *reg_next_use;
 
+/* Structure for recording information for converting a sequence
+   of memory accesses into autoincrement memory accesses.  */
+
+struct autoinc 
+{
+  HOST_WIDE_INT pre_inc;
+  HOST_WIDE_INT post_inc;
+  HOST_WIDE_INT offset;
+  rtx insn;
+  rtx x;
+  rtx src;
+  rtx reg;
+  struct autoinc *next;
+  struct autoinc *prev;
+};
+
+static struct autoinc **reg_auto_inc;
+
 /* Size of a regset for the current function,
    in (1) bytes and (2) elements.  */
 
@@ -263,12 +281,19 @@ static void mark_set_regs		PROTO((regset
 					       rtx, regset));
 static void mark_set_1			PROTO((regset, regset, rtx,
 					       rtx, regset));
-static void find_auto_inc		PROTO((regset, rtx, rtx));
+static void find_auto_inc		PROTO((regset, rtx, rtx, int));
 static void mark_used_regs		PROTO((regset, regset, rtx, int, rtx));
+#ifdef AUTO_INC_DEC
 static int try_pre_increment_1		PROTO((rtx));
 static int try_pre_increment		PROTO((rtx, rtx, HOST_WIDE_INT));
-static rtx find_use_as_address		PROTO((rtx, rtx, HOST_WIDE_INT));
+static void free_all_auto_inc		PROTO((int));
+static void replace_auto_inc		PROTO((regset, int));
+static void free_auto_inc		PROTO((struct autoinc **));
+#endif
+static rtx find_use_as_address		PROTO((rtx, rtx, HOST_WIDE_INT, int *));
 void dump_flow_info			PROTO((FILE *));
+
+
 
 /* Find basic blocks of the current function and perform data flow analysis.
    F is the first insn of the function and NREGS the number of register numbers
@@ -859,6 +884,12 @@ life_analysis (f, nregs)
   reg_next_use = (rtx *) alloca (nregs * sizeof (rtx));
   bzero ((char *) reg_next_use, nregs * sizeof (rtx));
 
+#ifdef AUTO_INC_DEC
+  reg_auto_inc = (struct autoinc **)
+    alloca (nregs * sizeof (struct autoinc *));
+  bzero ((char *) reg_auto_inc, nregs * sizeof (struct autoinc *));
+#endif
+
   /* Set up several regset-vectors used internally within this function.
      Their meanings are documented above, with their declarations.  */
 
@@ -1202,6 +1233,9 @@ life_analysis (f, nregs)
 				 }
 			     });
 
+#ifdef AUTO_INC_DEC
+  free_all_auto_inc(nregs);
+#endif
 
   free_regset_vector (basic_block_live_at_end, n_basic_blocks);
   free_regset_vector (basic_block_new_live_at_end, n_basic_blocks);
@@ -2045,192 +2079,486 @@ mark_set_1 (needed, dead, x, insn, signi
 
 #ifdef AUTO_INC_DEC
 
+static void
+free_auto_inc (p)
+     struct autoinc **p;
+{
+  struct autoinc *a = *p;
+  if (!a)
+    return;
+  if (a->next)
+    free_auto_inc ((&a->next));
+  free (*p);
+  *p = 0;
+}
+
+static void
+free_all_auto_inc (nregs)
+     int nregs;
+{
+  int r;
+
+  for (r = 0; r < nregs; r++)
+    {
+      if (reg_auto_inc[r])
+	free_auto_inc(&reg_auto_inc[r]);
+    }
+}
+
+/* validate_change can only handle MAX_CHANGE_LOCS changes. */
+#define MAX_AUTO_INCS (MAX_RECOG_OPERANDS * 5)
+
+static void
+replace_auto_inc (needed, regno)
+     regset needed;
+     int regno;
+{
+  struct autoinc *a;
+  struct autoinc *head;
+  struct autoinc *tail;
+  rtx reg;
+  rtx set;
+  rtx incr;
+  rtx insns;
+  int i;
+  int incs;      
+
+  /* The insn on the end of the list is the increment insn.  */
+  head = reg_auto_inc[regno];
+  for (incs = 0, tail = head; tail->next; incs++, tail = tail->next);
+    
+  if (incs > MAX_AUTO_INCS)
+    {
+      /* Rather than giving up if we have too many memory references
+	 to deal with, we could convert as many as we can to autoincrements
+	 and then adjust the INCR insn.  While this does not get rid of INCR,
+	 it still allows us to generate more compact addresses in general.  */
+      free_auto_inc(&reg_auto_inc[regno]);
+      return;
+    }
+
+  incr = tail->insn;
+  set = single_set(incr);
+  reg = tail->reg;
+
+  if (tail->reg != tail->src)
+    {
+      rtx temp;
+
+      /* Here we have memory references using SRC followed sometime
+	 later by an increment insn of the form, REG = SRC + INC.  Both
+	 REG and SRC are live afterward, and REG is not used between
+	 the first memory reference and the increment insn.  We change
+	 things to REG = SRC, ...*REG..., REG = REG + INC.  */
+      
+      start_sequence ();
+      emit_move_insn (SET_DEST (set), tail->src);
+      insns = get_insns ();
+      end_sequence ();
+      
+      /* If anything in INSNS have UID's that don't fit within the
+	 extra space we allocate earlier, we can't make this auto-inc.
+	 This should never happen.  */
+      for (temp = insns; temp; temp = NEXT_INSN (temp))
+	{
+	  if (INSN_UID (temp) > max_uid_for_flow)
+	    {
+	      free_auto_inc(&reg_auto_inc[regno]);
+	      return;
+	    }
+	  BLOCK_NUM (temp) = BLOCK_NUM (head->insn);
+	}
+    }
+
+  /* Validate all the required changes to the memory references.  */
+  for (incs = 0, a = tail->prev; a; a = a->prev)
+    {
+      int size = GET_MODE_SIZE (GET_MODE (a->x));
+      int inc;
+      enum rtx_code inc_code;
+      rtx inc_rtx;
+
+      if (a->post_inc)
+	{
+	  inc = a->post_inc;
+	  if (inc == size)
+	    inc_code = POST_INC;
+	  else if (inc == -size)
+	    inc_code = POST_DEC;
+	  else
+	    inc_code = POST_MODIFY;
+	}
+      else
+	{
+	  inc = a->pre_inc;
+	  if (inc == size)
+	    inc_code = PRE_INC;
+	  else if (inc == -size)
+	    inc_code = PRE_DEC;
+	  else
+	    inc_code = PRE_MODIFY;
+	}
+
+      if (inc_code == POST_MODIFY || inc_code == PRE_MODIFY)
+ 	inc_rtx = gen_rtx (inc_code, Pmode, reg,
+			   gen_rtx (PLUS, Pmode, reg,
+				    gen_rtx (CONST_INT, VOIDmode, inc)));
+      else
+ 	inc_rtx = gen_rtx (inc_code, Pmode, reg);
+      
+      validate_change (a->insn, &XEXP (a->x, 0), inc_rtx, 1);
+      incs++;
+    }
+
+  if (! apply_change_group ())
+    {
+      free_auto_inc(&reg_auto_inc[regno]);
+      return;
+    }
+
+  if (tail->reg != tail->src)
+    {
+      rtx temp;
+
+      /* We now know we'll be doing this change, so emit the
+	 new insn(s).  */
+      emit_insns_before (insns, head->insn);
+      
+      /* If the new move insn becomes the head of the basic block
+	 update basic block head.  */
+      if (basic_block_head[BLOCK_NUM (head->insn)] == head->insn)
+	basic_block_head[BLOCK_NUM (head->insn)] = insns;
+      
+      /* INCR will become a NOTE and each INSN using SRC won't contain
+	 a use of SRC.  If a use of SRC was just placed in the insn
+	 before INSN, make that is is the next use.  Otherwise,
+	 invalidate it.  */
+      if (GET_CODE (PREV_INSN (head->insn)) == INSN
+	  && GET_CODE (PATTERN (PREV_INSN (head->insn))) == SET
+	  && SET_SRC (PATTERN (PREV_INSN (head->insn))) == tail->src)
+	reg_next_use[regno] = PREV_INSN (head->insn);
+      else
+	reg_next_use[regno] = 0;
+      
+      /* REG is now used in INCR which is below INSN, but
+	 it previously wasn't live here.  If we don't mark
+	 it as needed, we'll put a REG_DEAD note for it
+	 on this insn, which is incorrect.  */
+      SET_REGNO_REG_SET (needed, REGNO (reg));
+      
+      /* If there are any calls between INSN and INCR, show
+	 that REG now crosses them.  */
+      for (temp = head->insn; temp != incr; temp = NEXT_INSN (temp))
+	if (GET_CODE (temp) == CALL_INSN)
+	  REG_N_CALLS_CROSSED (REGNO (reg))++;
+    }
+  
+  a = tail->prev;
+  for (i = 0; i < incs; i++)
+    {
+      REG_NOTES (a->insn)
+	= gen_rtx (EXPR_LIST, REG_INC, reg, REG_NOTES (a->insn));
+      a = a->prev;
+    }
+  
+  /* Modify the old increment-insn to simply copy
+     the already-incremented value of our register.  */
+  if (! validate_change (incr, &SET_SRC (set), reg, 0))
+    abort ();
+  
+  /* If that makes it a no-op (copying the register into itself) delete
+     it so it won't appear to be a "use" and a "set" of this
+     register.  */
+  if (SET_DEST (set) == reg)
+    {
+      PUT_CODE (incr, NOTE);
+      NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
+      NOTE_SOURCE_FILE (incr) = 0;
+    }
+  
+  if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+    {
+      /* Count an extra reference to REG.  When a register is
+	 incremented, spilling it is worse, so we want to make
+	 that less likely.  */
+      REG_N_REFS (REGNO (reg)) += loop_depth * incs;
+      
+      /* Count the increments as a setting of the register,
+	     even though it isn't a SET in rtl.  */
+      REG_N_SETS (REGNO (reg)) += incs;
+    }
+  
+  /* We're all done, so tidy up... */
+  free_auto_inc(&reg_auto_inc[regno]);
+}
+
 /* X is a MEM found in INSN.  See if we can convert it into an auto-increment
-   reference.  */
+   or auto-modify reference.  */
 
 static void
-find_auto_inc (needed, x, insn)
+find_auto_inc (needed, x, insn, wrflag)
      regset needed;
      rtx x;
      rtx insn;
+     int wrflag;
 {
   rtx addr = XEXP (x, 0);
   HOST_WIDE_INT offset = 0;
+  register int size = GET_MODE_SIZE (GET_MODE (x));
+  struct autoinc *a;
+  struct autoinc *b;
+  register rtx y;
   rtx set;
+  rtx use;
+  rtx incr;
+  int regno;
 
   /* Here we detect use of an index register which might be good for
-     postincrement, postdecrement, preincrement, or predecrement.  */
+     postincrement, postdecrement, postmodify, preincrement, predecrement,
+     or premodify.  */
 
   if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
     offset = INTVAL (XEXP (addr, 1)), addr = XEXP (addr, 0);
 
-  if (GET_CODE (addr) == REG)
+  if (GET_CODE (addr) != REG)
+    return;
+
+  regno = REGNO (addr);
+
+  if ((b = reg_auto_inc[regno]) == 0)
     {
-      register rtx y;
-      register int size = GET_MODE_SIZE (GET_MODE (x));
-      rtx use;
-      rtx incr;
-      int regno = REGNO (addr);
+      rtx reg;
+      int inc;
 
       /* Is the next use an increment that might make auto-increment? */
-      if ((incr = reg_next_use[regno]) != 0
-	  && (set = single_set (incr)) != 0
-	  && GET_CODE (set) == SET
-	  && BLOCK_NUM (incr) == BLOCK_NUM (insn)
-	  /* Can't add side effects to jumps; if reg is spilled and
-	     reloaded, there's no way to store back the altered value.  */
-	  && GET_CODE (insn) != JUMP_INSN
-	  && (y = SET_SRC (set), GET_CODE (y) == PLUS)
-	  && XEXP (y, 0) == addr
-	  && GET_CODE (XEXP (y, 1)) == CONST_INT
-	  && (0
-#ifdef HAVE_POST_INCREMENT
-	      || (INTVAL (XEXP (y, 1)) == size && offset == 0)
-#endif
-#ifdef HAVE_POST_DECREMENT
-	      || (INTVAL (XEXP (y, 1)) == - size && offset == 0)
-#endif
-#ifdef HAVE_PRE_INCREMENT
-	      || (INTVAL (XEXP (y, 1)) == size && offset == size)
-#endif
-#ifdef HAVE_PRE_DECREMENT
-	      || (INTVAL (XEXP (y, 1)) == - size && offset == - size)
-#endif
-	      )
-	  /* Make sure this reg appears only once in this insn.  */
-	  && (use = find_use_as_address (PATTERN (insn), addr, offset),
-	      use != 0 && use != (rtx) 1))
-	{
-	  rtx q = SET_DEST (set);
-	  enum rtx_code inc_code = (INTVAL (XEXP (y, 1)) == size
-				    ? (offset ? PRE_INC : POST_INC)
-				    : (offset ? PRE_DEC : POST_DEC));
-
-	  if (dead_or_set_p (incr, addr))
-	    {
-	      /* This is the simple case.  Try to make the auto-inc.  If
-		 we can't, we are done.  Otherwise, we will do any
-		 needed updates below.  */
-	      if (! validate_change (insn, &XEXP (x, 0),
-				     gen_rtx (inc_code, Pmode, addr),
-				     0))
-		return;
-	    }
-	  else if (GET_CODE (q) == REG
-		   /* PREV_INSN used here to check the semi-open interval
-		      [insn,incr).  */
-		   && ! reg_used_between_p (q,  PREV_INSN (insn), incr)
-		   /* We must also check for sets of q as q may be
-		      a call clobbered hard register and there may
-		      be a call between PREV_INSN (insn) and incr.  */
-		   && ! reg_set_between_p (q,  PREV_INSN (insn), incr))
-	    {
-	      /* We have *p followed sometime later by q = p+size.
-		 Both p and q must be live afterward,
-		 and q is not used between INSN and it's assignment.
-		 Change it to q = p, ...*q..., q = q+size.
-		 Then fall into the usual case.  */
-	      rtx insns, temp;
-
-	      start_sequence ();
-	      emit_move_insn (q, addr);
-	      insns = get_insns ();
-	      end_sequence ();
-
-	      /* If anything in INSNS have UID's that don't fit within the
-		 extra space we allocate earlier, we can't make this auto-inc.
-		 This should never happen.  */
-	      for (temp = insns; temp; temp = NEXT_INSN (temp))
+      if ((incr = reg_next_use[regno]) == 0
+	  || (set = single_set (incr)) == 0
+	  || BLOCK_NUM (incr) != BLOCK_NUM (insn)
+	  || (y = SET_SRC (set), 
+	      (GET_CODE (y) != PLUS && GET_CODE (y) != MINUS))
+	  || XEXP (y, 0) != addr)
+	return;
+
+      /* Look for (MEM REG) followed by (SET (REG) (PLUS (REG) (INDEX)))
+	 where INDEX is either a constant or an index register.
+	 if INDEX is a register, it cannot be set between insn and incr.  */
+      if (REG_P (XEXP (y, 1))
+	  && offset == 0
+	  && SET_DEST (set) == addr
+	  && ! reg_set_between_p (XEXP (y, 1), PREV_INSN (insn), incr)
+	  && dead_or_set_p (incr, addr))
+	{
+	  rtx update;
+
+#ifdef HAVE_POST_MODIFY_REG
+	  /* This optimization is probably only worthwhile inside a
+	     loop where the register increment can be used repeatedly. */
+	  if ((use = find_use_as_address (PATTERN (insn), addr, offset, 0),
+	       use != 0 && use != (rtx) 1)
+	      && loop_depth > 1
+	      && validate_change (insn, &XEXP (x, 0),
+				  gen_rtx (POST_MODIFY, Pmode, addr,
+					   gen_rtx (GET_CODE (y), Pmode, addr, 
+						    XEXP (y, 1))), 0))
+	    {
+	      /* Add a note to show the side effect.  */
+	      REG_NOTES (insn)
+		= gen_rtx (EXPR_LIST, REG_INC, addr, REG_NOTES (insn));
+	      
+	      if (regno >= FIRST_PSEUDO_REGISTER)
 		{
-		  if (INSN_UID (temp) > max_uid_for_flow)
-		    return;
-		  BLOCK_NUM (temp) = BLOCK_NUM (insn);
+		  /* Count an extra reference to the base reg.  When a reg
+		     is incremented, spilling it is worse, so we want to
+		     make that less likely.  */
+		  REG_N_REFS (regno) += loop_depth;
+		  
+		  /* Count the increments as a setting of the register,
+		     even though it isn't a SET in rtl.  */
+		  REG_N_SETS (regno) += 1;
 		}
 
-	      /* If we can't make the auto-inc, or can't make the
-		 replacement into Y, exit.  There's no point in making
-		 the change below if we can't do the auto-inc and doing
-		 so is not correct in the pre-inc case.  */
-
-	      validate_change (insn, &XEXP (x, 0),
-			       gen_rtx (inc_code, Pmode, q),
-			       1);
-	      validate_change (incr, &XEXP (y, 0), q, 1);
-	      if (! apply_change_group ())
-		return;
-
-	      /* We now know we'll be doing this change, so emit the
-		 new insn(s) and do the updates.  */
-	      emit_insns_before (insns, insn);
-
-	      if (basic_block_head[BLOCK_NUM (insn)] == insn)
-		basic_block_head[BLOCK_NUM (insn)] = insns;
-
-	      /* INCR will become a NOTE and INSN won't contain a
-		 use of ADDR.  If a use of ADDR was just placed in
-		 the insn before INSN, make that the next use. 
-		 Otherwise, invalidate it.  */
-	      if (GET_CODE (PREV_INSN (insn)) == INSN
-		  && GET_CODE (PATTERN (PREV_INSN (insn))) == SET
-		  && SET_SRC (PATTERN (PREV_INSN (insn))) == addr)
-		reg_next_use[regno] = PREV_INSN (insn);
-	      else
-		reg_next_use[regno] = 0;
-
-	      addr = q;
-	      regno = REGNO (q);
-
-	      /* REGNO is now used in INCR which is below INSN, but
-		 it previously wasn't live here.  If we don't mark
-		 it as needed, we'll put a REG_DEAD note for it
-		 on this insn, which is incorrect.  */
-	      SET_REGNO_REG_SET (needed, regno);
-
-	      /* If there are any calls between INSN and INCR, show
-		 that REGNO now crosses them.  */
-	      for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
-		if (GET_CODE (temp) == CALL_INSN)
-		  REG_N_CALLS_CROSSED (regno)++;
+	      if (REG_P (XEXP (y, 1)))
+		{
+		  /* Add a note if the index register dies.  */
+		  if (dead_or_set_p (incr, XEXP (y, 1)))
+		    REG_NOTES (insn)
+		      = gen_rtx (EXPR_LIST, REG_DEAD, XEXP (y, 1),
+				 REG_NOTES (insn));
+		  
+		  /* Count an extra reference to the index reg.  */
+		  regno = REGNO (XEXP (y, 1));
+		  if (regno >= FIRST_PSEUDO_REGISTER)
+		    REG_N_REFS (regno) += loop_depth;
+		}
 	    }
+#else
+	  if (0)
+	    {}
+#endif
 	  else
-	    return;
-
-	  /* If we haven't returned, it means we were able to make the
-	     auto-inc, so update the status.  First, record that this insn
-	     has an implicit side effect.  */
-
-	  REG_NOTES (insn)
-	    = gen_rtx (EXPR_LIST, REG_INC, addr, REG_NOTES (insn));
-
-	  /* Modify the old increment-insn to simply copy
-	     the already-incremented value of our register.  */
-	  if (! validate_change (incr, &SET_SRC (set), addr, 0))
-	    abort ();
-
-	  /* If that makes it a no-op (copying the register into itself) delete
-	     it so it won't appear to be a "use" and a "set" of this
-	     register.  */
-	  if (SET_DEST (set) == addr)
 	    {
-	      PUT_CODE (incr, NOTE);
-	      NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
-	      NOTE_SOURCE_FILE (incr) = 0;
+	      /* If incrementing by a register, then we might be able
+		 to utilise an update pattern. 
+		 
+		 Note that the combiner won't perform the following
+		 optimization since the destination operand of INSN is not a
+		 source operand of INCR.  */
+	      
+	      update = gen_rtx (PARALLEL, VOIDmode,
+				gen_rtvec (2, PATTERN (insn), set));
+	      
+	      if (!validate_change (insn, &PATTERN (insn), update, 0))
+		{
+		  /* There may be a move_update pattern written for
+		     the combiner to find.  Try that one as well using
+		     a two stage approach.  */
+		  validate_change (insn, &XEXP (x, 0), SET_SRC (set), 1);
+		  update = gen_rtx (PARALLEL, VOIDmode,
+				    gen_rtvec (2, PATTERN (insn), set));
+		  validate_change (insn, &PATTERN (insn), update, 1);
+		  if (! apply_change_group ())
+		    return;
+		}
 	    }
+	      
+	  /* Delete the increment insn INCR.  */
+	  PUT_CODE (incr, NOTE);
+	  NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
+	  NOTE_SOURCE_FILE (incr) = 0;
+	  return;
+	}
 
-	  if (regno >= FIRST_PSEUDO_REGISTER)
-	    {
-	      /* Count an extra reference to the reg.  When a reg is
-		 incremented, spilling it is worse, so we want to make
-		 that less likely.  */
-	      REG_N_REFS (regno) += loop_depth;
+      if (GET_CODE (XEXP (y, 1)) != CONST_INT)
+	return;
 
-	      /* Count the increment as a setting of the register,
-		 even though it isn't a SET in rtl.  */
-	      REG_N_SETS (regno)++;
-	    }
-	}
+      /* With the INCR insn we have DST = SRC + INC, where SRC is a
+	 register, INC is a constant increment, and DST may be the
+	 same register as SRC.  The simple case occurs when SRC
+	 is not live after the insn.  If SRC is live, we can
+	 handle the general case provided SRC is a register.  */
+
+      if (dead_or_set_p (incr, addr))
+	reg = addr;
+      else if (REG_P (SET_DEST (set)))
+	reg = SET_DEST (set);
+      else
+	return;
+      
+      b = (struct autoinc *) xmalloc (sizeof (struct autoinc));	      
+      b->insn = incr;
+      b->pre_inc = 0;
+      b->post_inc = INTVAL (XEXP (y, 1));
+      b->offset = b->post_inc;
+      b->x = 0;
+      b->reg = reg;
+      b->src = addr;
+      b->next = 0;
+      b->prev = 0;
+      reg_auto_inc[regno] = b;
+    }
+
+  /* Can this memory reference be changed to auto-increment?  */
+  if (BLOCK_NUM (insn) != BLOCK_NUM (b->insn)
+      /* Can't add side effects to jumps; if reg is spilled and
+	 reloaded, there's no way to store back the altered value.  */
+      || GET_CODE (insn) == JUMP_INSN
+      /* The memory reference must be on the chain.  */
+      || reg_next_use[regno] != b->insn
+      /* Make sure this reg appears only once in this insn.  */
+      || (use = find_use_as_address (PATTERN (insn), addr, offset, 0),
+	  use == 0 || use == (rtx) 1)
+      || (b->reg != b->src 
+	  /* reg can't be used, since we want to use it for the
+	     autoincrement. PREV_INSN used here to check the semi-open
+	     interval [insn,b->insn).  */
+	  && (reg_used_between_p (b->reg, PREV_INSN (insn), b->insn)
+	      /* We must also check for sets of reg as reg may be
+		 a call clobbered hard register and there may
+		 be a call between PREV_INSN (insn) and b->insn.  */
+	      || reg_set_between_p (b->reg, PREV_INSN (insn), b->insn)))
+      || !(0
+#ifdef HAVE_POST_MODIFY_DISP
+	   || 1
+#endif
+#ifdef HAVE_POST_INCREMENT_READ
+	   || (offset + size == b->offset && b->offset > 0 && !wrflag)
+#endif
+#ifdef HAVE_POST_INCREMENT_WRITE
+	   || (offset + size == b->offset && b->offset > 0 && wrflag)
+#endif
+#ifdef HAVE_POST_DECREMENT_READ
+	   || (offset - size == b->offset && b->offset < 0 && !wrflag)
+#endif
+#ifdef HAVE_POST_DECREMENT_WRITE
+	   || (offset - size == b->offset && b->offset < 0 && wrflag) 
+#endif
+#ifdef HAVE_PRE_MODIFY_DISP
+	   || (offset == b->offset)
+#endif
+#ifdef HAVE_PRE_INCREMENT_READ
+	   || (offset == b->offset && b->offset > 0 && !wrflag)
+#endif
+#ifdef HAVE_PRE_INCREMENT_WRITE
+	   || (offset == b->offset && b->offset > 0 && wrflag)
+#endif
+#ifdef HAVE_PRE_DECREMENT_READ
+	   || (offset == b->offset && b->offset < 0 && !wrflag)
+#endif
+#ifdef HAVE_PRE_DECREMENT_WRITE
+	   || (offset == b->offset && b->offset < 0 && wrflag)
+#endif
+	   ))
+    {
+      /* Give up ... */
+      free_auto_inc(&reg_auto_inc[regno]);
+      return;
     }
+  
+  /* Build a list of candidate memory references for each address
+     register that can be potentially converted to use auto-increment
+     addressing modes.  Stop when we have enough auto-increments to
+     increment the address by the desired amount, for example:
+     *p; *(p + 1); p = p + 2  becomes *p++; *p++  */
+
+  a = (struct autoinc *) xmalloc (sizeof (struct autoinc));	      
+  a->insn = insn;
+  a->offset = offset;
+  a->src = addr;
+  a->x = x;
+  
+  if (offset == b->offset)
+    {
+#ifdef HAVE_PRE_MODIFY_DISP
+      /* We can achieve the desired increment here.
+	 It would be nice if we could scan for some more
+	 memory references and to use pre-increments or
+	 decrements instead of a pre-modify since these
+	 will usually generate more compact addresses. 
+	 We will need a more comprehensive flow graph. */
+      a->pre_inc = offset;
+#else
+      a->pre_inc = b->offset > 0 ? size : - size;
+#endif
+      a->post_inc = 0;
+    }
+  else
+    {
+      a->pre_inc = 0;
+      a->post_inc = b->offset - offset;
+    }
+  
+  a->reg = b->reg;
+  a->next = b;
+  a->prev = 0;
+  b->prev = a;
+  reg_auto_inc[regno] = a;
+  
+  /* If we have satisfied the total increment, try converting
+     the memory references to autoincrements.  */
+  if (a->offset == 0 || (a->pre_inc && (a->offset == a->pre_inc)))
+    replace_auto_inc(needed, regno);
 }
+
 #endif /* AUTO_INC_DEC */
 
 /* Scan expression X and store a 1-bit in LIVE for each reg it uses.
@@ -2294,7 +2622,7 @@ mark_used_regs (needed, live, x, final, 
 
 #ifdef AUTO_INC_DEC
       if (final)
-	find_auto_inc (needed, x, insn);
+	find_auto_inc (needed, x, insn, 0);
 #endif
       break;
 
@@ -2475,7 +2803,7 @@ mark_used_regs (needed, live, x, final, 
 	  {
 #ifdef AUTO_INC_DEC
 	    if (final)
-	      find_auto_inc (needed, testreg, insn);
+	      find_auto_inc (needed, testreg, insn, 1);
 #endif
 	    mark_used_regs (needed, live, XEXP (testreg, 0), final, insn);
 	    mark_used_regs (needed, live, SET_SRC (x), final, insn);
@@ -2653,22 +2981,25 @@ try_pre_increment (insn, reg, amount)
   /* Nonzero if the opportunity actually requires post-inc or post-dec.  */
   int do_post = 0;
 
+  /* Nonzero if the memory reference is the destination of a set.  */
+  int wrflag;
+
   /* From the sign of increment, see which possibilities are conceivable
      on this target machine.  */
-#ifdef HAVE_PRE_INCREMENT
+#if defined (HAVE_PRE_INCREMENT_READ) || defined (HAVE_PRE_INCREMENT_WRITE)
   if (amount > 0)
     pre_ok = 1;
 #endif
-#ifdef HAVE_POST_INCREMENT
+#if defined (HAVE_POST_INCREMENT_READ) || defined (HAVE_POST_INCREMENT_WRITE)
   if (amount > 0)
     post_ok = 1;
 #endif
 
-#ifdef HAVE_PRE_DECREMENT
+#if defined (HAVE_PRE_DECREMENT_READ) || defined (HAVE_PRE_DECREMENT_WRITE)
   if (amount < 0)
     pre_ok = 1;
 #endif
-#ifdef HAVE_POST_DECREMENT
+#if defined (HAVE_POST_DECREMENT_READ) || defined (HAVE_POST_DECREMENT_WRITE)
   if (amount < 0)
     post_ok = 1;
 #endif
@@ -2685,10 +3016,10 @@ try_pre_increment (insn, reg, amount)
 
   use = 0;
   if (pre_ok)
-    use = find_use_as_address (PATTERN (insn), reg, 0);
+    use = find_use_as_address (PATTERN (insn), reg, 0, &wrflag);
   if (post_ok && (use == 0 || use == (rtx) 1))
     {
-      use = find_use_as_address (PATTERN (insn), reg, -amount);
+      use = find_use_as_address (PATTERN (insn), reg, -amount, &wrflag);
       do_post = 1;
     }
 
@@ -2698,6 +3029,34 @@ try_pre_increment (insn, reg, amount)
   if (GET_MODE_SIZE (GET_MODE (use)) != (amount > 0 ? amount : - amount))
     return 0;
 
+  if (! (0
+#ifdef HAVE_PRE_DECREMENT_READ
+	 || (amount < 0 && !do_post && !wrflag)
+#endif
+#ifdef HAVE_PRE_DECREMENT_WRITE
+	 || (amount < 0 && !do_post && wrflag)
+#endif
+#ifdef HAVE_POST_DECREMENT_READ
+	 || (amount < 0 && do_post && !wrflag)
+#endif
+#ifdef HAVE_POST_DECREMENT_WRITE
+	 || (amount < 0 && do_post && wrflag)
+#endif
+#ifdef HAVE_PRE_INCREMENT_READ
+	 || (amount > 0 && !do_post && !wrflag)
+#endif
+#ifdef HAVE_PRE_INCREMENT_WRITE
+	 || (amount > 0 && !do_post && wrflag)
+#endif
+#ifdef HAVE_POST_INCREMENT_READ
+	 || (amount > 0 && do_post && !wrflag)
+#endif
+#ifdef HAVE_POST_INCREMENT_WRITE
+	 || (amount > 0 && do_post && wrflag)
+#endif
+	 ))
+    return 0;
+
   /* See if this combination of instruction and addressing mode exists.  */
   if (! validate_change (insn, &XEXP (use, 0),
 			 gen_rtx (amount > 0
@@ -2723,16 +3082,21 @@ try_pre_increment (insn, reg, amount)
    return (rtx)1.  */
 
 static rtx
-find_use_as_address (x, reg, plusconst)
+find_use_as_address (x, reg, plusconst, pwrflag)
      register rtx x;
      rtx reg;
      HOST_WIDE_INT plusconst;
+     int *pwrflag;
 {
   enum rtx_code code = GET_CODE (x);
   char *fmt = GET_RTX_FORMAT (code);
   register int i;
   register rtx value = 0;
   register rtx tem;
+  int wrflag = 0;
+
+  if (pwrflag)
+    *pwrflag = wrflag;
 
   if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
     return x;
@@ -2747,7 +3111,7 @@ find_use_as_address (x, reg, plusconst)
     {
       /* If REG occurs inside a MEM used in a bit-field reference,
 	 that is unacceptable.  */
-      if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
+      if (find_use_as_address (XEXP (x, 0), reg, 0, 0) != 0)
 	return (rtx) (HOST_WIDE_INT) 1;
     }
 
@@ -2758,9 +3122,13 @@ find_use_as_address (x, reg, plusconst)
     {
       if (fmt[i] == 'e')
 	{
-	  tem = find_use_as_address (XEXP (x, i), reg, plusconst);
+	  tem = find_use_as_address (XEXP (x, i), reg, plusconst, &wrflag);
 	  if (value == 0)
-	    value = tem;
+	    {
+	      value = tem;
+	      if (code == SET && SET_DEST(x) == tem)
+		wrflag = 1;
+	    }
 	  else if (tem != 0)
 	    return (rtx) (HOST_WIDE_INT) 1;
 	}
@@ -2769,7 +3137,8 @@ find_use_as_address (x, reg, plusconst)
 	  register int j;
 	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
 	    {
-	      tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
+	      tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst,
+					 &wrflag);
 	      if (value == 0)
 		value = tem;
 	      else if (tem != 0)
@@ -2777,6 +3146,9 @@ find_use_as_address (x, reg, plusconst)
 	    }
 	}
     }
+
+  if (pwrflag)
+    *pwrflag = wrflag;
 
   return value;
 }
Index: function.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/function.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -p -u -r1.1.1.2 -r1.4
--- function.c	1998/05/09 03:34:33	1.1.1.2
+++ function.c	1998/05/30 08:03:39	1.4
@@ -3293,6 +3293,8 @@ instantiate_virtual_regs_1 (loc, object,
     case NE:       case EQ:
     case GE:       case GT:       case GEU:    case GTU:
     case LE:       case LT:       case LEU:    case LTU:
+    case POST_MODIFY:
+    case PRE_MODIFY:
       if (XEXP (x, 1) && ! CONSTANT_P (XEXP (x, 1)))
 	instantiate_virtual_regs_1 (&XEXP (x, 1), object, extra_insns);
       loc = &XEXP (x, 0);
Index: loop.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/loop.c,v
retrieving revision 1.1.1.2
diff -p -u -r1.1.1.2 loop.c
--- loop.c	1998/05/09 03:34:47	1.1.1.2
+++ loop.c	1998/05/30 07:58:47
@@ -3893,11 +3897,11 @@ strength_reduce (scan_start, end, loop_t
 	  if (v->giv_type == DEST_ADDR
 	      && GET_CODE (v->mult_val) == CONST_INT)
 	    {
-#if defined (HAVE_POST_INCREMENT) || defined (HAVE_PRE_INCREMENT)
+#ifdef HAVE_AUTO_INC
 	      if (INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
 		benefit += add_cost * bl->biv_count;
 #endif
-#if defined (HAVE_POST_DECREMENT) || defined (HAVE_PRE_DECREMENT)
+#ifdef HAVE_AUTO_DEC
 	      if (-INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
 		benefit += add_cost * bl->biv_count;
 #endif
@@ -3999,7 +4003,7 @@ strength_reduce (scan_start, end, loop_t
 			  && INSN_LUID (v->insn) < INSN_LUID (bl->biv->insn))
 			auto_inc_opt = 1;
 		    }
-		  /* Check for case where increment is before the the address
+		  /* Check for case where increment is before the address
 		     giv.  Do this test in "loop order".  */
 		  else if ((INSN_LUID (v->insn) > INSN_LUID (bl->biv->insn)
 			    && (INSN_LUID (v->insn) < INSN_LUID (scan_start)
Index: md.texi
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/md.texi,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -p -u -r1.1.1.2 -r1.2
--- md.texi	1998/05/09 03:34:49	1.1.1.2
+++ md.texi	1998/03/20 05:25:20	1.2
@@ -714,6 +714,14 @@ postdecrement) is allowed.
 A memory operand with autoincrement addressing (either preincrement or
 postincrement) is allowed.
 
+@cindex @samp{@{} in constraint
+@item @samp{@{}
+A memory operand with pre_modify addressing.
+ 
+@cindex @samp{@}} in constraint
+@item @samp{@}}
+A memory operand with post_modify addressing.
+
 @cindex @samp{r} in constraint
 @cindex registers in constraints
 @item @samp{r}
Index: recog.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/recog.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 recog.c
--- recog.c	1998/03/20 05:07:06	1.1.1.1
+++ recog.c	1998/05/30 07:58:48
@@ -1502,7 +1502,8 @@ offsettable_address_p (strictp, mode, y)
     }
 
   if (ycode == PRE_DEC || ycode == PRE_INC
-      || ycode == POST_DEC || ycode == POST_INC)
+      || ycode == POST_DEC || ycode == POST_INC
+      || ycode == PRE_MODIFY || ycode == POST_MODIFY)
     return 0;
 
   /* The offset added here is chosen as the maximum offset that
@@ -1828,6 +1829,18 @@ constrain_operands (insn_code_num, stric
 		if (GET_CODE (op) == MEM
 		    && (GET_CODE (XEXP (op, 0)) == PRE_INC
 			|| GET_CODE (XEXP (op, 0)) == POST_INC))
+		  win = 1;
+		break;
+
+	      case '{':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == PRE_MODIFY))
+		  win = 1;
+		break;
+
+	      case '}':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == POST_MODIFY))
 		  win = 1;
 		break;
 
Index: reg-stack.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/reg-stack.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 reg-stack.c
--- reg-stack.c	1998/03/20 05:07:07	1.1.1.1
+++ reg-stack.c	1998/05/30 07:58:48
@@ -747,6 +747,18 @@ constrain_asm_operands (n_operands, oper
 		  win = 1;
 		break;
 
+	      case '{':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == PRE_MODIFY))
+		  win = 1;
+		break;
+
+	      case '}':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == POST_MODIFY))
+		  win = 1;
+		break;
+
 	      case 'E':
 		/* Match any CONST_DOUBLE, but only if
 		   we can examine the bits of it reliably.  */
Index: regclass.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/regclass.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -p -u -r1.1.1.2 -r1.3
--- regclass.c	1998/05/09 03:34:57	1.1.1.2
+++ regclass.c	1998/05/30 08:03:43	1.3
@@ -1248,6 +1248,18 @@ record_reg_classes (n_alts, n_ops, ops, 
 		  win = 1;
 		break;
 
+	      case '{':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == PRE_MODIFY))
+		  win = 1;
+		break;
+
+	      case '}':
+		if (GET_CODE (op) == MEM
+		    && (GET_CODE (XEXP (op, 0)) == POST_MODIFY))
+		  win = 1;
+		break;
+
 	      case 'E':
 #ifndef REAL_ARITHMETIC
 		/* Match any floating double constant, but only if
@@ -1663,6 +1675,17 @@ record_address_regs (x, class, scale)
       }
       break;
 
+      /* Double the importance of a pseudo register that is incremented
+	 or decremented, since it would take two extra insns
+	 if it ends up in the wrong place.  */
+    case POST_MODIFY:
+    case PRE_MODIFY:
+      record_address_regs (XEXP (x, 0), BASE_REG_CLASS, 2 * scale);
+      if (REG_P (XEXP (XEXP (x, 1), 1)))
+	record_address_regs (XEXP (XEXP (x, 1), 1),
+			     INDEX_REG_CLASS, 2 * scale);
+      break;
+
     case POST_INC:
     case PRE_INC:
     case POST_DEC:
@@ -1714,22 +1737,22 @@ auto_inc_dec_reg_p (reg, mode)
      rtx reg;
      enum machine_mode mode;
 {
-#ifdef HAVE_POST_INCREMENT
+#if defined (HAVE_POST_INCREMENT_READ) || defined (HAVE_POST_INCREMENT_WRITE) 
   if (memory_address_p (mode, gen_rtx (POST_INC, Pmode, reg)))
     return 1;
 #endif
 
-#ifdef HAVE_POST_DECREMENT
+#if defined (HAVE_POST_DECREMENT_READ) || defined (HAVE_POST_DECREMENT_WRITE) 
   if (memory_address_p (mode, gen_rtx (POST_DEC, Pmode, reg)))
     return 1;
 #endif
 
-#ifdef HAVE_PRE_INCREMENT
+#if defined (HAVE_PRE_INCREMENT_READ) || defined (HAVE_PRE_INCREMENT_WRITE) 
   if (memory_address_p (mode, gen_rtx (PRE_INC, Pmode, reg)))
     return 1;
 #endif
 
-#ifdef HAVE_PRE_DECREMENT
+#if defined (HAVE_PRE_DECREMENT_READ) || defined (HAVE_PRE_DECREMENT_WRITE) 
   if (memory_address_p (mode, gen_rtx (PRE_DEC, Pmode, reg)))
     return 1;
 #endif
Index: reload.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/reload.c,v
retrieving revision 1.1.1.2
retrieving revision 1.5
diff -p -u -r1.1.1.2 -r1.5
--- reload.c	1998/05/09 03:34:57	1.1.1.2
+++ reload.c	1998/05/30 08:03:44	1.5
@@ -834,10 +838,12 @@ push_reload (in, out, inloc, outloc, cla
   if (in != 0 && out != 0 && GET_CODE (in) == MEM && rtx_equal_p (in, out))
     {
       if (GET_CODE (XEXP (in, 0)) == POST_INC
-	  || GET_CODE (XEXP (in, 0)) == POST_DEC)
+	  || GET_CODE (XEXP (in, 0)) == POST_DEC
+	  || GET_CODE (XEXP (in, 0)) == POST_MODIFY)
 	in = gen_rtx (MEM, GET_MODE (in), XEXP (XEXP (in, 0), 0));
       if (GET_CODE (XEXP (in, 0)) == PRE_INC
-	  || GET_CODE (XEXP (in, 0)) == PRE_DEC)
+	  || GET_CODE (XEXP (in, 0)) == PRE_DEC
+	  || GET_CODE (XEXP (in, 0)) == PRE_MODIFY)
 	out = gen_rtx (MEM, GET_MODE (out), XEXP (XEXP (out, 0), 0));
     }
 
@@ -859,7 +865,7 @@ push_reload (in, out, inloc, outloc, cla
      we can't handle it here because CONST_INT does not indicate a mode.
 
      Similarly, we must reload the inside expression if we have a
-     STRICT_LOW_PART (presumably, in == out in the cas).
+     STRICT_LOW_PART (presumably, in == out in that case).
 
      Also reload the inner expression if it does not require a secondary
      reload but the SUBREG does.
@@ -1200,14 +1206,18 @@ push_reload (in, out, inloc, outloc, cla
 	       && (GET_CODE (reload_in[i]) == POST_INC
 		   || GET_CODE (reload_in[i]) == POST_DEC
 		   || GET_CODE (reload_in[i]) == PRE_INC
-		   || GET_CODE (reload_in[i]) == PRE_DEC)
+		   || GET_CODE (reload_in[i]) == PRE_DEC
+		   || GET_CODE (reload_in[i]) == POST_MODIFY
+		   || GET_CODE (reload_in[i]) == PRE_MODIFY)
 	       && MATCHES (XEXP (reload_in[i], 0), in))
 	      ||
 	      (GET_CODE (reload_in[i]) == REG
 	       && (GET_CODE (in) == POST_INC
 		   || GET_CODE (in) == POST_DEC
 		   || GET_CODE (in) == PRE_INC
-		   || GET_CODE (in) == PRE_DEC)
+		   || GET_CODE (in) == PRE_DEC
+		   || GET_CODE (in) == POST_MODIFY
+		   || GET_CODE (in) == PRE_MODIFY)
 	       && MATCHES (XEXP (in, 0), reload_in[i])))
 	  && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
 	  && MERGABLE_RELOADS (type, reload_when_needed[i],
@@ -1965,7 +1975,7 @@ operands_match_p (x, y)
      because the assembler insn would increment only once.
      On the other hand, an postincrement matches ordinary indexing
      if the postincrement is the output operand.  */
-  if (code == POST_DEC || code == POST_INC)
+  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.
@@ -1973,7 +1983,8 @@ operands_match_p (x, y)
      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)
+  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;
 
  slow:
@@ -2080,6 +2091,20 @@ decompose (x)
 	  return val;
 	}
 
+      if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
+ 	{
+ 	  if (GET_CODE (XEXP (addr, 1)) == PLUS
+	      && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+	      && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+ 	    {
+ 	      val.base  = XEXP (addr, 0);
+ 	      val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
+ 	      val.end   = INTVAL (XEXP (XEXP (addr, 1), 1));
+ 	      val.safe  = REGNO (val.base) == STACK_POINTER_REGNUM;
+ 	      return val;
+ 	    }
+ 	}
+      
       if (GET_CODE (addr) == CONST)
 	{
 	  addr = XEXP (addr, 0);
@@ -2613,7 +2638,7 @@ find_reloads (insn, replace, ind_levels,
 
 	      /* If this is an output operand, we must output a CLOBBER
 		 after INSN so find_equiv_reg knows REGNO is being written. 
-		 Mark this insn specially, do we can put our output reloads
+		 Mark this insn specially, so we can put our output reloads
 		 after it.  */
 
 	      if (modified[i] != RELOAD_READ)
@@ -2942,6 +2967,20 @@ find_reloads (insn, replace, ind_levels,
 		  win = 1;
 		break;
 
+ 	      case '{':
+ 		if (GET_CODE (operand) == MEM
+ 		    && ! address_reloaded[i]
+ 		    && (GET_CODE (XEXP (operand, 0)) == PRE_MODIFY))
+		  win = 1;
+ 		break;
+		
+ 	      case '}':
+ 		if (GET_CODE (operand) == MEM
+ 		    && ! address_reloaded[i]
+ 		    && (GET_CODE (XEXP (operand, 0)) == POST_MODIFY))
+		  win = 1;
+ 		break;
+
 		/* Memory operand whose address is not offsettable.  */
 	      case 'V':
 		if (force_reload)
@@ -4946,6 +4986,51 @@ find_reloads_address_1 (mode, x, context
 
       return 0;
 
+    case POST_MODIFY:
+    case PRE_MODIFY:
+      {
+	rtx op0 = XEXP (x, 0);
+	rtx op1 = XEXP (x, 1);
+
+	if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
+	  return 0;
+
+	/* Currently, we only support {PRE,POST}_MODIFY constructs
+	   where a base register is {inc,dec}remented by the contents
+	   of another register or by a constant value.  Thus, these
+	   operands must match.  */
+	if (op0 != XEXP (op1, 0))
+	  abort();
+
+	/* Require index register (or constant).  Let's just handle the
+	   register case in the meantime... If the target allows
+	   auto-modify by a constant then we could try replacing a pseduo
+	   register with its equivalent constant where applicable. */
+	if (REG_P (XEXP (op1, 1)))
+	  find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
+				  opnum, type, ind_levels, insn);
+
+	if (REG_P (XEXP (op1, 0)))
+	  {
+	    register int regno = REGNO (XEXP (x, 0));
+	    
+	    /* A register that is incremented cannot be constant!  */
+	    if (regno >= FIRST_PSEUDO_REGISTER
+		&& reg_equiv_constant[regno] != 0)
+	      abort ();
+	    
+	    /* We require a base register here...  */
+	    push_reload (XEXP (op1, 0), XEXP (x, 0),
+			 &XEXP (op1, 0), &XEXP (x, 0), 
+			 reload_address_base_reg_class,
+			 GET_MODE (x), GET_MODE (x), 0, 0,
+			 opnum, RELOAD_OTHER);
+	  }
+	else
+	  abort();
+      }
+      return 0;
+
     case POST_INC:
     case POST_DEC:
     case PRE_INC:
@@ -5703,6 +5789,8 @@ find_equiv_reg (goal, insn, class, other
 	case PRE_INC:
 	case POST_DEC:
 	case PRE_DEC:
+	case POST_MODIFY:
+	case PRE_MODIFY:
 	  return 0;
 	default:
 	  break;
@@ -6115,7 +6203,17 @@ find_inc_amount (x, inced)
 	   || GET_CODE (addr) == POST_INC)
 	  && XEXP (addr, 0) == inced)
 	return GET_MODE_SIZE (GET_MODE (x));
-    }
+      else if ((GET_CODE (addr) == PRE_MODIFY
+		|| GET_CODE (addr) == POST_MODIFY)
+	       && GET_CODE (XEXP (addr, 1)) == PLUS
+	       && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+	       && XEXP (addr, 0) == inced
+	       && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+ 	{ 
+ 	  i = INTVAL (XEXP (XEXP (addr, 1), 1));
+ 	  return i < 0 ? -i : i;
+ 	}
+   }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
Index: reload1.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/reload1.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -p -u -r1.1.1.2 -r1.4
--- reload1.c	1998/05/09 03:34:59	1.1.1.2
+++ reload1.c	1998/05/30 11:26:49	1.4
@@ -3019,6 +3066,8 @@ eliminate_regs (x, mem_mode, insn, stori
     case POST_INC:
     case PRE_DEC:
     case POST_DEC:
+    case POST_MODIFY:
+    case PRE_MODIFY:
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
 	if (ep->to_rtx == XEXP (x, 0))
 	  {
@@ -3031,8 +3080,13 @@ eliminate_regs (x, mem_mode, insn, stori
 #endif
 	    if (code == PRE_DEC || code == POST_DEC)
 	      ep->offset += size;
-	    else
+	    else if (code == PRE_INC || code == POST_INC)
 	      ep->offset -= size;
+	    else if ((code == PRE_MODIFY || code == POST_MODIFY)
+		     && GET_CODE (XEXP (x, 1)) == PLUS
+		     && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
+		     && CONSTANT_P (XEXP (XEXP (x, 1), 1)))
+	      ep->offset -= INTVAL (XEXP (XEXP (x, 1), 1));
 	  }
 
       /* Fall through to generic unary operation case.  */
@@ -6194,7 +6261,9 @@ emit_reload_insns (insn)
 	  if (GET_CODE (oldequiv) == POST_INC
 	      || GET_CODE (oldequiv) == POST_DEC
 	      || GET_CODE (oldequiv) == PRE_INC
-	      || GET_CODE (oldequiv) == PRE_DEC)
+	      || GET_CODE (oldequiv) == PRE_DEC
+	      || GET_CODE (oldequiv) == POST_MODIFY
+	      || GET_CODE (oldequiv) == PRE_MODIFY)
 	    {
 	      /* We are not going to bother supporting the case where a
 		 incremented register can't be copied directly from
@@ -8314,7 +8389,8 @@ reload_cse_simplify_operands (insn)
 		case '#':  case '&':  case '!':
 		case '*':  case '%':  
 		case '0':  case '1':  case '2':  case '3':  case '4':
-		case 'm':  case '<':  case '>':  case 'V':  case 'o':
+		case 'm':  case '<':  case '>':  case '{':  case '}': 
+		case 'V':  case 'o':
 		case 'E':  case 'F':  case 'G':  case 'H':
 		case 's':  case 'i':  case 'n':
 		case 'I':  case 'J':  case 'K':  case 'L':
Index: reorg.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/reorg.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 reorg.c
--- reorg.c	1998/03/20 05:07:07	1.1.1.1
+++ reorg.c	1998/05/30 07:58:49
@@ -620,6 +624,13 @@ mark_set_resources (x, res, in_dest, inc
       mark_set_resources (XEXP (x, 0), res, 1, 0);
       return;
 
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      mark_set_resources (XEXP (x, 0), res, 1, 0);
+      mark_set_resources (XEXP (XEXP (x, 1), 0), res, 0, 0);
+      mark_set_resources (XEXP (XEXP (x, 1), 1), res, 0, 0);
+      return;
+
     case ZERO_EXTRACT:
       mark_set_resources (XEXP (x, 0), res, in_dest, 0);
       mark_set_resources (XEXP (x, 1), res, 0, 0);
Index: rtl.def
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/rtl.def,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -p -u -r1.1.1.1 -r1.2
--- rtl.def	1998/03/20 05:07:08	1.1.1.1
+++ rtl.def	1998/03/20 05:25:41	1.2
@@ -684,6 +684,8 @@ DEF_RTL_EXPR(PRE_DEC, "pre_dec", "e", 'x
 DEF_RTL_EXPR(PRE_INC, "pre_inc", "e", 'x')
 DEF_RTL_EXPR(POST_DEC, "post_dec", "e", 'x')
 DEF_RTL_EXPR(POST_INC, "post_inc", "e", 'x')
+DEF_RTL_EXPR(PRE_MODIFY, "pre_modify", "ee", 'x')
+DEF_RTL_EXPR(POST_MODIFY, "post_modify", "ee", 'x')
 
 /* Comparison operations.  The ordered comparisons exist in two
    flavors, signed and unsigned.  */
Index: rtl.h
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/rtl.h,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 rtl.h
--- rtl.h	1998/03/20 05:07:08	1.1.1.1
+++ rtl.h	1998/05/30 07:58:58
@@ -631,22 +631,55 @@ extern char *note_insn_name[];
 #define FUNCTION_FLAGS_CALLS_LONGJMP 0400
 #define FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE 01000
 
-/* Define a macro to look for REG_INC notes,
-   but save time on machines where they never exist.  */
+/* Cater for machines that only have post increment on writes
+   and pre increment on reads, and other asymmetries.  */
+#ifdef HAVE_PRE_INCREMENT
+#define HAVE_PRE_INCREMENT_READ
+#define HAVE_PRE_INCREMENT_WRITE
+#endif
 
-/* Don't continue this line--convex cc version 4.1 would lose.  */
-#if (defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) || defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT))
-#define FIND_REG_INC_NOTE(insn, reg) (find_reg_note ((insn), REG_INC, (reg)))
-#else
-#define FIND_REG_INC_NOTE(insn, reg) 0
+#ifdef HAVE_PRE_DECREMENT
+#define HAVE_PRE_DECREMENT_READ
+#define HAVE_PRE_DECREMENT_WRITE
+#endif
+
+#ifdef HAVE_POST_INCREMENT
+#define HAVE_POST_INCREMENT_READ
+#define HAVE_POST_INCREMENT_WRITE
+#endif
+
+#ifdef HAVE_POST_DECREMENT
+#define HAVE_POST_DECREMENT_READ
+#define HAVE_POST_DECREMENT_WRITE
+#endif
+
+#if (defined (HAVE_PRE_MODIFY_DISP) || defined (HAVE_PRE_MODIFY_REG) || defined (HAVE_POST_MODIFY_DISP) || defined (HAVE_POST_MODIFY_REG))
+#define HAVE_AUTO_MODIFY
+#endif
+
+#if (defined (HAVE_PRE_INCREMENT_READ) || defined (HAVE_PRE_INCREMENT_WRITE) || defined (HAVE_POST_INCREMENT_READ) || defined (HAVE_POST_INCREMENT_WRITE))
+#define HAVE_AUTO_INC
+#endif
+
+#if (defined (HAVE_PRE_DECREMENT_READ) || defined (HAVE_PRE_DECREMENT_WRITE) || defined (HAVE_POST_DECREMENT_READ) || defined (HAVE_POST_DECREMENT_WRITE))
+#define HAVE_AUTO_DEC
 #endif
 
 /* Indicate whether the machine has any sort of auto increment addressing.
    If not, we can avoid checking for REG_INC notes.  */
 
 /* Don't continue this line--convex cc version 4.1 would lose.  */
-#if (defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) || defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT))
+#if (defined (HAVE_AUTO_MODIFY) || defined (HAVE_AUTO_INC) || defined (HAVE_AUTO_DEC))
 #define AUTO_INC_DEC
+#endif
+
+/* Define a macro to look for REG_INC notes,
+   but save time on machines where they never exist.  */
+
+#ifdef AUTO_INC_DEC
+#define FIND_REG_INC_NOTE(insn, reg) (find_reg_note ((insn), REG_INC, (reg)))
+#else
+#define FIND_REG_INC_NOTE(insn, reg) 0
 #endif
 
 /* Generally useful functions.  */
Index: rtl.texi
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/rtl.texi,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -p -u -r1.1.1.1 -r1.2
--- rtl.texi	1998/03/20 05:07:08	1.1.1.1
+++ rtl.texi	1998/03/20 05:25:43	1.2
@@ -2011,7 +2011,7 @@ space is given to each address-differenc
 @cindex RTL predecrement
 @cindex RTL postdecrement
 
-Four special side-effect expression codes appear as memory addresses.
+Six special side-effect expression codes appear as memory addresses.
 
 @table @code
 @findex pre_dec
@@ -2046,6 +2046,39 @@ being decremented.
 @findex post_inc
 @item (post_inc:@var{m} @var{x})
 Similar, but specifies incrementing @var{x} instead of decrementing it.
+
+@findex post_modify
+@item (post_modify:@var{m} @var{x} @var{y})
+
+Represents the side effect of setting @var{x} to @var{y} and
+represents @var{x} before @var{x} is modified.  @var{x} must be a
+@code{reg} or @code{mem}, but most machines allow only a @code{reg}.
+@var{m} must be the machine mode for pointers on the machine in use.
+The amount @var{x} is decremented by is the length in bytes of the
+machine mode of the containing memory reference of which this expression
+serves as the address.
+
+The expression @var{y} must be one of three forms:
+@table @code
+@code{(plus:@var{m} @var{x} @var{z})},
+@code{(minus:@var{m} @var{x} @var{z})}, or
+@code{(plus:@var{m} @var{x} @var{i})},
+@end table
+where @var{z} is an index register and @var{i} is a constant.
+
+Here is an example of its use:@refill
+
+@example
+(mem:SF (post_modify:SI (reg:SI 42) (plus (reg:SI 42) (reg:SI 48))))
+@end example
+
+This says to modify pseudo register 42 by adding the contents of pseudo
+register 48 to it, after the use of what ever 42 points to.
+
+@findex post_modify
+@item (pre_modify:@var{m} @var{x} @var{expr})
+Similar except sideffects happen before the use.
+
 @end table
 
 These embedded side effect expressions must be used with care.  Instruction
Index: rtlanal.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/rtlanal.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 rtlanal.c
--- rtlanal.c	1998/03/20 05:07:09	1.1.1.1
+++ rtlanal.c	1998/05/30 07:58:49
@@ -560,10 +560,11 @@ modified_in_p (x, insn)
      rtx x;
      rtx insn;
 {
-  enum rtx_code code = GET_CODE (x);
+  enum rtx_code code;
   char *fmt;
   int i, j;
 
+  code = GET_CODE (x);
   switch (code)
     {
     case CONST_INT:
@@ -1570,6 +1571,8 @@ side_effects_p (x)
     case PRE_DEC:
     case POST_INC:
     case POST_DEC:
+    case POST_MODIFY:
+    case PRE_MODIFY:
     case CALL:
     case UNSPEC_VOLATILE:
  /* case TRAP_IF: This isn't clear yet.  */
@@ -1954,7 +1957,7 @@ jmp_uses_reg_or_mem (x)
 /* Return nonzero if INSN is an indirect jump (aka computed jump).
 
    Tablejumps and casesi insns are not considered indirect jumps;
-   we can recognize them by a (use (lael_ref)).  */
+   we can recognize them by a (use (label_ref)).  */
 
 int
 computed_jump_p (insn)
Index: sched.c
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/sched.c,v
retrieving revision 1.1.1.1
diff -p -u -r1.1.1.1 sched.c
--- sched.c	1998/03/20 05:07:09	1.1.1.1
+++ sched.c	1998/05/30 07:58:49
@@ -1716,14 +1716,16 @@ sched_analyze_1 (x, insn)
   if (GET_CODE (dest) == REG)
     {
       register int i;
+      enum machine_mode mode;
 
       regno = REGNO (dest);
+      mode = GET_MODE (dest);
 
       /* A hard reg in a wide mode may really be multiple registers.
 	 If so, mark all of them just like the first.  */
       if (regno < FIRST_PSEUDO_REGISTER)
 	{
-	  i = HARD_REGNO_NREGS (regno, GET_MODE (dest));
+	  i = HARD_REGNO_NREGS (regno, mode);
 	  while (--i >= 0)
 	    {
 	      rtx u;
@@ -1735,7 +1737,7 @@ sched_analyze_1 (x, insn)
 		add_dependence (insn, reg_last_sets[regno + i],
 				REG_DEP_OUTPUT);
 	      SET_REGNO_REG_SET (reg_pending_sets, regno + i);
-	      if ((call_used_regs[i] || global_regs[i])
+	      if ((HARD_REGNO_CALL_CLOBBERED (i, mode) || global_regs[i])
 		  && last_function_call)
 		/* Function calls clobber all call_used regs.  */
 		add_dependence (insn, last_function_call, REG_DEP_ANTI);
@@ -1884,11 +1886,13 @@ sched_analyze_2 (x, insn)
     case REG:
       {
 	int regno = REGNO (x);
+	enum machine_mode mode = GET_MODE (x);
+
 	if (regno < FIRST_PSEUDO_REGISTER)
 	  {
 	    int i;
 
-	    i = HARD_REGNO_NREGS (regno, GET_MODE (x));
+	    i = HARD_REGNO_NREGS (regno, mode);
 	    while (--i >= 0)
 	      {
 		reg_last_uses[regno + i]
@@ -1896,7 +1900,8 @@ sched_analyze_2 (x, insn)
 			     insn, reg_last_uses[regno + i]);
 		if (reg_last_sets[regno + i])
 		  add_dependence (insn, reg_last_sets[regno + i], 0);
-		if ((call_used_regs[regno + i] || global_regs[regno + i])
+		if ((HARD_REGNO_CALL_CLOBBERED (regno + i, mode)
+		     || global_regs[regno + i])
 		    && last_function_call)
 		  /* Function calls clobber all call_used regs.  */
 		  add_dependence (insn, last_function_call, REG_DEP_ANTI);
@@ -2028,6 +2033,14 @@ sched_analyze_2 (x, insn)
       sched_analyze_1 (x, insn);
       return;
       
+    case POST_MODIFY:
+    case PRE_MODIFY:
+      /* op0 = op0 + op1 */
+      sched_analyze_2 (XEXP (x, 0), insn);
+      sched_analyze_2 (XEXP (x, 1), insn);
+      sched_analyze_1 (x, insn);
+      return;
+
     default:
       break;
     }
Index: tm.texi
===================================================================
RCS file: /usr/local/src/cvsroot/gnu/gcc/tm.texi,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -p -u -r1.1.1.2 -r1.2
--- tm.texi	1998/05/09 03:35:09	1.1.1.2
+++ tm.texi	1998/03/20 05:25:49	1.2
@@ -4042,16 +4050,60 @@ This is about addressing modes.
 @table @code
 @findex HAVE_POST_INCREMENT
 @item HAVE_POST_INCREMENT
-Define this macro if the machine supports post-increment addressing.
+Define this macro if the machine supports post-increment addressing
+for both read and write operands.
+
+@findex HAVE_POST_INCREMENT_READ
+@item HAVE_POST_INCREMENT_READ
+Define this macro if the machine supports post-increment addressing
+but only for operands that are read.
+
+@findex HAVE_POST_INCREMENT_WRITE
+@item HAVE_POST_INCREMENT_WRITE
+Define this macro if the machine supports post-increment addressing
+but only for operands that are written.
 
 @findex HAVE_PRE_INCREMENT
 @findex HAVE_POST_DECREMENT
 @findex HAVE_PRE_DECREMENT
+@findex HAVE_PRE_INCREMENT_READ
+@findex HAVE_POST_DECREMENT_READ
+@findex HAVE_PRE_DECREMENT_READ
+@findex HAVE_PRE_INCREMENT_WRITE
+@findex HAVE_POST_DECREMENT_WRITE
+@findex HAVE_PRE_DECREMENT_WRITE
 @item HAVE_PRE_INCREMENT
 @itemx HAVE_POST_DECREMENT
 @itemx HAVE_PRE_DECREMENT
+@item HAVE_PRE_INCREMENT_READ
+@itemx HAVE_POST_DECREMENT_READ
+@itemx HAVE_PRE_DECREMENT_READ
+@item HAVE_PRE_INCREMENT_WRITE
+@itemx HAVE_POST_DECREMENT_WRITE
+@itemx HAVE_PRE_DECREMENT_WRITE
+
 Similar for other kinds of addressing.
 
+@findex HAVE_POST_MODIFY_DISP
+@item HAVE_POST_MODIFY_DISP
+Define this macro if the machine supports post-modify addressing
+with a constant displacement.
+
+@findex HAVE_PRE_MODIFY_DISP
+@item HAVE_PRE_MODIFY_DISP
+Define this macro if the machine supports pre-modify addressing
+with a constant displacement.
+
+@findex HAVE_POST_MODIFY_REG
+@item HAVE_POST_MODIFY_REG
+Define this macro if the machine supports post-modify addressing
+by the contents of a register.
+
+@findex HAVE_PRE_MODIFY_REG
+@item HAVE_PRE_MODIFY_REG
+Define this macro if the machine supports pre-modify addressing
+by the contents of a register.
+
 @findex CONSTANT_ADDRESS_P
 @item CONSTANT_ADDRESS_P (@var{x})
 A C expression that is 1 if the RTX @var{x} is a constant which


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