⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sched.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (unit >= 0)    {      int instance = unit;#if MAX_MULTIPLICITY > 1      /* Find the first free instance of the function unit and use that	 one.  We assume that one is free.  */      for (i = function_units[unit].multiplicity - 1; i > 0; i--)	{	  if (! actual_hazard_this_instance (unit, instance, insn, clock, 0))	    break;	  instance += FUNCTION_UNITS_SIZE;	}#endif      unit_last_insn[instance] = insn;      unit_tick[instance] = (clock + function_units[unit].max_blockage);    }  else    for (i = 0, unit = ~unit; unit; i++, unit >>= 1)      if ((unit & 1) != 0)	schedule_unit (i, insn, clock);}/* Return the actual hazard cost of executing INSN on the units encoded by   UNIT at time CLOCK if the previous actual hazard cost was COST.  */__inline static intactual_hazard (unit, insn, clock, cost)     int unit, clock, cost;     rtx insn;{  int i;  if (unit >= 0)    {      /* Find the instance of the function unit with the minimum hazard.  */      int instance = unit;      int best_cost = actual_hazard_this_instance (unit, instance, insn,						   clock, cost);      int this_cost;#if MAX_MULTIPLICITY > 1      if (best_cost > cost)	{	  for (i = function_units[unit].multiplicity - 1; i > 0; i--)	    {	      instance += FUNCTION_UNITS_SIZE;	      this_cost = actual_hazard_this_instance (unit, instance, insn,						       clock, cost);	      if (this_cost < best_cost)		{		  best_cost = this_cost;		  if (this_cost <= cost)		    break;		}	    }	}#endif      cost = MAX (cost, best_cost);    }  else    for (i = 0, unit = ~unit; unit; i++, unit >>= 1)      if ((unit & 1) != 0)	cost = actual_hazard (i, insn, clock, cost);  return cost;}/* Return the potential hazard cost of executing an instruction on the   units encoded by UNIT if the previous potential hazard cost was COST.   An insn with a large blockage time is chosen in preference to one   with a smaller time; an insn that uses a unit that is more likely   to be used is chosen in preference to one with a unit that is less   used.  We are trying to minimize a subsequent actual hazard.  */__inline static intpotential_hazard (unit, insn, cost)     int unit, cost;     rtx insn;{  int i, ncost;  unsigned int minb, maxb;  if (unit >= 0)    {      minb = maxb = function_units[unit].max_blockage;      if (maxb > 1)	{	  if (function_units[unit].blockage_range_function)	    {	      maxb = minb = blockage_range (unit, insn);	      maxb = MAX_BLOCKAGE_COST (maxb);	      minb = MIN_BLOCKAGE_COST (minb);	    }	  if (maxb > 1)	    {	      /* Make the number of instructions left dominate.  Make the		 minimum delay dominate the maximum delay.  If all these		 are the same, use the unit number to add an arbitrary		 ordering.  Other terms can be added.  */	      ncost = minb * 0x40 + maxb;	      ncost *= (unit_n_insns[unit] - 1) * 0x1000 + unit;	      if (ncost > cost)		cost = ncost;	    }	}    }  else    for (i = 0, unit = ~unit; unit; i++, unit >>= 1)      if ((unit & 1) != 0)	cost = potential_hazard (i, insn, cost);  return cost;}/* Compute cost of executing INSN given the dependence LINK on the insn USED.   This is the number of virtual cycles taken between instruction issue and   instruction results.  */__inline static intinsn_cost (insn, link, used)     rtx insn, link, used;{  register int cost = INSN_COST (insn);  if (cost == 0)    {      recog_memoized (insn);      /* A USE insn, or something else we don't need to understand.	 We can't pass these directly to result_ready_cost because it will	 trigger a fatal error for unrecognizable insns.  */      if (INSN_CODE (insn) < 0)	{	  INSN_COST (insn) = 1;	  return 1;	}      else	{	  cost = result_ready_cost (insn);	  if (cost < 1)	    cost = 1;	  INSN_COST (insn) = cost;	}    }  /* A USE insn should never require the value used to be computed.  This     allows the computation of a function's result and parameter values to     overlap the return and call.  */  recog_memoized (used);  if (INSN_CODE (used) < 0)    LINK_COST_FREE (link) = 1;  /* If some dependencies vary the cost, compute the adjustment.  Most     commonly, the adjustment is complete: either the cost is ignored     (in the case of an output- or anti-dependence), or the cost is     unchanged.  These values are cached in the link as LINK_COST_FREE     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;    }#endif  return cost;}/* Compute the priority number for INSN.  */static intpriority (insn)     rtx insn;{  if (insn && GET_RTX_CLASS (GET_CODE (insn)) == 'i')    {      int prev_priority;      int max_priority;      int this_priority = INSN_PRIORITY (insn);      rtx prev;      if (this_priority > 0)	return this_priority;      max_priority = 1;      /* Nonzero if these insns must be scheduled together.  */      if (SCHED_GROUP_P (insn))	{	  prev = insn;	  while (SCHED_GROUP_P (prev))	    {	      prev = PREV_INSN (prev);	      INSN_REF_COUNT (prev) += 1;	    }	}      for (prev = LOG_LINKS (insn); prev; prev = XEXP (prev, 1))	{	  rtx x = XEXP (prev, 0);	  /* A dependence pointing to a note or deleted insn is always	     obsolete, because sched_analyze_insn will have created any	     necessary new dependences which replace it.  Notes and deleted	     insns can be created when instructions are deleted by insn	     splitting, or by register allocation.  */	  if (GET_CODE (x) == NOTE || INSN_DELETED_P (x))	    {	      remove_dependence (insn, x);	      continue;	    }	  /* Clear the link cost adjustment bits.  */	  LINK_COST_FREE (prev) = 0;#ifdef ADJUST_COST	  LINK_COST_ZERO (prev) = 0;#endif	  /* This priority calculation was chosen because it results in the	     least instruction movement, and does not hurt the performance	     of the resulting code compared to the old algorithm.	     This makes the sched algorithm more stable, which results	     in better code, because there is less register pressure,	     cross jumping is more likely to work, and debugging is easier.	     When all instructions have a latency of 1, there is no need to	     move any instructions.  Subtracting one here ensures that in such	     cases all instructions will end up with a priority of one, and	     hence no scheduling will be done.	     The original code did not subtract the one, and added the	     insn_cost of the current instruction to its priority (e.g.	     move the insn_cost call down to the end).  */	  prev_priority = priority (x) + insn_cost (x, prev, insn) - 1;	  if (prev_priority > max_priority)	    max_priority = prev_priority;	  INSN_REF_COUNT (x) += 1;	}      prepare_unit (insn_unit (insn));      INSN_PRIORITY (insn) = max_priority;      return INSN_PRIORITY (insn);    }  return 0;}/* Remove all INSN_LISTs and EXPR_LISTs from the pending lists and add   them to the unused_*_list variables, so that they can be reused.  */static voidfree_pending_lists (){  register rtx link, prev_link;  if (pending_read_insns)    {      prev_link = pending_read_insns;      link = XEXP (prev_link, 1);      while (link)	{	  prev_link = link;	  link = XEXP (link, 1);	}      XEXP (prev_link, 1) = unused_insn_list;      unused_insn_list = pending_read_insns;      pending_read_insns = 0;    }  if (pending_write_insns)    {      prev_link = pending_write_insns;      link = XEXP (prev_link, 1);      while (link)	{	  prev_link = link;	  link = XEXP (link, 1);	}      XEXP (prev_link, 1) = unused_insn_list;      unused_insn_list = pending_write_insns;      pending_write_insns = 0;    }  if (pending_read_mems)    {      prev_link = pending_read_mems;      link = XEXP (prev_link, 1);      while (link)	{	  prev_link = link;	  link = XEXP (link, 1);	}      XEXP (prev_link, 1) = unused_expr_list;      unused_expr_list = pending_read_mems;      pending_read_mems = 0;    }  if (pending_write_mems)    {      prev_link = pending_write_mems;      link = XEXP (prev_link, 1);      while (link)	{	  prev_link = link;	  link = XEXP (link, 1);	}      XEXP (prev_link, 1) = unused_expr_list;      unused_expr_list = pending_write_mems;      pending_write_mems = 0;    }}/* Add an INSN and MEM reference pair to a pending INSN_LIST and MEM_LIST.   The MEM is a memory reference contained within INSN, which we are saving   so that we can do memory aliasing on it.  */static voidadd_insn_mem_dependence (insn_list, mem_list, insn, mem)     rtx *insn_list, *mem_list, insn, mem;{  register rtx link;  if (unused_insn_list)    {      link = unused_insn_list;      unused_insn_list = XEXP (link, 1);    }  else    link = rtx_alloc (INSN_LIST);  XEXP (link, 0) = insn;  XEXP (link, 1) = *insn_list;  *insn_list = link;  if (unused_expr_list)    {      link = unused_expr_list;      unused_expr_list = XEXP (link, 1);    }  else    link = rtx_alloc (EXPR_LIST);  XEXP (link, 0) = mem;  XEXP (link, 1) = *mem_list;  *mem_list = link;  pending_lists_length++;}/* Make a dependency between every memory reference on the pending lists   and INSN, thus flushing the pending lists.  */static voidflush_pending_lists (insn)     rtx insn;{  rtx link;  while (pending_read_insns)    {      add_dependence (insn, XEXP (pending_read_insns, 0), REG_DEP_ANTI);      link = pending_read_insns;      pending_read_insns = XEXP (pending_read_insns, 1);      XEXP (link, 1) = unused_insn_list;      unused_insn_list = link;      link = pending_read_mems;      pending_read_mems = XEXP (pending_read_mems, 1);      XEXP (link, 1) = unused_expr_list;      unused_expr_list = link;    }  while (pending_write_insns)    {      add_dependence (insn, XEXP (pending_write_insns, 0), REG_DEP_ANTI);      link = pending_write_insns;      pending_write_insns = XEXP (pending_write_insns, 1);      XEXP (link, 1) = unused_insn_list;      unused_insn_list = link;      link = pending_write_mems;      pending_write_mems = XEXP (pending_write_mems, 1);      XEXP (link, 1) = unused_expr_list;      unused_expr_list = link;    }  pending_lists_length = 0;  if (last_pending_memory_flush)    add_dependence (insn, last_pending_memory_flush, REG_DEP_ANTI);  last_pending_memory_flush = insn;}/* Analyze a single SET or CLOBBER rtx, X, creating all dependencies generated   by the write to the destination of X, and reads of everything mentioned.  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -