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]

Re: Autoincrement examples


Bernd Schmidt <bernds@cygnus.co.uk> writes:

> I'm playing with a patch to improve the generation of auto-increment
> addressing modes, e.g. by generating POST_MODIFY and PRE_MODIFY rtxs for
> targets where this is possible.

Few months ago I'm playing with autoincrement/autodecrement addressing
mode.
(I'm playing with my own gcc port: ATMEL AVR - 8bit microcontroller)

Combiner pass generate (and try to recognize) insns like:
(parallel [(set (mem:MODE (reg1)) reg2)
	   (set (reg1) (plus (reg1) (const_int MODE_SIZE)))])

IMHO: Combiner must transform this insn to insn with post increment
address.
(I'm know about flow pass - flow must do this.
But combine must transform insns to POST/PRE DECRE/INCRE MENT form if
it's possible.)

This is my experimental code.
I'm call `try_auto_inc' from `recog_for_combine' immediately before:

  insn_code_number = recog (pat, insn, &num_clobbers_to_add);

as:

  pat = try_auto_inc (pnewpat, insn, &notes);       /* XXXX */

  /* Is the result of combination a valid instruction?  */
  insn_code_number = recog (pat, insn, &num_clobbers_to_add);


try_auto_inc and try_auto_inc_1 :


rtx 
try_auto_inc_1 (reg, mem_addr, set)
     rtx reg;
     rtx mem_addr;
     rtx set;
{
  if (GET_CODE (set) == SET)
    {
      rtx addr = XEXP (mem_addr,0);
      HOST_WIDE_INT offset = 0;
      
      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
	  && ! reg_overlap_mentioned_p (addr, reg))
	{
	  register rtx y;
	  register int size = GET_MODE_SIZE (GET_MODE (mem_addr));

	  /* Is the next use an increment that might make auto-increment? */
	  if ((y = SET_SRC (set), GET_CODE (y) == PLUS)  )
	    if (XEXP (y, 0) == addr && addr == SET_DEST (y))
	      if (GET_CODE (XEXP (y, 1)) == CONST_INT)
		if ((HAVE_POST_INCREMENT
		   && (INTVAL (XEXP (y, 1)) == size && offset == 0))
		  || (HAVE_POST_DECREMENT
		      && (INTVAL (XEXP (y, 1)) == - size && offset == 0))
		  || (HAVE_PRE_INCREMENT
		      && (INTVAL (XEXP (y, 1)) == size && offset == size))
		  || (HAVE_PRE_DECREMENT
		      && (INTVAL (XEXP (y, 1)) == - size
			  && offset == - size)))
	    {
	      enum rtx_code inc_code = (INTVAL (XEXP (y, 1)) == size
					? (offset ? PRE_INC : POST_INC)
					: (offset ? PRE_DEC : POST_DEC));

	      /* This is the simple case.  Try to make the auto-inc. */
	      return gen_rtx_MEM (GET_MODE (mem_addr),
				  gen_rtx_fmt_e (inc_code, Pmode, addr));
	    }
	}
    }
  return NULL_RTX;
}

rtx
try_auto_inc (pnewpat, insn, pnotes)
     rtx *pnewpat;
     rtx insn;
     rtx *pnotes;
{
  rtx pat = *pnewpat;
  rtx new_rtx;
  rtx *new_mem;
  if (GET_CODE (pat) == PARALLEL
      && XVECLEN (pat, 0) == 2)
    {
      rtx incr = XVECEXP (pat, 0, 1);
      rtx x = XVECEXP (pat, 0, 0);
      rtx addr;
      rtx reg;
      if (GET_CODE (SET_SRC (x)) == MEM && REG_P (SET_DEST (x)))
	{
	  addr = SET_SRC (x);
	  reg = SET_DEST (x);
	  new_rtx = gen_rtx_SET (VOIDmode, reg, addr);
	  new_mem = &XEXP (new_rtx,1);
	}
      else if (GET_CODE (SET_DEST (x)) == MEM && REG_P (SET_SRC (x)))
	{
	  addr = SET_DEST (x);
	  reg = SET_SRC (x);
	  new_rtx = gen_rtx_SET (VOIDmode, addr, reg);
	  new_mem = &XEXP (new_rtx,0);
	}
      else
	return *pnewpat;
      if (pat = try_auto_inc_1 (reg, addr, incr))
	{
	  *new_mem = pat;
	  *pnewpat = new_rtx;
	  /* insn has an implicit side effect. */
  	  /* Warning !!! */
	  /* combine don't work correctly with NOTES */
          /* combine.c must be changed. */
	  *pnotes = gen_rtx_EXPR_LIST (REG_INC, XEXP (addr,0), 0);
	}
    }
  return *pnewpat;
}


Patch for combine.c:

===File ~/d/Archive/gcc/egcs-19990502/gcc/combiner-patch====
*** combine.c	Thu Mar 25 19:54:31 1999
--- /disk5/egcs-19990502/gcc/combine.c	Thu Jul 15 23:17:05 1999
*************** try_combine (i3, i2, i1)
*** 2235,2241 ****
  	}
  
        for (note = new_other_notes; note; note = XEXP (note, 1))
! 	if (GET_CODE (XEXP (note, 0)) == REG)
  	  REG_N_DEATHS (REGNO (XEXP (note, 0)))++;
  
        distribute_notes (new_other_notes, undobuf.other_insn,
--- 2235,2243 ----
  	}
  
        for (note = new_other_notes; note; note = XEXP (note, 1))
! 	if ((REG_NOTE_KIND (note) == REG_UNUSED
! 	     || REG_NOTE_KIND (note) == REG_DEAD)
! 	    && GET_CODE (XEXP (note, 0)) == REG)
  	  REG_N_DEATHS (REGNO (XEXP (note, 0)))++;
  
        distribute_notes (new_other_notes, undobuf.other_insn,
*************** try_combine (i3, i2, i1)
*** 2391,2397 ****
      if (newi2pat && new_i2_notes)
        {
  	for (temp = new_i2_notes; temp; temp = XEXP (temp, 1))
! 	  if (GET_CODE (XEXP (temp, 0)) == REG)
  	    REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
  	
  	distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX);
--- 2393,2401 ----
      if (newi2pat && new_i2_notes)
        {
  	for (temp = new_i2_notes; temp; temp = XEXP (temp, 1))
! 	  if ((REG_NOTE_KIND (temp) == REG_UNUSED
! 	       || REG_NOTE_KIND (temp) == REG_DEAD)
! 	      && GET_CODE (XEXP (temp, 0)) == REG)
  	    REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
  	
  	distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX);
*************** try_combine (i3, i2, i1)
*** 2400,2406 ****
      if (new_i3_notes)
        {
  	for (temp = new_i3_notes; temp; temp = XEXP (temp, 1))
! 	  if (GET_CODE (XEXP (temp, 0)) == REG)
  	    REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
  	
  	distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX);
--- 2404,2412 ----
      if (new_i3_notes)
        {
  	for (temp = new_i3_notes; temp; temp = XEXP (temp, 1))
! 	  if ((REG_NOTE_KIND (temp) == REG_UNUSED
! 	       || REG_NOTE_KIND (temp) == REG_DEAD)
! 	      && GET_CODE (XEXP (temp, 0)) == REG)
  	    REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
  	
  	distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX);
*************** recog_for_combine (pnewpat, insn, pnotes
*** 9115,9120 ****
--- 9124,9131 ----
        if (GET_CODE (XVECEXP (pat, 0, i)) == CLOBBER
  	  && XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
  	return -1;
+ 
+  pat = try_auto_inc (pnewpat, insn, &notes);	/* XXXX */
  
    /* Is the result of combination a valid instruction?  */
    insn_code_number = recog (pat, insn, &num_clobbers_to_add);
============================================================


Also patch for rtlanal.c needed:

===File ~/d/Archive/gcc/egcs-19990502/gcc/rtlanal-patch=====
*** rtlanal.c	Mon Apr 12 06:18:55 1999
--- /disk5/egcs-19990502/gcc/rtlanal.c	Tue May 25 21:41:14 1999
*************** dead_or_set_regno_p (insn, test_regno)
*** 1292,1308 ****
       TEST_REGNO.  */
    for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
      {
!       if (REG_NOTE_KIND (link) != REG_DEAD
! 	  || GET_CODE (XEXP (link, 0)) != REG)
! 	continue;
! 
!       regno = REGNO (XEXP (link, 0));
!       endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
! 		  : regno + HARD_REGNO_NREGS (regno,
! 					      GET_MODE (XEXP (link, 0))));
! 
!       if (test_regno >= regno && test_regno < endregno)
! 	return 1;
      }
  
    if (GET_CODE (insn) == CALL_INSN
--- 1292,1308 ----
       TEST_REGNO.  */
    for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
      {
!       if ((REG_NOTE_KIND (link) == REG_DEAD || REG_NOTE_KIND (link) == REG_INC)
! 	  && GET_CODE (XEXP (link, 0)) == REG)
! 	{
! 	  regno = REGNO (XEXP (link, 0));
! 	  endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
! 		      : regno + HARD_REGNO_NREGS (regno,
! 						  GET_MODE (XEXP (link, 0))));
! 	  
! 	  if (test_regno >= regno && test_regno < endregno)
! 	    return 1;
! 	}
      }
  
    if (GET_CODE (insn) == CALL_INSN
============================================================


Denis.

PS: all my patches may be too old because they against egcs-19990502.


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