This is the mail archive of the gcc-patches@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]

[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)
     {


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