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

📄 cse.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    if (fmt[i] == 'e')      total += rtx_cost (XEXP (x, i));    else if (fmt[i] == 'E')      for (j = 0; j < XVECLEN (x, i); j++)	total += rtx_cost (XVECEXP (x, i, j));  return total;}/* Clear the hash table and initialize each register with its own quantity,   for a new basic block.  */static voidnew_basic_block (){  register int i;  register int vecsize = max_reg * sizeof (rtx);  next_qty = max_reg;  bzero (reg_rtx, vecsize);  bzero (reg_tick, vecsize);  bcopy (all_minus_one, reg_in_table, vecsize);  bcopy (all_minus_one, reg_next_eqv, vecsize);  bcopy (all_minus_one, reg_prev_eqv, vecsize);  bcopy (consec_ints, reg_qty, vecsize);  for (i = 0; i < max_qty; i++)    {      qty_first_reg[i] = i;      qty_last_reg[i] = i;      qty_const[i] = 0;      qty_const_insn[i] = 0;    }  for (i = 0; i < NBUCKETS; i++)    {      register struct table_elt *this, *next;      for (this = table[i]; this; this = next)	{	  next = this->next_same_hash;	  free_element (this);	}    }  bzero (table, sizeof table);  prev_insn_cc0 = 0;  prev_insn_explicit_cc0 = 0;  prev_insn = 0;}/* Say that register REG contains a quantity not in any register before.  */static voidmake_new_qty (reg)     register int reg;{  register int q;  q = reg_qty[reg] = next_qty++;  qty_first_reg[q] = reg;  qty_last_reg[q] = reg;}/* Make reg NEW equivalent to reg OLD.   OLD is not changing; NEW is.  */static voidmake_regs_eqv (new, old)     register int new, old;{  register int lastr, firstr;  register int q = reg_qty[old];  /* Nothing should become eqv until it has a "non-invalid" qty number.  */  if (q == old)    abort ();  reg_qty[new] = q;  firstr = qty_first_reg[q];  lastr = qty_last_reg[q];  /* Prefer pseudo regs to hard regs with the same value.     Among pseudos, if NEW will live longer than any other reg of the same qty,     and that is beyond the current basic block,     make it the new canonical replacement for this qty.  */  if (new >= FIRST_PSEUDO_REGISTER      && (firstr < FIRST_PSEUDO_REGISTER	  || ((uid_cuid[regno_last_uid[new]] > cse_basic_block_end	       || uid_cuid[regno_first_uid[new]] < cse_basic_block_start)	      && (uid_cuid[regno_last_uid[new]]		  > uid_cuid[regno_last_uid[firstr]]))))    {      reg_prev_eqv[firstr] = new;      reg_next_eqv[new] = firstr;      reg_prev_eqv[new] = -1;      qty_first_reg[q] = new;    }  else    {      /* If NEW is a hard reg, insert at end.	 Otherwise, insert before any hard regs that are at the end.  */      while (lastr < FIRST_PSEUDO_REGISTER && new >= FIRST_PSEUDO_REGISTER)	lastr = reg_prev_eqv[lastr];      reg_next_eqv[new] = reg_next_eqv[lastr];      if (reg_next_eqv[lastr] >= 0)	reg_prev_eqv[reg_next_eqv[lastr]] = new;      else	qty_last_reg[q] = new;      reg_next_eqv[lastr] = new;      reg_prev_eqv[new] = lastr;    }}/* Discard the records of what is in register REG.  */static voidreg_invalidate (reg)     register int reg;{  register int n = reg_next_eqv[reg];  register int p = reg_prev_eqv[reg];  register int q = reg_qty[reg];  reg_tick[reg]++;  if (q == reg)    {      /* Save time if already invalid */      /* It shouldn't be linked to anything if it's invalid.  */      if (reg_prev_eqv[q] != -1)	abort ();      if (reg_next_eqv[q] != -1)	abort ();      return;    }  if (n != -1)    reg_prev_eqv[n] = p;  else    qty_last_reg[q] = p;  if (p != -1)    reg_next_eqv[p] = n;  else    qty_first_reg[q] = n;  reg_qty[reg] = reg;  qty_first_reg[reg] = reg;  qty_last_reg[reg] = reg;  reg_next_eqv[reg] = -1;  reg_prev_eqv[reg] = -1;}/* Remove any invalid expressions from the hash table   that refer to any of the registers contained in expression X.   Make sure that newly inserted references to those registers   as subexpressions will be considered valid.   mention_regs is not called when a register itself   is being stored in the table.  */static voidmention_regs (x)     rtx x;{  register enum rtx_code code;  register int i, j;  register char *fmt;  if (x == 0)    return;  code = GET_CODE (x);  if (code == REG)    {      register int regno = REGNO (x);      reg_rtx[regno] = x;      if (reg_in_table[regno] >= 0 && reg_in_table[regno] != reg_tick[regno])	remove_invalid_refs (regno);      reg_in_table[regno] = reg_tick[regno];      return;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    if (fmt[i] == 'e')      mention_regs (XEXP (x, i));    else if (fmt[i] == 'E')      for (j = 0; j < XVECLEN (x, i); j++)	mention_regs (XVECEXP (x, i, j));}/* Update the register quantities for inserting X into the hash table   with a value equivalent to CLASSP.   (If CLASSP is not a REG or a SUBREG, it is irrelevant.)   If MODIFIED is nonzero, X is a destination; it is being modified.   Note that reg_invalidate should be called on a register   before insert_regs is done on that register with MODIFIED != 0.   Nonzero value means that elements of reg_qty have changed   so X's hash code may be different.  */static intinsert_regs (x, classp, modified)     rtx x;     struct table_elt *classp;     int modified;{  if (GET_CODE (x) == REG)    {      register int regno = REGNO (x);      reg_rtx[regno] = x;      if (modified || reg_qty[regno] == regno)	{	  if (classp && GET_CODE (classp->exp) == REG)	    {	      make_regs_eqv (regno, REGNO (classp->exp));	      /* Make sure reg_rtx is set up even for regs		 not explicitly set (such as function value).  */	      reg_rtx[REGNO (classp->exp)] = classp->exp;	    }	  else	    make_new_qty (regno);	  return 1;	}    }  /* Copying a subreg into a subreg makes the regs equivalent,     but only if the entire regs' mode is within one word.     Copying one reg of a DImode into one reg of another DImode     does not make them equivalent.  */  else if (GET_CODE (x) == SUBREG	   && GET_CODE (SUBREG_REG (x)) == REG	   && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) <= UNITS_PER_WORD	   && (modified	       || reg_qty[REGNO (SUBREG_REG (x))] == REGNO (SUBREG_REG (x))))    {      if (classp && GET_CODE (classp->exp) == SUBREG	  && GET_CODE (SUBREG_REG (classp->exp)) == REG	  && GET_MODE (SUBREG_REG (classp->exp)) == GET_MODE (SUBREG_REG (x)))	{	  int oregno = REGNO (SUBREG_REG (classp->exp));	  make_regs_eqv (REGNO (SUBREG_REG (x)), oregno);	  /* Make sure reg_rtx is set up even for regs	     not explicitly set (such as function value).  */	  reg_rtx[oregno] = SUBREG_REG (classp->exp);	}      else	make_new_qty (REGNO (SUBREG_REG (x)));      return 1;    }  else    mention_regs (x);  return 0;}/* Look in or update the hash table.  *//* Put the element ELT on the list of free elements.  */static voidfree_element (elt)     struct table_elt *elt;{  elt->next_same_hash = free_element_chain;  free_element_chain = elt;}/* Return an element that is free for use.  */static struct table_elt *get_element (){  struct table_elt *elt = free_element_chain;  if (elt)    {      free_element_chain = elt->next_same_hash;      return elt;    }  n_elements_made++;  return (struct table_elt *) oballoc (sizeof (struct table_elt));}/* Remove table element ELT from use in the table.   HASH is its hash code, made using the HASH macro.   It's an argument because often that is known in advance   and we save much time not recomputing it.  */static voidremove (elt, hash)     register struct table_elt *elt;     int hash;{  if (elt == 0)    return;  /* Mark this element as removed.  See cse_insn.  */  elt->first_same_value = 0;  /* Remove the table element from its equivalence class.  */       {    register struct table_elt *prev = elt->prev_same_value;    register struct table_elt *next = elt->next_same_value;    if (next) next->prev_same_value = prev;    if (prev)      prev->next_same_value = next;    else      {	register struct table_elt *newfirst = next;	while (next)	  {	    next->first_same_value = newfirst;	    next = next->next_same_value;	  }      }  }  /* Remove the table element from its hash bucket.  */  {    register struct table_elt *prev = elt->prev_same_hash;    register struct table_elt *next = elt->next_same_hash;    if (next) next->prev_same_hash = prev;    if (prev)      prev->next_same_hash = next;    else      table[hash] = next;   }  /* Remove the table element from its related-value circular chain.  */  if (elt->related_value != 0 && elt->related_value != elt)    {      register struct table_elt *p = elt->related_value;      while (p->related_value != elt)	p = p->related_value;      p->related_value = elt->related_value;      if (p->related_value == p)	p->related_value = 0;    }  free_element (elt);}/* Look up X in the hash table and return its table element,   or 0 if X is not in the table.   MODE is the machine-mode of X, or if X is an integer constant   with VOIDmode then MODE is the mode with which X will be used.   Here we are satisfied to find an expression whose tree structure   looks like X.  */static struct table_elt *lookup (x, hash, mode)     rtx x;     int hash;     enum machine_mode mode;{  register struct table_elt *p;  for (p = table[hash]; p; p = p->next_same_hash)    if (mode == p->mode && (x == p->exp || exp_equiv_p (x, p->exp, 1)))      return p;  return 0;}/* Like `lookup' but don't care whether the table element uses invalid regs.   Also ignore discrepancies in the machine mode of a register.  */static struct table_elt *lookup_for_remove (x, hash, mode)     rtx x;     int hash;     enum machine_mode mode;{  register struct table_elt *p;  if (GET_CODE (x) == REG)    {      int regno = REGNO (x);      /* Don't check the machine mode when comparing registers;	 invalidating (REG:SI 0) also invalidates (REG:DF 0).  */      for (p = table[hash]; p; p = p->next_same_hash)	if (GET_CODE (p->exp) == REG	    && REGNO (p->exp) == regno)	  return p;    }  else    {      for (p = table[hash]; p; p = p->next_same_hash)	if (mode == p->mode && (x == p->exp || exp_equiv_p (x, p->exp, 0)))	  return p;    }  return 0;}/* Look for an expression equivalent to X and with code CODE.   If one is found, return that expression.  */static rtxlookup_as_function (x, code)     rtx x;     enum rtx_code code;{  register struct table_elt *p = lookup (x, safe_hash (x, 0) % NBUCKETS,					 GET_MODE (x));  if (p == 0)    return 0;  for (p = p->first_same_value; p; p = p->next_same_value)    {      if (GET_CODE (p->exp) == code	  /* Make sure this is a valid entry in the table.  */	  && (exp_equiv_p (XEXP (p->exp, 0), XEXP (p->exp, 0), 1)))	return p->exp;    }    return 0;}/* Insert X in the hash table, assuming HASH is its hash code   and CLASSP is the current first element of the class it should go in   (or 0 if a new class should be made).   It is inserted at the proper position to keep the class in   the order cheapest first.   MODE is the machine-mode of X, or if X is an integer constant   with VOIDmode then MODE is the mode with which X will be used.   For elements of equal cheapness, the most recent one   goes in front, except that the first element in the list   remains first unless a cheaper element is added.   The in_memory field in the hash table element is set to 0.   The caller must set it nonzero if appropriate.   You should call insert_regs (X, CLASSP, MODIFY) before calling here,   and if insert_regs returns a nonzero value   you must then recompute its hash code before calling here.   If necessary, update table showing constant values of quantities.  */#define CHEAPER(X,Y)	\   (((X)->cost < (Y)->cost) ||						\    ((X)->cost == (Y)->cost						\     && GET_CODE ((X)->exp) == REG && GET_CODE ((Y)->exp) == REG	\     && (uid_cuid[regno_last_uid[REGNO ((X)->exp)]] > cse_basic_block_end		\

⌨️ 快捷键说明

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