Patchwork Scheduler cleanups, 5/5

login
register
mail settings
Submitter Bernd Schmidt
Date March 24, 2011, 1:19 p.m.
Message ID <4D8B44E9.7070908@codesourcery.com>
Download mbox | patch
Permalink /patch/88197/
State New
Headers show

Comments

Bernd Schmidt - March 24, 2011, 1:19 p.m.
We can currently select an insn to be scheduled, only to find out that
it's not actually valid at the current time, either due to state
conflicts or being an asm with something else already scheduled in the
same cycle. Not only is this pointless, it causes problem with the
sched_reorder logic in the TI C6X port (which will be submitted later).
The solution is to prune the ready list earlier. More code is moved out
of the schedule_block main loop, which is IMO always a good thing.

Bootstrapped and tested (a slightly earlier version with an unused
variable) on i686-linux; I also verified that there are no changes in
code generation on any of my testcases.


Bernd
* haifa-sched.c (prune_ready_list): New function, broken out of
	schedule_block.
	(schedule_block): Use it.
Jeff Law - March 25, 2011, 6:35 p.m.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/24/11 07:19, Bernd Schmidt wrote:
> We can currently select an insn to be scheduled, only to find out that
> it's not actually valid at the current time, either due to state
> conflicts or being an asm with something else already scheduled in the
> same cycle. Not only is this pointless, it causes problem with the
> sched_reorder logic in the TI C6X port (which will be submitted later).
> The solution is to prune the ready list earlier. More code is moved out
> of the schedule_block main loop, which is IMO always a good thing.
> 
> Bootstrapped and tested (a slightly earlier version with an unused
> variable) on i686-linux; I also verified that there are no changes in
> code generation on any of my testcases.
OK.
Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNjOBTAAoJEBRtltQi2kC7TKwH/i5NH93tC1y9LVzCoc0Gk9oj
FvuxaUSeoGrSvliGCw5Zdw1CJFtPBWOVWGHsVpcYzVIRSGy8i4v9N9COteWVNfZ0
pVKSrr+b4FcVBDzcEoi6e/BN/SlNo7C9grdmmDMeePguNBsf00XVptdwvSfC8Cil
osqnlVvoQX1Fi2D3updBHqCcTmCe6Aug59tXaZ9k8dOKv7+8NfVeKSygnbjtr3Yk
sqo8Iuog95LYo/LmDz9hqpRaMkkH5iBXgaoQEvSRYb66Kpa2TIhmSokj1xx6Ndq1
rYyEgJPHPLHxQFqIGDZpSKaHh0gPmvZqIWy0lZdsxZS4ZqQb4KYW+cw46OtSN4w=
=A++W
-----END PGP SIGNATURE-----

Patch

Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c.orig
+++ gcc/haifa-sched.c
@@ -2614,8 +2614,8 @@  max_issue (struct ready_list *ready, int
 	    {
 	      if (state_dead_lock_p (state)
 		  || insn_finishes_cycle_p (insn))
- 		/* We won't issue any more instructions in the next
- 		   choice_state.  */
+		/* We won't issue any more instructions in the next
+		   choice_state.  */
 		top->rest = 0;
 	      else
 		top->rest--;
@@ -2863,6 +2863,52 @@  commit_schedule (rtx prev_head, rtx tail
   VEC_truncate (rtx, scheduled_insns, 0);
 }
 
+/* Examine all insns on the ready list and queue those which can't be
+   issued in this cycle.  TEMP_STATE is temporary scheduler state we
+   can use as scratch space.  If FIRST_CYCLE_INSN_P is true, no insns
+   have been issued for the current cycle, which means it is valid to
+   issue an asm statement.  */
+
+static void
+prune_ready_list (state_t temp_state, bool first_cycle_insn_p)
+{
+  int i;
+
+ restart:
+  for (i = 0; i < ready.n_ready; i++)
+    {
+      rtx insn = ready_element (&ready, i);
+      int cost = 0;
+      const char *reason = "resource conflict";
+
+      if (recog_memoized (insn) < 0)
+	{
+	  if (!first_cycle_insn_p
+	      && (GET_CODE (PATTERN (insn)) == ASM_INPUT
+		  || asm_noperands (PATTERN (insn)) >= 0))
+	    cost = 1;
+	  reason = "asm";
+	}
+      else if (flag_sched_pressure)
+	cost = 0;
+      else
+	{
+	  memcpy (temp_state, curr_state, dfa_state_size);
+	  cost = state_transition (temp_state, insn);
+	  if (cost < 0)
+	    cost = 0;
+	  else if (cost == 0)
+	    cost = 1;
+	}
+      if (cost >= 1)
+	{
+	  ready_remove (&ready, i);
+	  queue_insn (insn, cost, reason);
+	  goto restart;
+	}
+    }
+}
+
 /* Use forward list scheduling to rearrange insns of block pointed to by
    TARGET_BB, possibly bringing insns from subsequent blocks in the same
    region.  */
@@ -3014,6 +3060,10 @@  schedule_block (basic_block *target_bb)
 	}
       while (advance > 0);
 
+      prune_ready_list (temp_state, true);
+      if (ready.n_ready == 0)
+        continue;
+
       if (sort_p)
 	{
 	  /* Sort the ready list based on priority.  */
@@ -3144,44 +3194,6 @@  schedule_block (basic_block *target_bb)
 	    }
 
 	  sort_p = TRUE;
-	  memcpy (temp_state, curr_state, dfa_state_size);
-	  if (recog_memoized (insn) < 0)
-	    {
-	      asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
-		       || asm_noperands (PATTERN (insn)) >= 0);
-	      if (!first_cycle_insn_p && asm_p)
-		/* This is asm insn which is tried to be issued on the
-		   cycle not first.  Issue it on the next cycle.  */
-		cost = 1;
-	      else
-		/* A USE insn, or something else we don't need to
-		   understand.  We can't pass these directly to
-		   state_transition because it will trigger a
-		   fatal error for unrecognizable insns.  */
-		cost = 0;
-	    }
-	  else if (sched_pressure_p)
-	    cost = 0;
-	  else
-	    {
-	      cost = state_transition (temp_state, insn);
-	      if (cost < 0)
-		cost = 0;
-	      else if (cost == 0)
-		cost = 1;
-	    }
-
-	  if (cost >= 1)
-	    {
-	      queue_insn (insn, cost, "resource conflict");
- 	      if (SCHED_GROUP_P (insn))
- 		{
- 		  advance = cost;
- 		  break;
- 		}
-
-	      continue;
-	    }
 
 	  if (current_sched_info->can_schedule_ready_p
 	      && ! (*current_sched_info->can_schedule_ready_p) (insn))
@@ -3202,14 +3214,20 @@  schedule_block (basic_block *target_bb)
 
 	  /* Update counters, etc in the scheduler's front end.  */
 	  (*current_sched_info->begin_schedule_ready) (insn);
- 	  VEC_safe_push (rtx, heap, scheduled_insns, insn);
+	  VEC_safe_push (rtx, heap, scheduled_insns, insn);
 	  last_scheduled_insn = insn;
 
-	  if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
-            {
-              cycle_issued_insns++;
-              memcpy (curr_state, temp_state, dfa_state_size);
-            }
+	  if (recog_memoized (insn) >= 0)
+	    {
+	      cost = state_transition (curr_state, insn);
+	      if (!flag_sched_pressure)
+		gcc_assert (cost < 0);
+	      cycle_issued_insns++;
+	      asm_p = false;
+	    }
+	  else
+	    asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
+		     || asm_noperands (PATTERN (insn)) >= 0);
 
 	  if (targetm.sched.variable_issue)
 	    can_issue_more =
@@ -3230,6 +3248,9 @@  schedule_block (basic_block *target_bb)
 
 	  first_cycle_insn_p = false;
 
+	  if (ready.n_ready > 0)
+            prune_ready_list (temp_state, false);
+
 	  /* Sort the ready list based on priority.  This must be
 	     redone here, as schedule_insn may have readied additional
 	     insns that will not be sorted correctly.  */
@@ -3241,7 +3262,7 @@  schedule_block (basic_block *target_bb)
 	  if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))
 	      && (*current_sched_info->schedule_more_p) ())
 	    {
- 	      while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
+	      while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
 		{
 		  insn = ready_remove_first (&ready);
 		  gcc_assert (DEBUG_INSN_P (insn));