Patchwork Scheduler cleanups, 1/N

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

Comments

Bernd Schmidt - March 24, 2011, 1:07 p.m.
I have a number of patches that will be necessary for a new target. Some
of these can be applied now as cleanups, so I'm submit them now.

This changes the schedule_block main loop not to move instructions while
computing the schedule. Instead, we collect them in a VEC and modify the
RTL afterwards. The real motivation for this is to add support for
backtracking later.

Bootstrapped and tested on i686-linux. No changes in generated code on
any of my testcases.


Bernd
* sched-ebb.c (begin_schedule_ready): Remove second argument.
	Split most of the code into...
	(begin_move_insn): ... here.  New function.
	(ebb_sched_info): Add a pointer to it.
	* haifa-sched.c (scheduled_insns): New static variable.
	(sched_extend_ready_list): Allocate it.
	(schedule_block): Use it to record the order of scheduled insns.
	Perform RTL changes to move insns only after all scheduling
	decisions have been made.
	* modulo-sched.c (sms_sched_haifa_sched_info): Add NULL entry for the
	begin_move_insn field.
	* sel-sched-ir.c (sched_sel_haifa_sched_info): Likewise.
	* sched-int.h (struct haifa_sched_info): Remove second argument
	from begin_schedule_ready hook.  Add new member begin_move_insn.
	* sched-rgn.c (begin_schedule_ready): Remove second argument.
	(rgn_const_sched_info): Add NULL entry for the begin_move_insn field.
Jeff Law - March 31, 2011, 3:14 p.m.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/24/11 07:07, Bernd Schmidt wrote:
> I have a number of patches that will be necessary for a new target. Some
> of these can be applied now as cleanups, so I'm submit them now.
> 
> This changes the schedule_block main loop not to move instructions while
> computing the schedule. Instead, we collect them in a VEC and modify the
> RTL afterwards. The real motivation for this is to add support for
> backtracking later.
> 
> Bootstrapped and tested on i686-linux. No changes in generated code 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/

iQEcBAEBAgAGBQJNlJpQAAoJEBRtltQi2kC7cfsIAK9H8t8iOCREJDGx9F0z69Vt
EfX3Ip7I3IRWsqGShv9Y6MVmCs+JV8u4BuzqGyqBJ7JEda4gDDgaOC/uWJX8IqjE
5p5XhHrPGxp0EzrH/RbxmwolTw0O0TZoCGHFQtJS6TwwnXFfAWEGKSFigHmOkUlR
DhoRQynKC7Mc4itV9S09h15TNRj8X9QVhj9gRGCKgXjOWTFBV/rpe/geHPsqZ9G/
cZg/9BK9jBEsesMxyvyj6dEE34CrTbIdrvNO4JqZ+ihENB5ID26zXb0W9yczYvB4
DVXElaqBVaEcC/rJERJbC6D+x3iDgKqNRLKxriMWvOrKnmRvk4JF/iGwgqEHEtA=
=TIu+
-----END PGP SIGNATURE-----
H.J. Lu - April 2, 2011, 12:55 a.m.
On Thu, Mar 24, 2011 at 6:07 AM, Bernd Schmidt <bernds@codesourcery.com> wrote:
> I have a number of patches that will be necessary for a new target. Some
> of these can be applied now as cleanups, so I'm submit them now.
>
> This changes the schedule_block main loop not to move instructions while
> computing the schedule. Instead, we collect them in a VEC and modify the
> RTL afterwards. The real motivation for this is to add support for
> backtracking later.
>
> Bootstrapped and tested on i686-linux. No changes in generated code on
> any of my testcases.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48403

Patch

Index: gcc/sched-ebb.c
===================================================================
--- gcc/sched-ebb.c.orig
+++ gcc/sched-ebb.c
@@ -59,7 +59,7 @@  static basic_block last_bb;
 
 /* Implementations of the sched_info functions for region scheduling.  */
 static void init_ready_list (void);
-static void begin_schedule_ready (rtx, rtx);
+static void begin_schedule_ready (rtx);
 static int schedule_more_p (void);
 static const char *ebb_print_insn (const_rtx, int);
 static int rank (rtx, rtx);
@@ -125,10 +125,15 @@  init_ready_list (void)
 
 /* INSN is being scheduled after LAST.  Update counters.  */
 static void
-begin_schedule_ready (rtx insn, rtx last)
+begin_schedule_ready (rtx insn ATTRIBUTE_UNUSED)
 {
   sched_rgn_n_insns++;
+}
 
+/* INSN is being moved to its place in the schedule, after LAST.  */
+static void
+begin_move_insn (rtx insn, rtx last)
+{
   if (BLOCK_FOR_INSN (insn) == last_bb
       /* INSN is a jump in the last block, ...  */
       && control_flow_insn_p (insn)
@@ -288,6 +293,7 @@  static struct haifa_sched_info ebb_sched
 
   ebb_add_remove_insn,
   begin_schedule_ready,
+  begin_move_insn,
   advance_target_bb,
   SCHED_EBB
   /* We can create new blocks in begin_schedule_ready ().  */
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c.orig
+++ gcc/haifa-sched.c
@@ -302,6 +302,10 @@  static struct ready_list *readyp = &read
 /* Scheduling clock.  */
 static int clock_var;
 
+/* This records the actual schedule.  It is built up during the main phase
+   of schedule_block, and afterwards used to reorder the insns in the RTL.  */
+static VEC(rtx, heap) *scheduled_insns;
+
 static int may_trap_exp (const_rtx, int);
 
 /* Nonzero iff the address is comprised from at most 1 register.  */
@@ -2813,6 +2817,51 @@  choose_ready (struct ready_list *ready, 
     }
 }
 
+/* This function is called when we have successfully scheduled a
+   block.  It uses the schedule stored in the scheduled_insns vector
+   to rearrange the RTL.  PREV_HEAD is used as the anchor to which we
+   append the scheduled insns; TAIL is the insn after the scheduled
+   block.  TARGET_BB is the argument passed to schedule_block.  */
+
+static void
+commit_schedule (rtx prev_head, rtx tail, basic_block *target_bb)
+{
+  int i;
+
+  last_scheduled_insn = prev_head;
+  for (i = 0; i < (int)VEC_length (rtx, scheduled_insns); i++)
+    {
+      rtx insn = VEC_index (rtx, scheduled_insns, i);
+
+      if (control_flow_insn_p (last_scheduled_insn)
+	  || current_sched_info->advance_target_bb (*target_bb, insn))
+	{
+	  *target_bb = current_sched_info->advance_target_bb (*target_bb, 0);
+
+	  if (sched_verbose)
+	    {
+	      rtx x;
+
+	      x = next_real_insn (last_scheduled_insn);
+	      gcc_assert (x);
+	      dump_new_block_header (1, *target_bb, x, tail);
+	    }
+
+	  last_scheduled_insn = bb_note (*target_bb);
+	}
+
+      if (current_sched_info->begin_move_insn)
+	(*current_sched_info->begin_move_insn) (insn, last_scheduled_insn);
+      move_insn (insn, last_scheduled_insn,
+		 current_sched_info->next_tail);
+      if (!DEBUG_INSN_P (insn))
+	reemit_notes (insn);
+      last_scheduled_insn = insn;
+    }
+
+  VEC_truncate (rtx, scheduled_insns, 0);
+}
+
 /* Use forward list scheduling to rearrange insns of block pointed to by
    TARGET_BB, possibly bringing insns from subsequent blocks in the same
    region.  */
@@ -2934,6 +2983,7 @@  schedule_block (basic_block *target_bb)
 
   advance = 0;
 
+  gcc_assert (VEC_length (rtx, scheduled_insns) == 0);
   sort_p = TRUE;
   /* Loop until all the insns in BB are scheduled.  */
   while ((*current_sched_info->schedule_more_p) ())
@@ -2979,31 +3029,12 @@  schedule_block (basic_block *target_bb)
 	 them out right away.  */
       if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
 	{
-	  if (control_flow_insn_p (last_scheduled_insn))
-	    {
-	      *target_bb = current_sched_info->advance_target_bb
-		(*target_bb, 0);
-
-	      if (sched_verbose)
-		{
-		  rtx x;
-
-		  x = next_real_insn (last_scheduled_insn);
-		  gcc_assert (x);
-		  dump_new_block_header (1, *target_bb, x, tail);
-		}
-
-	      last_scheduled_insn = bb_note (*target_bb);
-	    }
-
 	  while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
 	    {
 	      rtx insn = ready_remove_first (&ready);
 	      gcc_assert (DEBUG_INSN_P (insn));
-	      (*current_sched_info->begin_schedule_ready) (insn,
-							   last_scheduled_insn);
-	      move_insn (insn, last_scheduled_insn,
-			 current_sched_info->next_tail);
+	      (*current_sched_info->begin_schedule_ready) (insn);
+	      VEC_safe_push (rtx, heap, scheduled_insns, insn);
 	      last_scheduled_insn = insn;
 	      advance = schedule_insn (insn);
 	      gcc_assert (advance == 0);
@@ -3165,39 +3196,12 @@  schedule_block (basic_block *target_bb)
           if (TODO_SPEC (insn) & SPECULATIVE)
             generate_recovery_code (insn);
 
-	  if (control_flow_insn_p (last_scheduled_insn)
-	      /* This is used to switch basic blocks by request
-		 from scheduler front-end (actually, sched-ebb.c only).
-		 This is used to process blocks with single fallthru
-		 edge.  If succeeding block has jump, it [jump] will try
-		 move at the end of current bb, thus corrupting CFG.  */
-	      || current_sched_info->advance_target_bb (*target_bb, insn))
-	    {
-	      *target_bb = current_sched_info->advance_target_bb
-		(*target_bb, 0);
-
-	      if (sched_verbose)
-		{
-		  rtx x;
-
-		  x = next_real_insn (last_scheduled_insn);
-		  gcc_assert (x);
-		  dump_new_block_header (1, *target_bb, x, tail);
-		}
-
-	      last_scheduled_insn = bb_note (*target_bb);
-	    }
-
-	  /* Update counters, etc in the scheduler's front end.  */
-	  (*current_sched_info->begin_schedule_ready) (insn,
-						       last_scheduled_insn);
-
-	  move_insn (insn, last_scheduled_insn, current_sched_info->next_tail);
-
 	  if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
 	    targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
 
-	  reemit_notes (insn);
+	  /* Update counters, etc in the scheduler's front end.  */
+	  (*current_sched_info->begin_schedule_ready) (insn);
+ 	  VEC_safe_push (rtx, heap, scheduled_insns, insn);
 	  last_scheduled_insn = insn;
 
 	  if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
@@ -3236,31 +3240,12 @@  schedule_block (basic_block *target_bb)
 	  if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))
 	      && (*current_sched_info->schedule_more_p) ())
 	    {
-	      if (control_flow_insn_p (last_scheduled_insn))
-		{
-		  *target_bb = current_sched_info->advance_target_bb
-		    (*target_bb, 0);
-
-		  if (sched_verbose)
-		    {
-		      rtx x;
-
-		      x = next_real_insn (last_scheduled_insn);
-		      gcc_assert (x);
-		      dump_new_block_header (1, *target_bb, x, tail);
-		    }
-
-		  last_scheduled_insn = bb_note (*target_bb);
-		}
-
  	      while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
 		{
 		  insn = ready_remove_first (&ready);
 		  gcc_assert (DEBUG_INSN_P (insn));
-		  (*current_sched_info->begin_schedule_ready)
-		    (insn, last_scheduled_insn);
-		  move_insn (insn, last_scheduled_insn,
-			     current_sched_info->next_tail);
+		  (*current_sched_info->begin_schedule_ready) (insn);
+		  VEC_safe_push (rtx, heap, scheduled_insns, insn);
 		  advance = schedule_insn (insn);
 		  last_scheduled_insn = insn;
 		  gcc_assert (advance == 0);
@@ -3321,6 +3306,7 @@  schedule_block (basic_block *target_bb)
 	  }
     }
 
+  commit_schedule (prev_head, tail, target_bb);
   if (sched_verbose)
     fprintf (sched_dump, ";;   total time = %d\n", clock_var);
 
@@ -4001,6 +3987,7 @@  sched_extend_ready_list (int new_sched_r
     {
       i = 0;
       sched_ready_n_insns = 0;
+      scheduled_insns = VEC_alloc (rtx, heap, new_sched_ready_n_insns);
     }
   else
     i = sched_ready_n_insns + 1;
Index: gcc/modulo-sched.c
===================================================================
--- gcc/modulo-sched.c.orig
+++ gcc/modulo-sched.c
@@ -275,7 +275,7 @@  static struct haifa_sched_info sms_sched
   NULL, NULL,
   0, 0,
 
-  NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL,
   0
 };
 
Index: gcc/sel-sched-ir.c
===================================================================
--- gcc/sel-sched-ir.c.orig
+++ gcc/sel-sched-ir.c
@@ -5638,6 +5638,7 @@  static struct haifa_sched_info sched_sel
 
   NULL, /* add_remove_insn */
   NULL, /* begin_schedule_ready */
+  NULL, /* begin_move_insn */
   NULL, /* advance_target_bb */
   SEL_SCHED | NEW_BBS
 };
Index: gcc/sched-int.h
===================================================================
--- gcc/sched-int.h.orig
+++ gcc/sched-int.h
@@ -605,10 +605,15 @@  struct haifa_sched_info
      parameter == 0) or removed (second parameter == 1).  */
   void (*add_remove_insn) (rtx, int);
 
-  /* Called to notify frontend that instruction is being scheduled.
-     The first parameter - instruction to scheduled, the second parameter -
-     last scheduled instruction.  */
-  void (*begin_schedule_ready) (rtx, rtx);
+  /* Called to notify the frontend that instruction INSN is being
+     scheduled.  */
+  void (*begin_schedule_ready) (rtx insn);
+
+  /* Called to notify the frontend that an instruction INSN is about to be
+     moved to its correct place in the final schedule.  This is done for all
+     insns in order of the schedule.  LAST indicates the last scheduled
+     instruction.  */
+  void (*begin_move_insn) (rtx insn, rtx last);
 
   /* If the second parameter is not NULL, return nonnull value, if the
      basic block should be advanced.
Index: gcc/sched-rgn.c
===================================================================
--- gcc/sched-rgn.c.orig
+++ gcc/sched-rgn.c
@@ -2068,7 +2068,7 @@  static int sched_n_insns;
 /* Implementations of the sched_info functions for region scheduling.  */
 static void init_ready_list (void);
 static int can_schedule_ready_p (rtx);
-static void begin_schedule_ready (rtx, rtx);
+static void begin_schedule_ready (rtx);
 static ds_t new_ready (rtx, ds_t);
 static int schedule_more_p (void);
 static const char *rgn_print_insn (const_rtx, int);
@@ -2163,7 +2163,7 @@  can_schedule_ready_p (rtx insn)
    can_schedule_ready_p () differs from the one passed to
    begin_schedule_ready ().  */
 static void
-begin_schedule_ready (rtx insn, rtx last ATTRIBUTE_UNUSED)
+begin_schedule_ready (rtx insn)
 {
   /* An interblock motion?  */
   if (INSN_BB (insn) != target_bb)
@@ -2380,6 +2380,7 @@  static const struct haifa_sched_info rgn
 
   rgn_add_remove_insn,
   begin_schedule_ready,
+  NULL,
   advance_target_bb,
   SCHED_RGN
 };