This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the EGCS project.


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

haifa clocking change


This is something that I experimented with back at the end of March
or so, and is needed by one of Jan's pentium scheduling changes.

First, by basing freedom on 0 rather than 1, we get to describe
when instructions can really dual issue and when they can't.

Second, MD_SCHED_REORDER is given enough information to decide if for
some reason we can't issue *any* instructions this cycle, despite having
free instructions on the ready list.  This comes up on pentium where
paired instructions issue and retire in lock-step.  Thus if a long(er)
latency instruction pairs with a short latency instruction, no new
insn can issue to the short pipe before the long insn completes.

Third, there was a redundant sort before the loop.  Removing it
kills some ugliness in the sparc backend.



r~



        * haifa-sched.c (insn_cost): FREE implies cost 0 and vice versa.
        (adjust_priority): Always call ADJUST_PRIORITY.
        (schedule_insn): Only put insns into the ready at cost 0.
        (schedule_block): Remove redundant initial sort.  Give clock_var
        and can_issue_more to MD_SCHED_REORDER.  Requeue if hazard cost
        is not 0.
        * tm.texi (MD_SCHED_REORDER): Update docs.

        * sparc.h (MD_SCHED_REORDER): Update.  Set CAN_ISSUE_MORE.
        * sparc.c (ultra_reorder_called_this_block): Delete.
        (ultrasparc_sched_init): Don't set it.
        (ultrasparc_sched_reorder): Don't check it.

Index: tm.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tm.texi,v
retrieving revision 1.78
diff -c -p -d -r1.78 tm.texi
*** tm.texi	1999/06/18 01:03:36	1.78
--- tm.texi	1999/07/21 01:10:10
*************** debug output to.  @var{verbose} is the v
*** 7656,7662 ****
  @samp{-fsched-verbose-}@var{n}.
  
  @findex MD_SCHED_REORDER
! @item MD_SCHED_REORDER (@var{file}, @var{verbose}, @var{ready}, @var{n_ready})
  A C statement which is executed by the @samp{Haifa} scheduler after it
  has scheduled the ready list to allow the machine description to reorder
  it (for example to combine two small instructions together on
--- 7656,7663 ----
  @samp{-fsched-verbose-}@var{n}.
  
  @findex MD_SCHED_REORDER
! @item MD_SCHED_REORDER (@var{file}, @var{verbose}, @var{ready}, @var{n_ready},
! 			@var{clock}, @var{can_issue_more})
  A C statement which is executed by the @samp{Haifa} scheduler after it
  has scheduled the ready list to allow the machine description to reorder
  it (for example to combine two small instructions together on
*************** provided by @samp{-fsched-verbose-}@var{
*** 7666,7672 ****
  the ready list of instructions that are ready to be scheduled.
  @var{n_ready} is the number of elements in the ready list.  The
  scheduler reads the ready list in reverse order, starting with
! @var{ready}[@var{n_ready}-1] and going to @var{ready}[0].
  
  @findex MD_SCHED_VARIABLE_ISSUE
  @item MD_SCHED_VARIABLE_ISSUE (@var{file}, @var{verbose}, @var{insn}, @var{more})
--- 7667,7676 ----
  the ready list of instructions that are ready to be scheduled.
  @var{n_ready} is the number of elements in the ready list.  The
  scheduler reads the ready list in reverse order, starting with
! @var{ready}[@var{n_ready}-1] and going to @var{ready}[0].  @var{clock}
! is the timer tick of the scheduler.  @var{can_issue_more} is an output
! parameter that is set to the number of insns that can issue this clock;
! normally this is just @code{issue_rate}.
  
  @findex MD_SCHED_VARIABLE_ISSUE
  @item MD_SCHED_VARIABLE_ISSUE (@var{file}, @var{verbose}, @var{insn}, @var{more})
Index: haifa-sched.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/haifa-sched.c,v
retrieving revision 1.89
diff -c -p -d -r1.89 haifa-sched.c
*** haifa-sched.c	1999/06/20 17:29:49	1.89
--- haifa-sched.c	1999/07/21 01:10:11
*************** insn_cost (insn, link, used)
*** 3147,3161 ****
       and LINK_COST_ZERO.  */
  
    if (LINK_COST_FREE (link))
!     cost = 1;
  #ifdef ADJUST_COST
    else if (!LINK_COST_ZERO (link))
      {
        int ncost = cost;
  
        ADJUST_COST (used, link, insn, ncost);
!       if (ncost <= 1)
! 	LINK_COST_FREE (link) = ncost = 1;
        if (cost == ncost)
  	LINK_COST_ZERO (link) = 1;
        cost = ncost;
--- 3147,3164 ----
       and LINK_COST_ZERO.  */
  
    if (LINK_COST_FREE (link))
!     cost = 0;
  #ifdef ADJUST_COST
    else if (!LINK_COST_ZERO (link))
      {
        int ncost = cost;
  
        ADJUST_COST (used, link, insn, ncost);
!       if (ncost < 1)
! 	{
! 	  LINK_COST_FREE (link) = 1;
! 	  ncost = 0;
! 	}
        if (cost == ncost)
  	LINK_COST_ZERO (link) = 1;
        cost = ncost;
*************** adjust_priority (prev)
*** 4362,4371 ****
  	    }
  	  break;
  	}
  #ifdef ADJUST_PRIORITY
!       ADJUST_PRIORITY (prev);
  #endif
-     }
  }
  
  /* Clock at which the previous instruction was issued.  */
--- 4365,4377 ----
  	    }
  	  break;
  	}
+     }
+ 
+   /* That said, a target might have it's own reasons for adjusting
+      priority after reload.  */
  #ifdef ADJUST_PRIORITY
!   ADJUST_PRIORITY (prev);
  #endif
  }
  
  /* Clock at which the previous instruction was issued.  */
*************** schedule_insn (insn, ready, n_ready, clo
*** 4439,4445 ****
  	      if (current_nr_blocks > 1 && INSN_BB (next) != target_bb)
  		fprintf (dump, "/b%d ", INSN_BLOCK (next));
  
! 	      if (effective_cost <= 1)
  		fprintf (dump, "into ready\n");
  	      else
  		fprintf (dump, "into queue with cost=%d\n", effective_cost);
--- 4445,4451 ----
  	      if (current_nr_blocks > 1 && INSN_BB (next) != target_bb)
  		fprintf (dump, "/b%d ", INSN_BLOCK (next));
  
! 	      if (effective_cost < 1)
  		fprintf (dump, "into ready\n");
  	      else
  		fprintf (dump, "into queue with cost=%d\n", effective_cost);
*************** schedule_insn (insn, ready, n_ready, clo
*** 4448,4454 ****
  	  /* Adjust the priority of NEXT and either put it on the ready
  	     list or queue it.  */
  	  adjust_priority (next);
! 	  if (effective_cost <= 1)
  	    ready[n_ready++] = next;
  	  else
  	    queue_insn (next, effective_cost);
--- 4454,4460 ----
  	  /* Adjust the priority of NEXT and either put it on the ready
  	     list or queue it.  */
  	  adjust_priority (next);
! 	  if (effective_cost < 1)
  	    ready[n_ready++] = next;
  	  else
  	    queue_insn (next, effective_cost);
*************** schedule_block (bb, rgn_n_insns)
*** 6675,6681 ****
    /* Local variables.  */
    rtx insn, last;
    rtx *ready;
-   int i;
    int n_ready = 0;
    int can_issue_more;
  
--- 6681,6686 ----
*************** schedule_block (bb, rgn_n_insns)
*** 6857,6881 ****
    /* no insns scheduled in this block yet */
    last_scheduled_insn = 0;
  
-   /* Sort the ready list */
-   SCHED_SORT (ready, n_ready);
- #ifdef MD_SCHED_REORDER
-   MD_SCHED_REORDER (dump, sched_verbose, ready, n_ready);
- #endif
- 
-   if (sched_verbose >= 2)
-     {
-       fprintf (dump, ";;\t\tReady list initially:             ");
-       debug_ready_list (ready, n_ready);
-     }
- 
    /* Q_SIZE is the total number of insns in the queue.  */
    q_ptr = 0;
    q_size = 0;
-   clock_var = 0;
    last_clock_var = 0;
    bzero ((char *) insn_queue, sizeof (insn_queue));
  
    /* We start inserting insns after PREV_HEAD.  */
    last = prev_head;
  
--- 6862,6876 ----
    /* no insns scheduled in this block yet */
    last_scheduled_insn = 0;
  
    /* Q_SIZE is the total number of insns in the queue.  */
    q_ptr = 0;
    q_size = 0;
    last_clock_var = 0;
    bzero ((char *) insn_queue, sizeof (insn_queue));
  
+   /* Start just before the beginning of time.  */
+   clock_var = -1;
+ 
    /* We start inserting insns after PREV_HEAD.  */
    last = prev_head;
  
*************** schedule_block (bb, rgn_n_insns)
*** 6907,6916 ****
  	  debug_ready_list (ready, n_ready);
  	}
  
!       /* Sort the ready list.  */
        SCHED_SORT (ready, n_ready);
  #ifdef MD_SCHED_REORDER
!       MD_SCHED_REORDER (dump, sched_verbose, ready, n_ready);
  #endif
  
        if (sched_verbose)
--- 6902,6917 ----
  	  debug_ready_list (ready, n_ready);
  	}
  
!       /* Sort the ready list based on priority.  */
        SCHED_SORT (ready, n_ready);
+ 
+       /* Allow the target to reorder the list, typically for 
+ 	 better instruction bundling.  */
  #ifdef MD_SCHED_REORDER
!       MD_SCHED_REORDER (dump, sched_verbose, ready, n_ready, clock_var,
! 			can_issue_more);
! #else
!       can_issue_more = issue_rate;
  #endif
  
        if (sched_verbose)
*************** schedule_block (bb, rgn_n_insns)
*** 6919,7028 ****
  	  debug_ready_list (ready, n_ready);
  	}
  
!       /* Issue insns from ready list.
!          It is important to count down from n_ready, because n_ready may change
!          as insns are issued.  */
!       can_issue_more = issue_rate;
!       for (i = n_ready - 1; i >= 0 && can_issue_more; i--)
  	{
! 	  rtx insn = ready[i];
  	  int cost = actual_hazard (insn_unit (insn), insn, clock_var, 0);
  
! 	  if (cost > 1)
  	    {
  	      queue_insn (insn, cost);
! 	      ready[i] = ready[--n_ready];	/* remove insn from ready list */
  	    }
- 	  else if (cost == 0)
- 	    {
- 	      /* an interblock motion? */
- 	      if (INSN_BB (insn) != target_bb)
- 		{
- 		  rtx temp;
  
! 		  if (IS_SPECULATIVE_INSN (insn))
! 		    {
  
! 		      if (!check_live (insn, INSN_BB (insn)))
! 			{
! 			  /* speculative motion, live check failed, remove
! 			     insn from ready list */
! 			  ready[i] = ready[--n_ready];
! 			  continue;
! 			}
! 		      update_live (insn, INSN_BB (insn));
  
! 		      /* for speculative load, mark insns fed by it.  */
! 		      if (IS_LOAD_INSN (insn) || FED_BY_SPEC_LOAD (insn))
! 			set_spec_fed (insn);
  
! 		      nr_spec++;
! 		    }
! 		  nr_inter++;
  
! 		  temp = insn;
! 		  while (SCHED_GROUP_P (temp))
! 		    temp = PREV_INSN (temp);
  
! 		  /* Update source block boundaries.   */
! 		  b1 = INSN_BLOCK (temp);
! 		  if (temp == BLOCK_HEAD (b1)
! 		      && insn == BLOCK_END (b1))
! 		    {
! 		      /* We moved all the insns in the basic block.
! 			 Emit a note after the last insn and update the
! 			 begin/end boundaries to point to the note.  */
! 		      emit_note_after (NOTE_INSN_DELETED, insn);
! 		      BLOCK_END (b1) = NEXT_INSN (insn);
! 		      BLOCK_HEAD (b1) = NEXT_INSN (insn);
! 		    }
! 		  else if (insn == BLOCK_END (b1))
! 		    {
! 		      /* We took insns from the end of the basic block,
! 			 so update the end of block boundary so that it
! 			 points to the first insn we did not move.  */
! 		      BLOCK_END (b1) = PREV_INSN (temp);
! 		    }
! 		  else if (temp == BLOCK_HEAD (b1))
! 		    {
! 		      /* We took insns from the start of the basic block,
! 			 so update the start of block boundary so that
! 			 it points to the first insn we did not move.  */
! 		      BLOCK_HEAD (b1) = NEXT_INSN (insn);
! 		    }
  		}
! 	      else
  		{
! 		  /* in block motion */
! 		  sched_target_n_insns++;
  		}
  
! 	      last_scheduled_insn = insn;
! 	      last = move_insn (insn, last);
! 	      sched_n_insns++;
  
  #ifdef MD_SCHED_VARIABLE_ISSUE
! 	      MD_SCHED_VARIABLE_ISSUE (dump, sched_verbose, insn, can_issue_more);
  #else
! 	      can_issue_more--;
  #endif
- 
- 	      n_ready = schedule_insn (insn, ready, n_ready, clock_var);
  
! 	      /* remove insn from ready list */
! 	      ready[i] = ready[--n_ready];
  
! 	      /* close this block after scheduling its jump */
! 	      if (GET_CODE (last_scheduled_insn) == JUMP_INSN)
! 		break;
! 	    }
  	}
  
!       /* debug info */
        if (sched_verbose)
! 	{
! 	  visualize_scheduled_insns (b, clock_var);
! 	}
      }
  
    /* debug info */
--- 6920,7015 ----
  	  debug_ready_list (ready, n_ready);
  	}
  
!       /* Issue insns from ready list.  */
!       while (n_ready != 0 && can_issue_more)
  	{
! 	  /* Select and remove the insn from the ready list.  */
! 	  rtx insn = ready[--n_ready];
  	  int cost = actual_hazard (insn_unit (insn), insn, clock_var, 0);
  
! 	  if (cost >= 1)
  	    {
  	      queue_insn (insn, cost);
! 	      continue;
  	    }
  
! 	  /* An interblock motion?  */
! 	  if (INSN_BB (insn) != target_bb)
! 	    {
! 	      rtx temp;
  
! 	      if (IS_SPECULATIVE_INSN (insn))
! 		{
! 		  if (!check_live (insn, INSN_BB (insn)))
! 		    continue;
! 		  update_live (insn, INSN_BB (insn));
  
! 		  /* For speculative load, mark insns fed by it.  */
! 		  if (IS_LOAD_INSN (insn) || FED_BY_SPEC_LOAD (insn))
! 		    set_spec_fed (insn);
  
! 		  nr_spec++;
! 		}
! 	      nr_inter++;
  
! 	      temp = insn;
! 	      while (SCHED_GROUP_P (temp))
! 		temp = PREV_INSN (temp);
  
! 	      /* Update source block boundaries.   */
! 	      b1 = INSN_BLOCK (temp);
! 	      if (temp == BLOCK_HEAD (b1)
! 		  && insn == BLOCK_END (b1))
! 		{
! 		  /* We moved all the insns in the basic block.
! 		     Emit a note after the last insn and update the
! 		     begin/end boundaries to point to the note.  */
! 		  emit_note_after (NOTE_INSN_DELETED, insn);
! 		  BLOCK_END (b1) = NEXT_INSN (insn);
! 		  BLOCK_HEAD (b1) = NEXT_INSN (insn);
  		}
! 	      else if (insn == BLOCK_END (b1))
  		{
! 		  /* We took insns from the end of the basic block,
! 		     so update the end of block boundary so that it
! 		     points to the first insn we did not move.  */
! 		  BLOCK_END (b1) = PREV_INSN (temp);
! 		}
! 	      else if (temp == BLOCK_HEAD (b1))
! 		{
! 		  /* We took insns from the start of the basic block,
! 		     so update the start of block boundary so that
! 		     it points to the first insn we did not move.  */
! 		  BLOCK_HEAD (b1) = NEXT_INSN (insn);
  		}
+ 	    }
+ 	  else
+ 	    {
+ 	      /* In block motion.  */
+ 	      sched_target_n_insns++;
+ 	    }
  
! 	  last_scheduled_insn = insn;
! 	  last = move_insn (insn, last);
! 	  sched_n_insns++;
  
  #ifdef MD_SCHED_VARIABLE_ISSUE
! 	  MD_SCHED_VARIABLE_ISSUE (dump, sched_verbose, insn,
! 				   can_issue_more);
  #else
! 	  can_issue_more--;
  #endif
  
! 	  n_ready = schedule_insn (insn, ready, n_ready, clock_var);
  
! 	  /* Close this block after scheduling its jump.  */
! 	  if (GET_CODE (last_scheduled_insn) == JUMP_INSN)
! 	    break;
  	}
  
!       /* Debug info.  */
        if (sched_verbose)
! 	visualize_scheduled_insns (b, clock_var);
      }
  
    /* debug info */
Index: config/sparc/sparc.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.c,v
retrieving revision 1.70
diff -c -p -d -r1.70 sparc.c
*** sparc.c	1999/06/21 17:47:40	1.70
--- sparc.c	1999/07/21 01:10:11
*************** ultra_flush_pipeline ()
*** 6879,6886 ****
    ultra_pipe.free_slot_mask = 0xf;
  }
  
- static int ultra_reorder_called_this_block;
- 
  /* Init our data structures for this current block.  */
  void
  ultrasparc_sched_init (dump, sched_verbose)
--- 6879,6884 ----
*************** ultrasparc_sched_init (dump, sched_verbo
*** 6890,6896 ****
    bzero ((char *) ultra_pipe_hist, sizeof ultra_pipe_hist);
    ultra_cur_hist = 0;
    ultra_cycles_elapsed = 0;
-   ultra_reorder_called_this_block = 0;
    ultra_pipe.free_slot_mask = 0xf;
  }
  
--- 6888,6893 ----
*************** ultrasparc_sched_reorder (dump, sched_ve
*** 6979,6992 ****
  {
    struct ultrasparc_pipeline_state *up = &ultra_pipe;
    int i, this_insn;
- 
-   /* We get called once unnecessarily per block of insns
-      scheduled.  */
-   if (ultra_reorder_called_this_block == 0)
-     {
-       ultra_reorder_called_this_block = 1;
-       return;
-     }
  
    if (sched_verbose)
      {
--- 6976,6981 ----
Index: config/sparc/sparc.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.h,v
retrieving revision 1.67
diff -c -p -d -r1.67 sparc.h
*** sparc.h	1999/06/21 17:47:41	1.67
--- sparc.h	1999/07/21 01:10:11
*************** extern int ultrasparc_variable_issue ();
*** 2702,2722 ****
    if (sparc_cpu == PROCESSOR_ULTRASPARC)				\
      ultrasparc_sched_init (DUMP, SCHED_VERBOSE)
  
! #define MD_SCHED_REORDER(DUMP, SCHED_VERBOSE, READY, N_READY)		\
    if (sparc_cpu == PROCESSOR_ULTRASPARC)				\
!     ultrasparc_sched_reorder (DUMP, SCHED_VERBOSE, READY, N_READY)
  
  #define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
!   if (sparc_cpu == PROCESSOR_ULTRASPARC)			\
!     (CAN_ISSUE_MORE) = ultrasparc_variable_issue (INSN);	\
!   else								\
!     (CAN_ISSUE_MORE)--
  
  /* Conditional branches with empty delay slots have a length of two.  */
  #define ADJUST_INSN_LENGTH(INSN, LENGTH)				\
    if (GET_CODE (INSN) == CALL_INSN					\
        || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn)))	\
!     LENGTH += 1; else
  
  /* Control the assembler format that we output.  */
  
--- 2702,2729 ----
    if (sparc_cpu == PROCESSOR_ULTRASPARC)				\
      ultrasparc_sched_init (DUMP, SCHED_VERBOSE)
  
! #define MD_SCHED_REORDER(DUMP, SCHED_VERBOSE, READY, N_READY, CLOCK, CIM) \
! do {									\
    if (sparc_cpu == PROCESSOR_ULTRASPARC)				\
!     ultrasparc_sched_reorder (DUMP, SCHED_VERBOSE, READY, N_READY);	\
!   CIM = issue_rate;							\
! } while (0)
  
  #define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
! do {									\
!   if (sparc_cpu == PROCESSOR_ULTRASPARC)				\
!     (CAN_ISSUE_MORE) = ultrasparc_variable_issue (INSN);		\
!   else									\
!     (CAN_ISSUE_MORE)--;							\
! } while (0)
  
  /* Conditional branches with empty delay slots have a length of two.  */
  #define ADJUST_INSN_LENGTH(INSN, LENGTH)				\
+ do {									\
    if (GET_CODE (INSN) == CALL_INSN					\
        || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn)))	\
!     LENGTH += 1;							\
! } while (0)
  
  /* Control the assembler format that we output.  */
  

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