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]

ia64 aliasing improvements


This patch makes alias analysis more effective on ia64.  This is done by
1) using ORIGINAL_REGNO instead of REGNO for accessing some arrays.
2) detecting more cases of known values for registers, such as additions
   of a known value and a constant
3) using known values when deciding whether a memory reference can trap
4) allowing scheduling memory references that can't trap across jumps
   in sched_ebbs.

Bootstrapped & tested on i686-linux, I'm fairly sure I also had a succesful
bootstrap on ia64-linux a few days ago.  SPECint95 is compiled correctly on
ia64-linux with this patch.


Bernd

	* alias.c (throughout): Use ORIGINAL_REGNO when accessing
	reg_base_value and reg_known_value arrays.
	(init_alias_analysis): Add more cases to detect known values.
	* sched-deps.c (deps_may_trap_p): New function.
	(sched_analyze_2): Use it.

Index: alias.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/alias.c,v
retrieving revision 1.110
diff -u -p -r1.110 alias.c
--- alias.c	2001/01/01 17:20:08	1.110
+++ alias.c	2001/01/03 14:48:08
@@ -148,7 +148,8 @@ static rtx *new_reg_base_value;
 static unsigned int reg_base_value_size; /* size of reg_base_value array */

 #define REG_BASE_VALUE(X) \
-  (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
+  (ORIGINAL_REGNO (X) < reg_base_value_size \
+   ? reg_base_value[ORIGINAL_REGNO (X)] : 0)

 /* Vector of known invariant relationships between registers.  Set in
    loop unrolling.  Indexed by register number, if nonzero the value
@@ -659,6 +660,7 @@ static rtx
 find_base_value (src)
      register rtx src;
 {
+  unsigned int regno;
   switch (GET_CODE (src))
     {
     case SYMBOL_REF:
@@ -666,12 +668,13 @@ find_base_value (src)
       return src;

     case REG:
+      regno = ORIGINAL_REGNO (src);
       /* At the start of a function, argument registers have known base
 	 values which may be lost later.  Returning an ADDRESS
 	 expression here allows optimization based on argument values
 	 even when the argument registers are used for other purposes.  */
-      if (REGNO (src) < FIRST_PSEUDO_REGISTER && copying_arguments)
-	return new_reg_base_value[REGNO (src)];
+      if (regno < FIRST_PSEUDO_REGISTER && copying_arguments)
+	return new_reg_base_value[regno];

       /* If a pseudo has a known base value, return it.  Do not do this
 	 for hard regs since it can result in a circular dependency
@@ -679,10 +682,10 @@ find_base_value (src)

 	 The test above is not sufficient because the scheduler may move
 	 a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN.  */
-      if (REGNO (src) >= FIRST_PSEUDO_REGISTER
-	  && (unsigned) REGNO (src) < reg_base_value_size
-	  && reg_base_value[REGNO (src)])
-	return reg_base_value[REGNO (src)];
+      if (regno >= FIRST_PSEUDO_REGISTER
+	  && regno < reg_base_value_size
+	  && reg_base_value[regno])
+	return reg_base_value[regno];

       return src;

@@ -789,7 +792,7 @@ record_set (dest, set, data)
   if (GET_CODE (dest) != REG)
     return;

-  regno = REGNO (dest);
+  regno = ORIGINAL_REGNO (dest);

   if (regno >= reg_base_value_size)
     abort ();
@@ -870,8 +873,8 @@ record_base_value (regno, val, invariant

   if (GET_CODE (val) == REG)
     {
-      if (REGNO (val) < reg_base_value_size)
-	reg_base_value[regno] = reg_base_value[REGNO (val)];
+      if (ORIGINAL_REGNO (val) < reg_base_value_size)
+	reg_base_value[regno] = reg_base_value[ORIGINAL_REGNO (val)];

       return;
     }
@@ -889,10 +892,10 @@ canon_rtx (x)
      rtx x;
 {
   /* Recursively look for equivalences.  */
-  if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
-      && REGNO (x) < reg_known_value_size)
-    return reg_known_value[REGNO (x)] == x
-      ? x : canon_rtx (reg_known_value[REGNO (x)]);
+  if (GET_CODE (x) == REG && ORIGINAL_REGNO (x) >= FIRST_PSEUDO_REGISTER
+      && ORIGINAL_REGNO (x) < reg_known_value_size)
+    return reg_known_value[ORIGINAL_REGNO (x)] == x
+      ? x : canon_rtx (reg_known_value[ORIGINAL_REGNO (x)]);
   else if (GET_CODE (x) == PLUS)
     {
       rtx x0 = canon_rtx (XEXP (x, 0));
@@ -2208,17 +2211,42 @@ init_alias_analysis ()

 	      if (set != 0
 		  && GET_CODE (SET_DEST (set)) == REG
-		  && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
-		  && REG_NOTES (insn) != 0
-		  && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
-		       && REG_N_SETS (REGNO (SET_DEST (set))) == 1)
-		      || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
-		  && GET_CODE (XEXP (note, 0)) != EXPR_LIST
-		  && ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
+		  && ORIGINAL_REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
 		{
-		  int regno = REGNO (SET_DEST (set));
-		  reg_known_value[regno] = XEXP (note, 0);
-		  reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
+		  unsigned int regno = ORIGINAL_REGNO (SET_DEST (set));
+		  rtx src = SET_SRC (set);
+
+		  if (REG_NOTES (insn) != 0
+		      && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
+			   && REG_N_SETS (regno) == 1)
+			  || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
+		      && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+		      && ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
+		    {
+		      reg_known_value[regno] = XEXP (note, 0);
+		      reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
+		    }
+		  else if (REG_N_SETS (regno) == 1
+			   && GET_CODE (src) == PLUS
+			   && GET_CODE (XEXP (src, 0)) == REG
+			   && ORIGINAL_REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
+			   && (reg_known_value[ORIGINAL_REGNO (XEXP (src, 0))])
+			   && GET_CODE (XEXP (src, 1)) == CONST_INT)
+		    {
+		      rtx op0 = XEXP (src, 0);
+		      if (reg_known_value[ORIGINAL_REGNO (op0)])
+			op0 = reg_known_value[ORIGINAL_REGNO (op0)];
+		      reg_known_value[regno]
+			= plus_constant_for_output (op0,
+						    INTVAL (XEXP (src, 1)));
+		      reg_known_equiv_p[regno] = 0;
+		    }
+		  else if (REG_N_SETS (regno) == 1
+			   && ! rtx_varies_p (src, 1))
+		    {
+		      reg_known_value[regno] = src;
+		      reg_known_equiv_p[regno] = 0;
+		    }
 		}
 	    }
 	  else if (GET_CODE (insn) == NOTE
@@ -2265,7 +2293,7 @@ init_alias_analysis ()
 	  rtx base = reg_base_value[ui];
 	  if (base && GET_CODE (base) == REG)
 	    {
-	      unsigned int base_regno = REGNO (base);
+	      unsigned int base_regno = ORIGINAL_REGNO (base);
 	      if (base_regno == ui)		/* register set from itself */
 		reg_base_value[ui] = 0;
 	      else
Index: sched-deps.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/sched-deps.c,v
retrieving revision 1.4
diff -u -p -r1.4 sched-deps.c
--- sched-deps.c	2000/12/27 12:55:16	1.4
+++ sched-deps.c	2001/01/03 14:48:09
@@ -74,6 +74,7 @@ static sbitmap *output_dependency_cache;
 static sbitmap *forward_dependency_cache;
 #endif

+static int deps_may_trap_p PARAMS ((rtx));
 static void remove_dependence PARAMS ((rtx, rtx));
 static void set_sched_group_p PARAMS ((rtx));

@@ -86,6 +87,21 @@ static rtx group_leader PARAMS ((rtx));
 static rtx get_condition PARAMS ((rtx));
 static int conditions_mutex_p PARAMS ((rtx, rtx));

+/* Return nonzero if a load of the memory reference MEM can cause a trap.  */
+
+static int
+deps_may_trap_p (mem)
+     rtx mem;
+{
+  rtx addr = XEXP (mem, 0);
+
+  if (REG_P (addr)
+      && ORIGINAL_REGNO (addr) >= FIRST_PSEUDO_REGISTER
+      && reg_known_value[ORIGINAL_REGNO (addr)])
+    addr = reg_known_value[ORIGINAL_REGNO (addr)];
+  return rtx_addr_can_trap_p (addr);
+}
+
 /* Return the INSN_LIST containing INSN in LIST, or NULL
    if LIST does not contain INSN.  */

@@ -817,7 +833,9 @@ sched_analyze_2 (deps, x, insn)
 	  }

 	for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
-	  add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
+	  if (GET_CODE (XEXP (u, 0)) != JUMP_INSN
+	      || deps_may_trap_p (x))
+	    add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);

 	/* Always add these dependencies to pending_reads, since
 	   this insn may be followed by a write.  */


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