This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR middle-end/28690, indexed load/store performance + reload bug
- From: Peter Bergner <bergner at vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 4 Dec 2006 23:08:08 -0600
- Subject: [PATCH] Fix PR middle-end/28690, indexed load/store performance + reload bug
The following patch fixes PR middle-end/28690 which is a performance regression
for indexed load/stores. The patch to rtlanal.c and tree-ssa-address.c exposed
a latent reload bug, which is included here. The reload bug was exposed by
this patch, by passing eliminate_regs_in_insn() a PARALLEL insn of a load with
update instruction, where the load portion had a REG_UNUSED flag set.
This allowed single_set() to return non NULL and we ended up not eliminating
the entire PARALLEL which caused us to back out the register elimination and
we ended up generating bogus assembler. More details are in the bugzila.
This bootstrapped and regtested with no errors on powerpc64-linux (-m32 & -m64).
Ok for mainline?
Peter
2006-12-04 Peter Bergner <bergner@vnet.ibm.com>
PR middle-end/28690
* rtlanal.c (swap_commutative_operands_p): Preference a REG_POINTER
over a non REG_POINTER.
* tree-ssa-address.c (gen_addr_rtx): Force a REG_POINTER to be
the first operand of a PLUS.
* reload1.c (eliminate_regs_in_insn): Don't call single_set() on
PARALLEL insns.
Index: rtlanal.c
===================================================================
--- rtlanal.c (revision 119497)
+++ rtlanal.c (working copy)
@@ -2807,8 +2807,18 @@ commutative_operand_precedence (rtx op)
int
swap_commutative_operands_p (rtx x, rtx y)
{
- return (commutative_operand_precedence (x)
- < commutative_operand_precedence (y));
+ int precedence_x = commutative_operand_precedence (x);
+ int precedence_y = commutative_operand_precedence (y);
+
+ /* Everything else being equal, preference registers with pointers
+ over registers without pointers. This is desirable for performance
+ reasons on indexed load/store instructions for some processors. */
+ if ((precedence_x == precedence_y)
+ && REG_P (x) && !REG_POINTER (x)
+ && REG_P (y) && REG_POINTER (y))
+ return 1;
+
+ return precedence_x < precedence_y;
}
/* Return 1 if X is an autoincrement side effect and the register is
Index: tree-ssa-address.c
===================================================================
--- tree-ssa-address.c (revision 119497)
+++ tree-ssa-address.c (working copy)
@@ -124,7 +124,15 @@ gen_addr_rtx (rtx symbol, rtx base, rtx
if (base)
{
if (*addr)
- *addr = gen_rtx_PLUS (Pmode, *addr, base);
+ {
+ /* For performance reasons on some processors, prefer
+ the pointer being the first operand of the PLUS. */
+ if (REG_P (*addr) && !REG_POINTER (*addr)
+ && REG_P (base) && REG_POINTER (base))
+ *addr = gen_rtx_PLUS (Pmode, base, *addr);
+ else
+ *addr = gen_rtx_PLUS (Pmode, *addr, base);
+ }
else
*addr = base;
}
Index: reload1.c
===================================================================
--- reload1.c (revision 119497)
+++ reload1.c (working copy)
@@ -2930,7 +2930,7 @@ eliminate_regs_in_insn (rtx insn, int re
int icode = recog_memoized (insn);
rtx old_body = PATTERN (insn);
int insn_is_asm = asm_noperands (old_body) >= 0;
- rtx old_set = single_set (insn);
+ rtx old_set;
rtx new_body;
int val = 0;
int i;
@@ -2949,6 +2949,12 @@ eliminate_regs_in_insn (rtx insn, int re
return 0;
}
+ /* Guard against a PARALLEL with a REG_UNUSED note. */
+ if (GET_CODE (PATTERN (insn)) != PARALLEL)
+ old_set = single_set (insn);
+ else
+ old_set = 0;
+
if (old_set != 0 && REG_P (SET_DEST (old_set))
&& REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER)
{