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

📄 cse.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif}/* Say that register REG contains a quantity not in any register before   and initialize that quantity.  */static voidmake_new_qty (reg)     register int reg;{  register int q;  if (next_qty >= max_qty)    abort ();  q = reg_qty[reg] = next_qty++;  qty_first_reg[q] = reg;  qty_last_reg[q] = reg;  qty_const[q] = qty_const_insn[q] = 0;  qty_comparison_code[q] = UNKNOWN;  reg_next_eqv[reg] = reg_prev_eqv[reg] = -1;}/* 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 (! REGNO_QTY_VALID_P (old))    abort ();  reg_qty[new] = q;  firstr = qty_first_reg[q];  lastr = qty_last_reg[q];  /* Prefer fixed hard registers to anything.  Prefer pseudo regs to other     hard regs.  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 (! (firstr < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (firstr))      /* Certain fixed registers might be of the class NO_REGS.  This means	 that not only can they not be allocated by the compiler, but	 they cannot be used in substitutions or canonicalizations	 either.  */      && (new >= FIRST_PSEUDO_REGISTER || REGNO_REG_CLASS (new) != NO_REGS)      && ((new < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (new))	  || (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 (known to be non-fixed), insert at end.	 Otherwise, insert before any non-fixed hard regs that are at the	 end.  Registers of class NO_REGS cannot be used as an	 equivalent for anything.  */      while (lastr < FIRST_PSEUDO_REGISTER && reg_prev_eqv[lastr] >= 0	     && (REGNO_REG_CLASS (lastr) == NO_REGS || ! FIXED_REGNO_P (lastr))	     && 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;    }}/* Remove REG from its equivalence class.  */static voiddelete_reg_equiv (reg)     register int reg;{  register int q = reg_qty[reg];  register int p, n;  /* If invalid, do nothing.  */  if (q == reg)    return;  p = reg_prev_eqv[reg];  n = reg_next_eqv[reg];  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;}/* 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.   Return 1 if we have done something that may have changed the hash code   of X.  */static intmention_regs (x)     rtx x;{  register enum rtx_code code;  register int i, j;  register char *fmt;  register int changed = 0;  if (x == 0)    return 0;  code = GET_CODE (x);  if (code == REG)    {      register int regno = REGNO (x);      register int endregno	= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1		   : HARD_REGNO_NREGS (regno, GET_MODE (x)));      int i;      for (i = regno; i < endregno; i++)	{	  if (reg_in_table[i] >= 0 && reg_in_table[i] != reg_tick[i])	    remove_invalid_refs (i);	  reg_in_table[i] = reg_tick[i];	}      return 0;    }  /* If X is a comparison or a COMPARE and either operand is a register     that does not have a quantity, give it one.  This is so that a later     call to record_jump_equiv won't cause X to be assigned a different     hash code and not found in the table after that call.     It is not necessary to do this here, since rehash_using_reg can     fix up the table later, but doing this here eliminates the need to     call that expensive function in the most common case where the only     use of the register is in the comparison.  */  if (code == COMPARE || GET_RTX_CLASS (code) == '<')    {      if (GET_CODE (XEXP (x, 0)) == REG	  && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))	if (insert_regs (XEXP (x, 0), NULL_PTR, 0))	  {	    rehash_using_reg (XEXP (x, 0));	    changed = 1;	  }      if (GET_CODE (XEXP (x, 1)) == REG	  && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1))))	if (insert_regs (XEXP (x, 1), NULL_PTR, 0))	  {	    rehash_using_reg (XEXP (x, 1));	    changed = 1;	  }    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    if (fmt[i] == 'e')      changed |= mention_regs (XEXP (x, i));    else if (fmt[i] == 'E')      for (j = 0; j < XVECLEN (x, i); j++)	changed |= mention_regs (XVECEXP (x, i, j));  return changed;}/* Update the register quantities for inserting X into the hash table   with a value equivalent to CLASSP.   (If the class does not contain a REG, it is irrelevant.)   If MODIFIED is nonzero, X is a destination; it is being modified.   Note that delete_reg_equiv 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);      /* If REGNO is in the equivalence table already but is of the	 wrong mode for that equivalence, don't do anything here.  */      if (REGNO_QTY_VALID_P (regno)	  && qty_mode[reg_qty[regno]] != GET_MODE (x))	return 0;      if (modified || ! REGNO_QTY_VALID_P (regno))	{	  if (classp)	    for (classp = classp->first_same_value;		 classp != 0;		 classp = classp->next_same_value)	      if (GET_CODE (classp->exp) == REG		  && GET_MODE (classp->exp) == GET_MODE (x))		{		  make_regs_eqv (regno, REGNO (classp->exp));		  return 1;		}	  make_new_qty (regno);	  qty_mode[reg_qty[regno]] = GET_MODE (x);	  return 1;	}      return 0;    }  /* If X is a SUBREG, we will likely be inserting the inner register in the     table.  If that register doesn't have an assigned quantity number at     this point but does later, the insertion that we will be doing now will     not be accessible because its hash code will have changed.  So assign     a quantity number now.  */  else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG	   && ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))    {      insert_regs (SUBREG_REG (x), NULL_PTR, 0);      mention_regs (SUBREG_REG (x));      return 1;    }  else    return mention_regs (x);}/* 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_from_table (elt, hash)     register struct table_elt *elt;     unsigned 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 if (table[hash] == elt)      table[hash] = next;    else      {	/* This entry is not in the proper hash bucket.  This can happen	   when two classes were merged by `merge_equiv_classes'.  Search	   for the hash bucket that it heads.  This happens only very	   rarely, so the cost is acceptable.  */	for (hash = 0; hash < NBUCKETS; hash++)	  if (table[hash] == elt)	    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;     unsigned 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 && GET_CODE (x) == REG)			    || exp_equiv_p (x, p->exp, GET_CODE (x) != REG, 0)))      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;     unsigned 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    {

⌨️ 快捷键说明

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