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

📄 regclass.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
     and find which class is preferred.  Store that in `prefclass[REGNO]'.  */      prefclass = (char *) oballoc (nregs);      preferred_or_nothing = (char *) oballoc (nregs);  for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)    {      register int best_savings = 0;      enum reg_class best = ALL_REGS;      /* This is an enum reg_class, but we call it an int	 to save lots of casts.  */      register int class;      register struct savings *p = &savings[i];      for (class = (int) ALL_REGS - 1; class > 0; class--)	{	  if (p->savings[class] > best_savings)	    {	      best_savings = p->savings[class];	      best = (enum reg_class) class;	    }	  else if (p->savings[class] == best_savings)	    {	      best = reg_class_subunion[(int)best][class];	    }	}#if 0      /* Note that best_savings is twice number of places something	 is saved.  */      if ((best_savings - p->savings[(int) GENERAL_REGS]) * 5 < reg_n_refs[i])	prefclass[i] = (int) GENERAL_REGS;      else	prefclass[i] = (int) best;#else      /* We cast to (int) because (char) hits bugs in some compilers.  */      prefclass[i] = (int) best;#endif      /* reg_n_refs + p->memcost measures the cost of putting in memory.	 If a GENERAL_REG is no better, don't even try for one.	 Since savings and memcost are 2 * number of refs,	 this effectively counts each memory operand not needing reloading	 as costing 1/2 of a reload insn.  */      if (reg_n_refs != 0)	preferred_or_nothing[i]	  = ((best_savings - p->savings[(int) GENERAL_REGS])	     >= p->nrefs + p->memcost);    }#endif /* REGISTER_CONSTRAINTS */}#ifdef REGISTER_CONSTRAINTS/* Scan an operand OP for register class preferences.   OPNO is the operand number, and CONSTRAINTS is the constraint   vector for the insn.   Record the preferred register classes from the constraint for OP   if OP is a register.  If OP is a memory reference, record suitable   preferences for registers used in the address.  */voidreg_class_record (op, opno, constraints)     rtx op;     int opno;     char **constraints;{  char *constraint = constraints[opno];  register char *p;  register enum reg_class class = NO_REGS;  char *next = 0;  int memok = 0;  int double_cost = 0;  while (1)    {      if (GET_CODE (op) == SUBREG)	op = SUBREG_REG (op);      else break;    }  /* Memory reference: scan the address.  */  if (GET_CODE (op) == MEM)    record_address_regs (XEXP (op, 0), 2, 0);  if (GET_CODE (op) != REG)    {      /* If the constraint says the operand is supposed to BE an address,	 scan it as one.  */      if (constraint != 0 && constraint[0] == 'p')	record_address_regs (op, 2, 0);      return;    }  /* Operand is a register: examine the constraint for specified classes.  */  for (p = constraint; *p || next; p++)    {      if (*p == 0)	{	  p = next;	  next = 0;	}      switch (*p)	{	case '=':	case '?':	case '#':	case '&':	case '!':	case '%':	case 'F':	case 'G':	case 'H':	case 'i':	case 'n':	case 's':	case 'p':	case ',':	  break;	case '+':	  /* An input-output operand is twice as costly if it loses.  */	  double_cost = 1;	  break;	case 'm':	case 'o':	  memok = 1;	  break;	  /* * means ignore following letter	     when choosing register preferences.  */	case '*':	  p++;	  break;	case 'g':	case 'r':	  class	    = reg_class_subunion[(int) class][(int) GENERAL_REGS];	  break;	case '0':	case '1':	case '2':	case '3':	case '4':	  /* If constraint says "match another operand",	     use that operand's constraint to choose preferences.  */	  next = constraints[*p - '0'];	  break;	default:	  class	    = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (*p)];	}    }  {    register int i;    register struct savings *pp;    register enum reg_class class1;    int cost = 2 * (1 + double_cost);    pp = &savings[REGNO (op)];    /* Increment the savings for this reg       for each class contained in the one the constraint asks for.  */    if (class != NO_REGS && class != ALL_REGS)      {	pp->savings[(int) class] += cost;	for (i = 0; ; i++)	  {	    class1 = reg_class_subclasses[(int)class][i];	    if (class1 == LIM_REG_CLASSES)	      break;	    pp->savings[(int) class1] += cost;	  }      }    if (! memok)      pp->memcost += 1 + 2 * double_cost;    pp->nrefs++;  }}/* Record the pseudo registers we must reload into hard registers   in a subexpression of a memory address, X.   BCOST is the cost if X is a register and it fails to be in BASE_REG_CLASS.   ICOST is the cost if it fails to be in INDEX_REG_CLASS. */voidrecord_address_regs (x, bcost, icost)     rtx x;     int bcost, icost;{  register enum rtx_code code = GET_CODE (x);  switch (code)    {    case CONST_INT:    case CONST:    case CC0:    case PC:    case SYMBOL_REF:    case LABEL_REF:      return;    case PLUS:      /* When we have an address that is a sum,	 we must determine whether registers are "base" or "index" regs.	 If there is a sum of two registers, we must choose one to be	 the "base".  Luckily, we can use the REGNO_POINTER_FLAG	 to make a good choice most of the time.  */      {	rtx arg0 = XEXP (x, 0);	rtx arg1 = XEXP (x, 1);	register enum rtx_code code0 = GET_CODE (arg0);	register enum rtx_code code1 = GET_CODE (arg1);	int icost0 = 0;	int icost1 = 0;	int suppress1 = 0;	int suppress0 = 0;	/* Look inside subregs.  */	while (code0 == SUBREG)	  arg0 = SUBREG_REG (arg0), code0 = GET_CODE (arg0);	while (code1 == SUBREG)	  arg1 = SUBREG_REG (arg1), code1 = GET_CODE (arg1);	if (code0 == MULT || code1 == MEM)	  icost0 = 2;	else if (code1 == MULT || code0 == MEM)	  icost1 = 2;	else if (code0 == CONST_INT)	  suppress0 = 1;	else if (code1 == CONST_INT)	  suppress1 = 1;	else if (code0 == REG && code1 == REG)	  {	    if (REGNO_POINTER_FLAG (REGNO (arg0)))	      icost1 = 2;	    else if (REGNO_POINTER_FLAG (REGNO (arg1)))	      icost0 = 2;	    else	      icost0 = icost1 = 1;	  }	else if (code0 == REG)	  {	    if (code1 == PLUS		&& ! REGNO_POINTER_FLAG (REGNO (arg0)))	      icost0 = 2;	    else	      REGNO_POINTER_FLAG (REGNO (arg0)) = 1;	  }	else if (code1 == REG)	  {	    if (code0 == PLUS		&& ! REGNO_POINTER_FLAG (REGNO (arg1)))	      icost1 = 2;	    else	      REGNO_POINTER_FLAG (REGNO (arg1)) = 1;	  }	/* ICOST0 determines whether we are treating operand 0	   as a base register or as an index register.	   SUPPRESS0 nonzero means it isn't a register at all.	   ICOST1 and SUPPRESS1 are likewise for operand 1.  */	if (! suppress0)	  record_address_regs (arg0, 2 - icost0, icost0);	if (! suppress1)	  record_address_regs (arg1, 2 - icost1, icost1);      }      break;    case POST_INC:    case PRE_INC:    case POST_DEC:    case PRE_DEC:      /* Double the importance of a pseudo register that is incremented	 or decremented, since it would take two extra insns	 if it ends up in the wrong place.  */      record_address_regs (XEXP (x, 0), 2 * bcost, 2 * icost);      break;    case REG:      {	register struct savings *pp;	register enum reg_class class, class1;	pp = &savings[REGNO (x)];	pp->nrefs++;	/* We have an address (or part of one) that is just one register.  */	/* Record BCOST worth of savings for classes contained	   in BASE_REG_CLASS.  */	class = BASE_REG_CLASS;	if (class != NO_REGS && class != ALL_REGS)	  {	    register int i;	    pp->savings[(int) class] += bcost;	    for (i = 0; ; i++)	      {		class1 = reg_class_subclasses[(int)class][i];		if (class1 == LIM_REG_CLASSES)		  break;		pp->savings[(int) class1] += bcost;	      }	  }	/* Record ICOST worth of savings for classes contained	   in INDEX_REG_CLASS.  */	class = INDEX_REG_CLASS;	if (icost != 0 && class != NO_REGS && class != ALL_REGS)	  {	    register int i;	    pp->savings[(int) class] += icost;	    for (i = 0; ; i++)	      {		class1 = reg_class_subclasses[(int)class][i];		if (class1 == LIM_REG_CLASSES)		  break;		pp->savings[(int) class1] += icost;	      }	  }      }      break;    default:      {	register char *fmt = GET_RTX_FORMAT (code);	register int i;	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)	  if (fmt[i] == 'e')	    record_address_regs (XEXP (x, i), bcost, icost);      }    }}#endif /* REGISTER_CONSTRAINTS *//* This is the `regscan' pass of the compiler, run just before cse   and again just before loop.   It finds the first and last use of each pseudo-register   and records them in the vectors regno_first_uid, regno_last_uid.   REPEAT is nonzero the second time this is called.  *//* Indexed by pseudo register number, gives uid of first insn using the reg   (as of the time reg_scan is called).  */short *regno_first_uid;/* Indexed by pseudo register number, gives uid of last insn using the reg   (as of the time reg_scan is called).  */short *regno_last_uid;/* Maximum number of parallel sets and clobbers in any insn in this fn.   Always at least 3, since the combiner could put that many togetherm   and we want this to remain correct for all the remaining passes.  */int max_parallel;void reg_scan_mark_refs ();voidreg_scan (f, nregs, repeat)     rtx f;     int nregs;     int repeat;{  register rtx insn;  if (!repeat)    regno_first_uid = (short *) oballoc (nregs * sizeof (short));  bzero (regno_first_uid, nregs * sizeof (short));  if (!repeat)    regno_last_uid = (short *) oballoc (nregs * sizeof (short));  bzero (regno_last_uid, nregs * sizeof (short));  max_parallel = 3;  for (insn = f; insn; insn = NEXT_INSN (insn))    if (GET_CODE (insn) == INSN	|| GET_CODE (insn) == CALL_INSN	|| GET_CODE (insn) == JUMP_INSN)      {	if (GET_CODE (PATTERN (insn)) == PARALLEL	    && XVECLEN (PATTERN (insn), 0) > max_parallel)	  max_parallel = XVECLEN (PATTERN (insn), 0);	reg_scan_mark_refs (PATTERN (insn), INSN_UID (insn));      }}voidreg_scan_mark_refs (x, uid)     rtx x;     int uid;{  register enum rtx_code code = GET_CODE (x);  switch (code)    {    case CONST_INT:    case CONST:    case CONST_DOUBLE:    case CC0:    case PC:    case SYMBOL_REF:    case LABEL_REF:    case ADDR_VEC:    case ADDR_DIFF_VEC:      return;    case REG:      {	register int regno = REGNO (x);	regno_last_uid[regno] = uid;	if (regno_first_uid[regno] == 0)	  regno_first_uid[regno] = uid;      }      break;    default:      {	register char *fmt = GET_RTX_FORMAT (code);	register int i;	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)	  {	    if (fmt[i] == 'e')	      reg_scan_mark_refs (XEXP (x, i), uid);	    else if (fmt[i] == 'E' && XVEC (x, i) != 0)	      {		register int j;		for (j = XVECLEN (x, i) - 1; j >= 0; j--)		  reg_scan_mark_refs (XVECEXP (x, i, j), uid);		  	      }	  }      }    }}

⌨️ 快捷键说明

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