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

📄 cse.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      x = XEXP (x, 0);      goto repeat;    case PRE_DEC:    case PRE_INC:    case POST_DEC:    case POST_INC:    case PC:    case CC0:    case CALL:      do_not_record = 1;      return 0;    case ASM_OPERANDS:      if (MEM_VOLATILE_P (x))	{	  do_not_record = 1;	  return 0;	}    }  i = GET_RTX_LENGTH (code) - 1;  hash += (int) code + (int) GET_MODE (x);  fmt = GET_RTX_FORMAT (code);  for (; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  /* If we are about to do the last recursive call	     needed at this level, change it into iteration.	     This function  is called enough to be worth it.  */	  if (i == 0)	    {	      x = XEXP (x, 0);	      goto repeat;	    }	  hash += canon_hash (XEXP (x, i), 0);	}      else if (fmt[i] == 'E')	for (j = 0; j < XVECLEN (x, i); j++)	  hash += canon_hash (XVECEXP (x, i, j), 0);      else if (fmt[i] == 's')	{	  register char *p = XSTR (x, i);	  if (p)	    while (*p)	      {		register int tem = *p++;		hash += ((1 << HASHBITS) - 1) & (tem + (tem >> HASHBITS));	      }	}      else	{	  register int tem = XINT (x, i);	  hash += ((1 << HASHBITS) - 1) & (tem + (tem >> HASHBITS));	}    }  return hash;}/* Like canon_hash but with no side effects.  */static intsafe_hash (x, mode)     rtx x;     enum machine_mode mode;{  int save_do_not_record = do_not_record;  int save_hash_arg_in_memory = hash_arg_in_memory;  int save_hash_arg_in_struct = hash_arg_in_struct;  int hash = canon_hash (x, mode);  hash_arg_in_memory = save_hash_arg_in_memory;  hash_arg_in_struct = save_hash_arg_in_struct;  do_not_record = save_do_not_record;  return hash;}/* Return 1 iff X and Y would canonicalize into the same thing,   without actually constructing the canonicalization of either one.   If VALIDATE is nonzero,   we assume X is an expression being processed from the rtl   and Y was found in the hash table.  We check register refs   in Y for being marked as valid.  */static intexp_equiv_p (x, y, validate)     rtx x, y;     int validate;{  register int i;  register enum rtx_code code;  register char *fmt;  /* Note: it is incorrect to assume an expression is equivalent to itself     if VALIDATE is nonzero.  */  if (x == y && !validate)    return 1;  if (x == 0 || y == 0)    return x == y;  code = GET_CODE (x);  if (code != GET_CODE (y))    return 0;  switch (code)    {    case PC:    case CC0:      return x == y;    case CONST_INT:      return XINT (x, 0) == XINT (y, 0);    case LABEL_REF:    case SYMBOL_REF:      return XEXP (x, 0) == XEXP (y, 0);    case REG:      return (reg_qty[REGNO (x)] == reg_qty[REGNO (y)]	      && (!validate		  || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]));    }  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */  if (GET_MODE (x) != GET_MODE (y))    return 0;  /* Compare the elements.  If any pair of corresponding elements     fail to match, return 0 for the whole things.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  if (! exp_equiv_p (XEXP (x, i), XEXP (y, i), validate))	    return 0;	}      else if (fmt[i] == 'E')	{	  int j;	  if (XVECLEN (x, i) != XVECLEN (y, i))	    return 0;	  for (j = 0; j < XVECLEN (x, i); j++)	    if (! exp_equiv_p (XVECEXP (x, i, j), XVECEXP (y, i, j), validate))	      return 0;	}      else if (fmt[i] == 's')	{	  if (strcmp (XSTR (x, i), XSTR (y, i)))	    return 0;	}      else	{	  if (XINT (x, i) != XINT (y, i))	    return 0;	}    }  return 1;}/* Return 1 iff any subexpression of X matches Y.   Here we do not require that X or Y be valid (for registers referred to)   for being in the hash table.  */intrefers_to_p (x, y)     rtx x, y;{  register int i;  register enum rtx_code code;  register char *fmt; repeat:  if (x == y)    return 1;  if (x == 0 || y == 0)    return 0;  code = GET_CODE (x);  /* If X as a whole has the same code as Y, they may match.     If so, return 1.  */  if (code == GET_CODE (y))    {      if (exp_equiv_p (x, y, 0))	return 1;    }  /* X does not match, so try its subexpressions.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    if (fmt[i] == 'e')      {	if (i == 0)	  {	    x = XEXP (x, 0);	    goto repeat;	  }	else	  if (refers_to_p (XEXP (x, i), y))	    return 1;      }    else if (fmt[i] == 'E')      {	int j;	for (j = 0; j < XVECLEN (x, i); j++)	  if (refers_to_p (XVECEXP (x, i, j), y))	    return 1;      }  return 0;}/* Return 1 iff any subexpression of X refers to memory   at an address of REG plus some offset   such that any of the bytes' offsets fall between START (inclusive)   and END (exclusive).   The value is undefined if X is a varying address.   This function is not used in such cases.   When used in the cse pass, `qty_const' is nonzero, and it is used   to treat an address that is a register with a known constant value   as if it were that constant value.   In the loop pass, `qty_const' is zero, so this is not done.  */intrefers_to_mem_p (x, reg, start, end)     rtx x, reg;     int start, end;{  register int i;  register enum rtx_code code;  register char *fmt;  if (GET_CODE (reg) == CONST_INT)    {      start += INTVAL (reg);      end += INTVAL (reg);      reg = const0_rtx;    } repeat:  if (x == 0)    return 0;  code = GET_CODE (x);  if (code == MEM)    {      register rtx addr = XEXP (x, 0);	/* Get the address.  */      int myend;      if (GET_CODE (addr) == REG	  /* qty_const is 0 when outside the cse pass;	     at such times, this info is not available.  */	  && qty_const != 0	  && qty_const[reg_qty[REGNO (addr)]] != 0)	addr = qty_const[reg_qty[REGNO (addr)]];      if (GET_CODE (addr) == CONST)	addr = XEXP (addr, 0);      /* If ADDR is BASE, or BASE plus an integer, put	 the integer in I.  */      if (addr == reg)	i = 0;      else if (GET_CODE (addr) == PLUS	       && XEXP (addr, 0) == reg	       && GET_CODE (XEXP (addr, 1)) == CONST_INT)	i = INTVAL (XEXP (addr, 1));      else if (GET_CODE (addr) == CONST_INT && reg == const0_rtx)	i = INTVAL (addr);      else	return 0;      myend = i + GET_MODE_SIZE (GET_MODE (x));      return myend > start && i < end;    }  /* X does not match, so try its subexpressions.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    if (fmt[i] == 'e')      {	if (i == 0)	  {	    x = XEXP (x, 0);	    goto repeat;	  }	else	  if (refers_to_mem_p (XEXP (x, i), reg, start, end))	    return 1;      }    else if (fmt[i] == 'E')      {	int j;	for (j = 0; j < XVECLEN (x, i); j++)	  if (refers_to_mem_p (XVECEXP (x, i, j), reg, start, end))	    return 1;      }  return 0;}/* Nonzero if X refers to memory at a varying address;   except that a register which has at the moment a known constant value   isn't considered variable.  */static intcse_rtx_addr_varies_p (x)     rtx x;{  if (GET_CODE (x) == MEM      && GET_CODE (XEXP (x, 0)) == REG      && qty_const[reg_qty[REGNO (XEXP (x, 0))]] != 0)    return 0;  return rtx_addr_varies_p (x);}/* Canonicalize an expression:   replace each register reference inside it   with the "oldest" equivalent register.  */static rtxcanon_reg (x)     rtx x;{  register int i;  register enum rtx_code code;  register char *fmt;  if (x == 0)    return x;  code = GET_CODE (x);  switch (code)    {    case PC:    case CC0:    case CONST:    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:    case LABEL_REF:    case ADDR_VEC:    case ADDR_DIFF_VEC:      return x;    case REG:      {	register rtx new;	/* Never replace a hard reg, because hard regs can appear	   in more than one machine mode, and we must preserve the mode	   of each occurrence.  Also, some hard regs appear in	   MEMs that are shared and mustn't be altered.  */	if (REGNO (x) < FIRST_PSEUDO_REGISTER)	  return x;	new = reg_rtx[qty_first_reg[reg_qty[REGNO (x)]]];	return new ? new : x;      }    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      register int j;      if (fmt[i] == 'e')	XEXP (x, i) = canon_reg (XEXP (x, i));      else if (fmt[i] == 'E')	for (j = 0; j < XVECLEN (x, i); j++)	  XVECEXP (x, i, j) = canon_reg (XVECEXP (x, i, j));    }  return x;}/* If X is a nontrivial arithmetic operation on an argument   for which a constant value can be determined, return   the result of operating on that value, as a constant.   Otherwise, return X, possibly with one or more operands   modified by recursive calls to this function.   If X is a register whose contents are known, we do NOT   return those contents.  This is because an instruction that   uses a register is usually faster than one that uses a constant.   COPYFLAG is nonzero for memory addresses and subexpressions thereof.   If COPYFLAG is nonzero, we avoid altering X itself   by creating new structure when necessary.  In this case we   can risk creating invalid structure because it will be tested.   If COPYFLAG is zero, be careful not to substitute constants   into expressions that cannot be simplified.  */static rtxfold_rtx (x, copyflag)     rtx x;     int copyflag;{  register enum rtx_code code;  register char *fmt;  register int i, val;  rtx new = 0;  int copied = ! copyflag;  int width;  /* Constant equivalents of first three operands of X;     0 when no such equivalent is known.  */  rtx const_arg0;  rtx const_arg1;  rtx const_arg2;  if (x == 0)    return x;  width = GET_MODE_BITSIZE (GET_MODE (x));  code = GET_CODE (x);  switch (code)    {    case CONST:    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:    case LABEL_REF:    case PC:    case CC0:    case REG:      /* No use simplifying an EXPR_LIST	 since they are used only for lists of args	 in a function call's REG_EQUAL note.  */    case EXPR_LIST:      return x;  /* We must be careful when folding a memory address     to avoid making it invalid.  So fold nondestructively     and use the result only if it's valid.  */    case MEM:      {	rtx newaddr = fold_rtx (XEXP (x, 0), 1);	/* Save time if no change was made.  */	if (XEXP (x, 0) == newaddr)	  return x;	if (! memory_address_p (GET_MODE (x), newaddr)	    && memory_address_p (GET_MODE (x), XEXP (x, 0)))	  return x;	/* Don't replace a value with a more expensive one.  */	if (rtx_cost (XEXP (x, 0)) < rtx_cost (newaddr))	  return x;	if (copyflag)	  return gen_rtx (MEM, GET_MODE (x), newaddr);	XEXP (x, 0) = newaddr;	return x;      }    }  const_arg0 = 0;  const_arg1 = 0;

⌨️ 快捷键说明

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