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

📄 genattrtab.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      exp = newexp;      /* Fall through to COND case since this is now a COND.  */    case COND:    cond:      {	int allsame = 1;	rtx defval;	/* First, check for degenerate COND. */	if (XVECLEN (exp, 0) == 0)	  return make_canonical (attr, XEXP (exp, 1));	defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));	for (i = 0; i < XVECLEN (exp, 0); i += 2)	  {	    XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));	    XVECEXP (exp, 0, i + 1)	      = make_canonical (attr, XVECEXP (exp, 0, i + 1));	    if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))	      allsame = 0;	  }	if (allsame)	  return defval;	break;      }    }  return exp;}static rtxcopy_boolean (exp)     rtx exp;{  if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)    return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),		     copy_boolean (XEXP (exp, 1)));  return exp;}/* Given a value and an attribute description, return a `struct attr_value *'   that represents that value.  This is either an existing structure, if the   value has been previously encountered, or a newly-created structure.   `insn_code' is the code of an insn whose attribute has the specified   value (-2 if not processing an insn).  We ensure that all insns for   a given value have the same number of alternatives if the value checks   alternatives.  */static struct attr_value *get_attr_value (value, attr, insn_code)     rtx value;     struct attr_desc *attr;     int insn_code;{  struct attr_value *av;  int num_alt = 0;  value = make_canonical (attr, value);  if (compares_alternatives_p (value))    {      if (insn_code < 0 || insn_alternatives == NULL)	fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");      else	num_alt = insn_alternatives[insn_code];    }  for (av = attr->first_value; av; av = av->next)    if (rtx_equal_p (value, av->value)	&& (num_alt == 0 || av->first_insn == NULL	    || insn_alternatives[av->first_insn->insn_code]))      return av;  av = (struct attr_value *) oballoc (sizeof (struct attr_value));  av->value = value;  av->next = attr->first_value;  attr->first_value = av;  av->first_insn = NULL;  av->num_insns = 0;  av->has_asm_insn = 0;  return av;}/* After all DEFINE_DELAYs have been read in, create internal attributes   to generate the required routines.   First, we compute the number of delay slots for each insn (as a COND of   each of the test expressions in DEFINE_DELAYs).  Then, if more than one   delay type is specified, we compute a similar function giving the   DEFINE_DELAY ordinal for each insn.   Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that   tells whether a given insn can be in that delay slot.   Normal attribute filling and optimization expands these to contain the   information needed to handle delay slots.  */static voidexpand_delays (){  struct delay_desc *delay;  rtx condexp;  rtx newexp;  int i;  char *p;  /* First, generate data for `num_delay_slots' function.  */  condexp = rtx_alloc (COND);  XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);  XEXP (condexp, 1) = make_numeric_value (0);  for (i = 0, delay = delays; delay; i += 2, delay = delay->next)    {      XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);      XVECEXP (condexp, 0, i + 1)	= make_numeric_value (XVECLEN (delay->def, 1) / 3);    }  make_internal_attr ("*num_delay_slots", condexp, 0);  /* If more than one delay type, do the same for computing the delay type.  */  if (num_delays > 1)    {      condexp = rtx_alloc (COND);      XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);      XEXP (condexp, 1) = make_numeric_value (0);      for (i = 0, delay = delays; delay; i += 2, delay = delay->next)	{	  XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);	  XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);	}      make_internal_attr ("*delay_type", condexp, 1);    }  /* For each delay possibility and delay slot, compute an eligibility     attribute for non-annulled insns and for each type of annulled (annul     if true and annul if false).  */ for (delay = delays; delay; delay = delay->next)   {     for (i = 0; i < XVECLEN (delay->def, 1); i += 3)       {	 condexp = XVECEXP (delay->def, 1, i);	 if (condexp == 0) condexp = false_rtx;	 newexp = attr_rtx (IF_THEN_ELSE, condexp,			    make_numeric_value (1), make_numeric_value (0));	 p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d",			  delay->num, i / 3);	 make_internal_attr (p, newexp, 1);	 if (have_annul_true)	   {	     condexp = XVECEXP (delay->def, 1, i + 1);	     if (condexp == 0) condexp = false_rtx;	     newexp = attr_rtx (IF_THEN_ELSE, condexp,				make_numeric_value (1),				make_numeric_value (0));	     p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2,			      "*annul_true_%d_%d", delay->num, i / 3);	     make_internal_attr (p, newexp, 1);	   }	 if (have_annul_false)	   {	     condexp = XVECEXP (delay->def, 1, i + 2);	     if (condexp == 0) condexp = false_rtx;	     newexp = attr_rtx (IF_THEN_ELSE, condexp,				make_numeric_value (1),				make_numeric_value (0));	     p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2,			      "*annul_false_%d_%d", delay->num, i / 3);	     make_internal_attr (p, newexp, 1);	   }       }   }}/* This function is given a left and right side expression and an operator.   Each side is a conditional expression, each alternative of which has a   numerical value.  The function returns another conditional expression   which, for every possible set of condition values, returns a value that is   the operator applied to the values of the two sides.   Since this is called early, it must also support IF_THEN_ELSE.  */static rtxoperate_exp (op, left, right)     enum operator op;     rtx left, right;{  int left_value, right_value;  rtx newexp;  int i;  /* If left is a string, apply operator to it and the right side.  */  if (GET_CODE (left) == CONST_STRING)    {      /* If right is also a string, just perform the operation.  */      if (GET_CODE (right) == CONST_STRING)	{	  left_value = atoi (XSTR (left, 0));	  right_value = atoi (XSTR (right, 0));	  switch (op)	    {	    case PLUS_OP:	      i = left_value + right_value;	      break;	    case MINUS_OP:	      i = left_value - right_value;	      break;	    case POS_MINUS_OP:  /* The positive part of LEFT - RIGHT.  */	      if (left_value > right_value)		i = left_value - right_value;	      else		i = 0;	      break;	    case OR_OP:	      i = left_value | right_value;	      break;	    case EQ_OP:	      i = left_value == right_value;	      break;	    case RANGE_OP:	      i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value;	      break;	    case MAX_OP:	      if (left_value > right_value)		i = left_value;	      else		i = right_value;	      break;	    case MIN_OP:	      if (left_value < right_value)		i = left_value;	      else		i = right_value;	      break;	    default:	      abort ();	    }	  return make_numeric_value (i);	}      else if (GET_CODE (right) == IF_THEN_ELSE)	{	  /* Apply recursively to all values within.  */	  rtx newleft = operate_exp (op, left, XEXP (right, 1));	  rtx newright = operate_exp (op, left, XEXP (right, 2));	  if (rtx_equal_p (newleft, newright))	    return newleft;	  return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);	}      else if (GET_CODE (right) == COND)	{	  int allsame = 1;	  rtx defval;	  newexp = rtx_alloc (COND);	  XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));	  defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));	  for (i = 0; i < XVECLEN (right, 0); i += 2)	    {	      XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);	      XVECEXP (newexp, 0, i + 1)		= operate_exp (op, left, XVECEXP (right, 0, i + 1));	      if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),				 defval))     		allsame = 0;	    }	  /* If the resulting cond is trivial (all alternatives	     give the same value), optimize it away.  */	  if (allsame)	    {	      obstack_free (rtl_obstack, newexp);	      return operate_exp (op, left, XEXP (right, 1));	    }	  /* If the result is the same as the RIGHT operand,	     just use that.  */	  if (rtx_equal_p (newexp, right))	    {	      obstack_free (rtl_obstack, newexp);	      return right;	    }	  return newexp;	}      else	fatal ("Badly formed attribute value");    }  /* Otherwise, do recursion the other way.  */  else if (GET_CODE (left) == IF_THEN_ELSE)    {      rtx newleft = operate_exp (op, XEXP (left, 1), right);      rtx newright = operate_exp (op, XEXP (left, 2), right);      if (rtx_equal_p (newleft, newright))	return newleft;      return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);    }  else if (GET_CODE (left) == COND)    {      int allsame = 1;      rtx defval;      newexp = rtx_alloc (COND);      XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));      defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);      for (i = 0; i < XVECLEN (left, 0); i += 2)	{	  XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);	  XVECEXP (newexp, 0, i + 1)	    = operate_exp (op, XVECEXP (left, 0, i + 1), right);	  if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),			     defval))     	    allsame = 0;	}      /* If the cond is trivial (all alternatives give the same value),	 optimize it away.  */      if (allsame)	{	  obstack_free (rtl_obstack, newexp);	  return operate_exp (op, XEXP (left, 1), right);	}      /* If the result is the same as the LEFT operand,	 just use that.  */      if (rtx_equal_p (newexp, left))	{	  obstack_free (rtl_obstack, newexp);	  return left;	}      return newexp;    }  else    fatal ("Badly formed attribute value.");  /* NOTREACHED */  return NULL;}/* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we   construct a number of attributes.   The first produces a function `function_units_used' which is given an   insn and produces an encoding showing which function units are required   for the execution of that insn.  If the value is non-negative, the insn   uses that unit; otherwise, the value is a one's compliment mask of units   used.   The second produces a function `result_ready_cost' which is used to   determine the time that the result of an insn will be ready and hence   a worst-case schedule.   Both of these produce quite complex expressions which are then set as the   default value of internal attributes.  Normal attribute simplification   should produce reasonable expressions.   For each unit, a `<name>_unit_ready_cost' function will take an   insn and give the delay until that unit will be ready with the result   and a `<name>_unit_conflict_cost' function is given an insn already   executing on the unit and a candidate to execute and will give the   cost from the time the executing insn started until the candidate   can start (ignore limitations on the number of simultaneous insns).   For each unit, a `<name>_unit_blockage' function is given an insn   already executing on the unit and a candidate to execute and will   give the delay incurred due to function unit conflicts.  The range of   blockage cost values for a given executing insn is given by the   `<name>_unit_blockage_range' function.  These values are encoded in   an int where the upper half gives the minimum value and the lower   half gives the maximum value.  */static voidexpand_units (){  struct function_unit *unit, **unit_num;  struct function_unit_op *op, **op_array, ***unit_ops;  rtx unitsmask;  rtx readycost;  rtx newexp;  char *str;  int i, j, u, num, nvalues;  /* Rebuild the condition for the unit to share the RTL expressions.     Sharing is required by simplify_by_exploding.  Build the issue delay     expressions.  Validate the expressions we were given for the conditions     and conflict vector.  Then make attributes for use in the conflict     function.  */  for (unit = units; unit; unit = unit->next)    {      rtx min_issue = make_numeric_value (unit->issue_delay.min);      unit->condexp = check_attr_test (unit->condexp, 0);      for (op = unit->ops; op; op = op->next)	{	  rtx issue_delay = make_numeric_value (op->issue_delay);	  rtx issue_exp = issue_delay;	  /* Build, validate, and simplify the issue delay expression.  */	  if (op->conflict_exp != true_rtx)	    issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp,				  issue_exp, make_numeric_value (0));	  issue_exp = check_attr_value (make_canonical (NULL_ATTR,							issue_exp),					NULL_ATTR);	  issue_exp = simplify_knowing (issue_exp, unit->condexp);	  op->issue_exp = issue_exp;	  /* Make an attribute for use in the conflict function if needed.  */	  unit->needs_conflict_function = (unit->issue_delay.min					   != unit->issue_delay.max);	  if (unit->needs_conflict_function)	    {	      str = attr_printf (strlen (unit->name) + sizeof ("*_cost_") + MAX_DIGITS,				 "*%s_cost_%d", unit->name, op->num);	      make_internal_attr (str, issue_exp, 1);	    }	  /* Validate the condition.  */	  op->condexp = check_attr_test (op->condexp, 0);

⌨️ 快捷键说明

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