This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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, ¬es); /* 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, ¬es); /* 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.