stop unnecessary spills in gcc/reload1.c

edmundo@rano.demon.co.uk edmundo@rano.demon.co.uk
Tue Jun 15 15:52:00 GMT 1999


The reaction to my previous patch was underwhelming, but here's a new
version of it anyway. This is supposed to have exactly the same effect
as the previous patch, but with more maintainable code, I hope.

I'd be grateful if anyone could test this, particularly on other
architectures than Intel.

It bootstraps nicely on Intel and gives better code in some cases.

Edmund


--- egcs/gcc/reload1.c.orig	Sat May  8 02:34:55 1999
+++ egcs/gcc/reload1.c	Tue Jun 15 20:49:41 1999
@@ -373,6 +373,7 @@
 };
 
 static void maybe_fix_stack_asms	PROTO((void));
+static void delete_equivalencing_insns	PROTO((int));
 static void calculate_needs_all_insns	PROTO((int));
 static void calculate_needs		PROTO((struct insn_chain *));
 static void find_reload_regs		PROTO((struct insn_chain *chain,
@@ -952,6 +953,9 @@
 	  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
 	}
 
+      /* Mark equivalencing instructions for possible deletion later.  */
+      delete_equivalencing_insns (0);
+
       calculate_needs_all_insns (global);
 
       CLEAR_REG_SET (spilled_pseudos);
@@ -994,7 +998,11 @@
 	find_reload_regs (chain, dumpfile);
 
       if (failure)
-	goto failed;
+	{
+	  /* Cancel the list of equivalencing insns.  */
+	  delete_equivalencing_insns (2);
+	  goto failed;
+	}
 
       if (insns_need_reload != 0 || did_spill)
 	something_changed |= finish_spills (global, dumpfile);
@@ -1013,34 +1021,8 @@
       if (ep->can_eliminate)
 	mark_elimination (ep->from, ep->to);
 
-  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
-     If that insn didn't set the register (i.e., it copied the register to
-     memory), just delete that insn instead of the equivalencing insn plus
-     anything now dead.  If we call delete_dead_insn on that insn, we may
-     delete the insn that actually sets the register if the register dies
-     there and that is incorrect.  */
-
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    {
-      if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
-	{
-	  rtx list;
-	  for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
-	    {
-	      rtx equiv_insn = XEXP (list, 0);
-	      if (GET_CODE (equiv_insn) == NOTE)
-		continue;
-	      if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
-		delete_dead_insn (equiv_insn);
-	      else
-		{
-		  PUT_CODE (equiv_insn, NOTE);
-		  NOTE_SOURCE_FILE (equiv_insn) = 0;
-		  NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
-		}
-	    }
-	}
-    }
+  /* Delete the equivalencing insns which we marked earlier.  */
+  delete_equivalencing_insns (1);
 
   /* Use the reload registers where necessary
      by generating move instructions to move the must-be-register
@@ -1345,6 +1327,97 @@
 #endif
 }
 
+static void
+delete_equivalencing_insns (action)
+     int action;
+{
+  struct list {
+    struct list *next; 
+    rtx insn;
+  };
+  static struct list *insn_list = 0;
+  struct list *p, *next;
+  int i;
+
+  /* Unmark the insns we marked earlier, and delete the list.
+     If action == 1, then delete the insns, too.  */
+  for (p = insn_list; p; p = next)
+    {
+      INSN_DELETED_P (p->insn) = 0;
+      if (action == 1)
+	{
+	  PUT_CODE (p->insn, NOTE);
+	  NOTE_SOURCE_FILE (p->insn) = 0;
+	  NOTE_LINE_NUMBER (p->insn) = NOTE_INSN_DELETED;
+	}
+      next = p->next;
+      free (p);
+    }
+  insn_list = 0;
+
+  if (action)
+    return;
+
+  /* If action == 0, make a list of deletable equivalencing
+     insns and mark them for possible deletion later.  */
+
+  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
+     If that insn didn't set the register (i.e., it copied the register to
+     memory), just delete that insn instead of the equivalencing insn plus
+     anything now dead.  If we delete previous insns from that insn, we may
+     delete the insn that actually sets the register if the register dies
+     there and that is incorrect.  */
+
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
+	{
+	  rtx list;
+	  for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
+	    {
+	      rtx insn = XEXP (list, 0);
+	      if (GET_CODE (insn) == NOTE)
+		continue;
+	      if (reg_set_p (regno_reg_rtx[i], PATTERN (insn)))
+		for (;;)
+		  {
+		    rtx prev = prev_real_insn (insn);
+		    rtx prev_dest;
+
+		    INSN_DELETED_P (insn) = 1;
+		    p = (struct list *) xmalloc (sizeof (struct list));
+		    p->insn = insn;
+		    p->next = insn_list;
+		    insn_list = p;
+
+		    /* If the previous insn sets a register that dies
+		       in our insn, delete it too.  */
+		    if (prev && GET_CODE (PATTERN (prev)) == SET
+			&& (prev_dest = SET_DEST (PATTERN (prev)),
+			    GET_CODE (prev_dest) == REG)
+			&& reg_mentioned_p (prev_dest, PATTERN (insn))
+			&& find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
+			&& ! side_effects_p (SET_SRC (PATTERN (prev))))
+		      {
+			insn = prev;
+			continue;
+		      }
+		    else
+		      break;
+		  }
+	      else
+		{
+		  INSN_DELETED_P (insn) = 1;
+		  p = (struct list *) xmalloc (sizeof (struct list));
+		  p->insn = insn;
+		  p->next = insn_list;
+		  insn_list = p;
+		}
+	    }
+	}
+    }
+}
+
 
 /* Walk the chain of insns, and determine for each whether it needs reloads
    and/or eliminations.  Build the corresponding insns_need_reload list, and
@@ -1384,10 +1457,12 @@
 	  int operands_changed = 0;
 	  rtx set = single_set (insn);
 
-	  /* Skip insns that only set an equivalence.  */
-	  if (set && GET_CODE (SET_DEST (set)) == REG
-	      && reg_renumber[REGNO (SET_DEST (set))] < 0
-	      && reg_equiv_constant[REGNO (SET_DEST (set))])
+	  /* Skip insns that only set an equivalence,
+	     and equivalencing insns which are marked to be deleted.  */
+	  if ((set && GET_CODE (SET_DEST (set)) == REG
+	       && reg_renumber[REGNO (SET_DEST (set))] < 0
+	       && reg_equiv_constant[REGNO (SET_DEST (set))])
+	      || INSN_DELETED_P (insn))
 	    {
 	      /* Must clear out the shortcuts, in case they were set last
 		 time through.  */


More information about the Gcc-patches mailing list