sched.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,054 行 · 第 1/5 页

C
2,054
字号
voidinit_alias_analysis (){  int maxreg = max_reg_num ();  rtx insn;  rtx note;  rtx set;  reg_known_value_size = maxreg;  reg_known_value    = (rtx *) oballoc ((maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx))      - FIRST_PSEUDO_REGISTER;  bzero ((char *) (reg_known_value + FIRST_PSEUDO_REGISTER),	 (maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx));  reg_known_equiv_p    = (char *) oballoc ((maxreg -FIRST_PSEUDO_REGISTER) * sizeof (char))      - FIRST_PSEUDO_REGISTER;  bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER,	 (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char));  /* Fill in the entries with known constant values.  */  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))    if ((set = single_set (insn)) != 0	&& GET_CODE (SET_DEST (set)) == REG	&& REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER	&& (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0	     && REG_N_SETS (REGNO (SET_DEST (set))) == 1)	    || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)	&& GET_CODE (XEXP (note, 0)) != EXPR_LIST)      {	int regno = REGNO (SET_DEST (set));	reg_known_value[regno] = XEXP (note, 0);	reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;      }  /* Fill in the remaining entries.  */  while (--maxreg >= FIRST_PSEUDO_REGISTER)    if (reg_known_value[maxreg] == 0)      reg_known_value[maxreg] = regno_reg_rtx[maxreg];}/* Return 1 if X and Y are identical-looking rtx's.   We use the data in reg_known_value above to see if two registers with   different numbers are, in fact, equivalent.  */static intrtx_equal_for_memref_p (x, y)     rtx x, y;{  register int i;  register int j;  register enum rtx_code code;  register char *fmt;  if (x == 0 && y == 0)    return 1;  if (x == 0 || y == 0)    return 0;  x = canon_rtx (x);  y = canon_rtx (y);  if (x == y)    return 1;  code = GET_CODE (x);  /* Rtx's of different codes cannot be equal.  */  if (code != GET_CODE (y))    return 0;  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.     (REG:SI x) and (REG:HI x) are NOT equivalent.  */  if (GET_MODE (x) != GET_MODE (y))    return 0;  /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively.  */  if (code == REG)    return REGNO (x) == REGNO (y);  if (code == LABEL_REF)    return XEXP (x, 0) == XEXP (y, 0);  if (code == SYMBOL_REF)    return XSTR (x, 0) == XSTR (y, 0);  /* For commutative operations, the RTX match if the operand match in any     order.  Also handle the simple binary and unary cases without a loop.  */  if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')    return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))	     && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)))	    || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1))		&& rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0))));  else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')    return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))	    && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)));  else if (GET_RTX_CLASS (code) == '1')    return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 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--)    {      switch (fmt[i])	{	case 'w':	  if (XWINT (x, i) != XWINT (y, i))	    return 0;	  break;	case 'n':	case 'i':	  if (XINT (x, i) != XINT (y, i))	    return 0;	  break;	case 'V':	case 'E':	  /* Two vectors must have the same length.  */	  if (XVECLEN (x, i) != XVECLEN (y, i))	    return 0;	  /* And the corresponding elements must match.  */	  for (j = 0; j < XVECLEN (x, i); j++)	    if (rtx_equal_for_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)	      return 0;	  break;	case 'e':	  if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0)	    return 0;	  break;	case 'S':	case 's':	  if (strcmp (XSTR (x, i), XSTR (y, i)))	    return 0;	  break;	case 'u':	  /* These are just backpointers, so they don't matter.  */	  break;	case '0':	  break;	  /* It is believed that rtx's at this level will never	     contain anything but integers and other rtx's,	     except for within LABEL_REFs and SYMBOL_REFs.  */	default:	  abort ();	}    }  return 1;}/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within   X and return it, or return 0 if none found.  */static rtxfind_symbolic_term (x)     rtx x;{  register int i;  register enum rtx_code code;  register char *fmt;  code = GET_CODE (x);  if (code == SYMBOL_REF || code == LABEL_REF)    return x;  if (GET_RTX_CLASS (code) == 'o')    return 0;  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      rtx t;      if (fmt[i] == 'e')	{	  t = find_symbolic_term (XEXP (x, i));	  if (t != 0)	    return t;	}      else if (fmt[i] == 'E')	break;    }  return 0;}/* Return nonzero if X and Y (memory addresses) could reference the   same location in memory.  C is an offset accumulator.  When   C is nonzero, we are testing aliases between X and Y + C.   XSIZE is the size in bytes of the X reference,   similarly YSIZE is the size in bytes for Y.   If XSIZE or YSIZE is zero, we do not know the amount of memory being   referenced (the reference was BLKmode), so make the most pessimistic   assumptions.   We recognize the following cases of non-conflicting memory:	(1) addresses involving the frame pointer cannot conflict	    with addresses involving static variables.	(2) static variables with different addresses cannot conflict.   Nice to notice that varying addresses cannot conflict with fp if no   local variables had their addresses taken, but that's too hard now.  *//* ??? In Fortran, references to a array parameter can never conflict with   another array parameter.  */static intmemrefs_conflict_p (xsize, x, ysize, y, c)     rtx x, y;     int xsize, ysize;     HOST_WIDE_INT c;{  if (GET_CODE (x) == HIGH)    x = XEXP (x, 0);  else if (GET_CODE (x) == LO_SUM)    x = XEXP (x, 1);  else    x = canon_rtx (x);  if (GET_CODE (y) == HIGH)    y = XEXP (y, 0);  else if (GET_CODE (y) == LO_SUM)    y = XEXP (y, 1);  else    y = canon_rtx (y);  if (rtx_equal_for_memref_p (x, y))    return (xsize == 0 || ysize == 0	    || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));  if (y == frame_pointer_rtx || y == hard_frame_pointer_rtx      || y == stack_pointer_rtx)    {      rtx t = y;      int tsize = ysize;      y = x; ysize = xsize;      x = t; xsize = tsize;    }  if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx      || x == stack_pointer_rtx)    {      rtx y1;      if (CONSTANT_P (y))	return 0;      if (GET_CODE (y) == PLUS	  && canon_rtx (XEXP (y, 0)) == x	  && (y1 = canon_rtx (XEXP (y, 1)))	  && GET_CODE (y1) == CONST_INT)	{	  c += INTVAL (y1);	  return (xsize == 0 || ysize == 0		  || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));	}      if (GET_CODE (y) == PLUS	  && (y1 = canon_rtx (XEXP (y, 0)))	  && CONSTANT_P (y1))	return 0;      return 1;    }  if (GET_CODE (x) == PLUS)    {      /* The fact that X is canonicalized means that this	 PLUS rtx is canonicalized.  */      rtx x0 = XEXP (x, 0);      rtx x1 = XEXP (x, 1);      if (GET_CODE (y) == PLUS)	{	  /* The fact that Y is canonicalized means that this	     PLUS rtx is canonicalized.  */	  rtx y0 = XEXP (y, 0);	  rtx y1 = XEXP (y, 1);	  if (rtx_equal_for_memref_p (x1, y1))	    return memrefs_conflict_p (xsize, x0, ysize, y0, c);	  if (rtx_equal_for_memref_p (x0, y0))	    return memrefs_conflict_p (xsize, x1, ysize, y1, c);	  if (GET_CODE (x1) == CONST_INT)	    if (GET_CODE (y1) == CONST_INT)	      return memrefs_conflict_p (xsize, x0, ysize, y0,					 c - INTVAL (x1) + INTVAL (y1));	    else	      return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));	  else if (GET_CODE (y1) == CONST_INT)	    return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));	  /* Handle case where we cannot understand iteration operators,	     but we notice that the base addresses are distinct objects.  */	  x = find_symbolic_term (x);	  if (x == 0)	    return 1;	  y = find_symbolic_term (y);	  if (y == 0)	    return 1;	  return rtx_equal_for_memref_p (x, y);	}      else if (GET_CODE (x1) == CONST_INT)	return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));    }  else if (GET_CODE (y) == PLUS)    {      /* The fact that Y is canonicalized means that this	 PLUS rtx is canonicalized.  */      rtx y0 = XEXP (y, 0);      rtx y1 = XEXP (y, 1);      if (GET_CODE (y1) == CONST_INT)	return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));      else	return 1;    }  if (GET_CODE (x) == GET_CODE (y) && GET_CODE (x) == MULT)    {      /* Handle cases where we expect the second operands to be the	 same, and check only whether the first operand would conflict	 or not.  */      rtx x0, y0;      rtx x1 = canon_rtx (XEXP (x, 1));      rtx y1 = canon_rtx (XEXP (y, 1));      if (! rtx_equal_for_memref_p (x1, y1))	return 1;      x0 = canon_rtx (XEXP (x, 0));      y0 = canon_rtx (XEXP (y, 0));      if (rtx_equal_for_memref_p (x0, y0))	return (xsize == 0 || ysize == 0		|| (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));      /* Can't properly adjust our sizes.  */      if (GET_CODE (x1) != CONST_INT)	return 1;      xsize /= INTVAL (x1);      ysize /= INTVAL (x1);      c /= INTVAL (x1);      return memrefs_conflict_p (xsize, x0, ysize, y0, c);    }  if (CONSTANT_P (x))    {      if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT)	{	  c += (INTVAL (y) - INTVAL (x));	  return (xsize == 0 || ysize == 0		  || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));	}      if (GET_CODE (x) == CONST)	{	  if (GET_CODE (y) == CONST)	    return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),				       ysize, canon_rtx (XEXP (y, 0)), c);	  else	    return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),				       ysize, y, c);	}      if (GET_CODE (y) == CONST)	return memrefs_conflict_p (xsize, x, ysize,				   canon_rtx (XEXP (y, 0)), c);      if (CONSTANT_P (y))	return (rtx_equal_for_memref_p (x, y)		&& (xsize == 0 || ysize == 0		    || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)));      return 1;    }  return 1;}/* Functions to compute memory dependencies.   Since we process the insns in execution order, we can build tables   to keep track of what registers are fixed (and not aliased), what registers   are varying in known ways, and what registers are varying in unknown   ways.   If both memory references are volatile, then there must always be a   dependence between the two references, since their order can not be   changed.  A volatile and non-volatile reference can be interchanged   though.    A MEM_IN_STRUCT reference at a non-QImode non-AND varying address can never   conflict with a non-MEM_IN_STRUCT reference at a fixed address.   We must   allow QImode aliasing because the ANSI C standard allows character   pointers to alias anything.  We are assuming that characters are   always QImode here.  We also must allow AND addresses, because they may   generate accesses outside the object being referenced.  This is used to   generate aligned addresses from unaligned addresses, for instance, the   alpha storeqi_unaligned pattern.  *//* Read dependence: X is read after read in MEM takes place.  There can   only be a dependence here if both reads are volatile.  */intread_dependence (mem, x)     rtx mem;     rtx x;

⌨️ 快捷键说明

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