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

📄 regclass.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
	     class would make a smaller class (i.e., no union of just those	     classes exists), skip that class.  The major unions of classes	     should be provided as a register class.  Don't do this if we	     will be doing it again later.  */	  if (pass == 1 || ! flag_expensive_optimizations)	    for (class = 0; class < N_REG_CLASSES; class++)	      if (p->cost[class] < p->mem_cost		  && (reg_class_size[(int) reg_class_subunion[(int) alt][class]]		      > reg_class_size[(int) alt])#ifdef FORBIDDEN_INC_DEC_CLASSES		  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])#endif		  )		alt = reg_class_subunion[(int) alt][class];	  	  /* If we don't add any classes, nothing to try.  */	  if (alt == best)	    alt = (int) NO_REGS;	  /* We cast to (int) because (char) hits bugs in some compilers.  */	  prefclass[i] = (int) best;	  altclass[i] = (int) alt;	}    }#endif /* REGISTER_CONSTRAINTS */}#ifdef REGISTER_CONSTRAINTS/* Record the cost of using memory or registers of various classes for   the operands in INSN.   N_ALTS is the number of alternatives.   N_OPS is the number of operands.   OPS is an array of the operands.   MODES are the modes of the operands, in case any are VOIDmode.   CONSTRAINTS are the constraints to use for the operands.  This array   is modified by this procedure.   This procedure works alternative by alternative.  For each alternative   we assume that we will be able to allocate all pseudos to their ideal   register class and calculate the cost of using that alternative.  Then   we compute for each operand that is a pseudo-register, the cost of    having the pseudo allocated to each register class and using it in that   alternative.  To this cost is added the cost of the alternative.   The cost of each class for this insn is its lowest cost among all the   alternatives.  */static voidrecord_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)     int n_alts;     int n_ops;     rtx *ops;     enum machine_mode *modes;     char **constraints;     rtx insn;{  int alt;  enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS];  int i, j;  rtx set;  /* By default, each operand is an input operand.  */  for (i = 0; i < n_ops; i++)    op_types[i] = OP_READ;  /* Process each alternative, each time minimizing an operand's cost with     the cost for each operand in that alternative.  */  for (alt = 0; alt < n_alts; alt++)    {      struct costs this_op_costs[MAX_RECOG_OPERANDS];      int alt_fail = 0;      int alt_cost = 0;      enum reg_class classes[MAX_RECOG_OPERANDS];      int class;      for (i = 0; i < n_ops; i++)	{	  char *p = constraints[i];	  rtx op = ops[i];	  enum machine_mode mode = modes[i];	  int allows_mem = 0;	  int win = 0;	  char c;	  /* If this operand has no constraints at all, we can conclude 	     nothing about it since anything is valid.  */	  if (*p == 0)	    {	      if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)		bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]);	      continue;	    }	  if (*p == '%')	    p++;	  /* If this alternative is only relevant when this operand	     matches a previous operand, we do different things depending	     on whether this operand is a pseudo-reg or not.  */	  if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0))	    {	      j = p[0] - '0';	      classes[i] = classes[j];	      if (GET_CODE (op) != REG || REGNO (op) < FIRST_PSEUDO_REGISTER)		{		  /* If this matches the other operand, we have no added		     cost and we win.  */		  if (rtx_equal_p (ops[j], op))		    win = 1;		  /* If we can put the other operand into a register, add to		     the cost of this alternative the cost to copy this		     operand to the register used for the other operand.  */		  else if (classes[j] != NO_REGS)		    alt_cost += copy_cost (op, mode, classes[j], 1), win = 1;		}	      else if (GET_CODE (ops[j]) != REG		       || REGNO (ops[j]) < FIRST_PSEUDO_REGISTER)		{		  /* This op is a pseudo but the one it matches is not.  */		  		  /* If we can't put the other operand into a register, this		     alternative can't be used.  */		  if (classes[j] == NO_REGS)		    alt_fail = 1;		  /* Otherwise, add to the cost of this alternative the cost		     to copy the other operand to the register used for this		     operand.  */		  else		    alt_cost += copy_cost (ops[j], mode, classes[j], 1);		}	      else		{		  /* The costs of this operand are the same as that of the		     other operand.  However, if we cannot tie them, this		     alternative needs to do a copy, which is one		     instruction.  */		  this_op_costs[i] = this_op_costs[j];		  if (REGNO (ops[i]) != REGNO (ops[j])		      && ! find_reg_note (insn, REG_DEAD, op))		    alt_cost += 2;		  /* This is in place of ordinary cost computation		     for this operand, so skip to the end of the		     alternative (should be just one character).  */		  while (*p && *p++ != ',')		    ;		  constraints[i] = p;		  continue;		}	    }	  /* Scan all the constraint letters.  See if the operand matches	     any of the constraints.  Collect the valid register classes	     and see if this operand accepts memory.  */	  classes[i] = NO_REGS;	  while (*p && (c = *p++) != ',')	    switch (c)	      {	      case '=':		op_types[i] = OP_WRITE;		break;	      case '+':		op_types[i] = OP_READ_WRITE;		break;	      case '*':		/* Ignore the next letter for this pass.  */		p++;		break;	      case '%':	      case '?':  case '!':  case '#':	      case '&':	      case '0':  case '1':  case '2':  case '3':  case '4':	      case 'p':		break;	      case 'm':  case 'o':  case 'V':		/* It doesn't seem worth distinguishing between offsettable		   and non-offsettable addresses here.  */		allows_mem = 1;		if (GET_CODE (op) == MEM)		  win = 1;		break;	      case '<':		if (GET_CODE (op) == MEM		    && (GET_CODE (XEXP (op, 0)) == PRE_DEC			|| GET_CODE (XEXP (op, 0)) == POST_DEC))		  win = 1;		break;	      case '>':		if (GET_CODE (op) == MEM		    && (GET_CODE (XEXP (op, 0)) == PRE_INC			|| GET_CODE (XEXP (op, 0)) == POST_INC))		  win = 1;		break;	      case 'E':#ifndef REAL_ARITHMETIC		/* Match any floating double constant, but only if		   we can examine the bits of it reliably.  */		if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT		     || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)		    && GET_MODE (op) != VOIDmode && ! flag_pretend_float)		  break;#endif		if (GET_CODE (op) == CONST_DOUBLE)		  win = 1;		break;	      case 'F':		if (GET_CODE (op) == CONST_DOUBLE)		  win = 1;		break;	      case 'G':	      case 'H':		if (GET_CODE (op) == CONST_DOUBLE		    && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))		  win = 1;		break;	      case 's':		if (GET_CODE (op) == CONST_INT		    || (GET_CODE (op) == CONST_DOUBLE			&& GET_MODE (op) == VOIDmode))		  break;	      case 'i':		if (CONSTANT_P (op)#ifdef LEGITIMATE_PIC_OPERAND_P		    && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif		    )		  win = 1;		break;	      case 'n':		if (GET_CODE (op) == CONST_INT		    || (GET_CODE (op) == CONST_DOUBLE			&& GET_MODE (op) == VOIDmode))		  win = 1;		break;	      case 'I':	      case 'J':	      case 'K':	      case 'L':	      case 'M':	      case 'N':	      case 'O':	      case 'P':		if (GET_CODE (op) == CONST_INT		    && CONST_OK_FOR_LETTER_P (INTVAL (op), c))		  win = 1;		break;	      case 'X':		win = 1;		break;#ifdef EXTRA_CONSTRAINT              case 'Q':              case 'R':              case 'S':              case 'T':              case 'U':		if (EXTRA_CONSTRAINT (op, c))		  win = 1;		break;#endif	      case 'g':		if (GET_CODE (op) == MEM		    || (CONSTANT_P (op)#ifdef LEGITIMATE_PIC_OPERAND_P			&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif			))		  win = 1;		allows_mem = 1;	      case 'r':		classes[i]		  = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];		break;	      default:		classes[i]		  = reg_class_subunion[(int) classes[i]]		    [(int) REG_CLASS_FROM_LETTER (c)];	      }	  constraints[i] = p;	  /* How we account for this operand now depends on whether it is  a	     pseudo register or not.  If it is, we first check if any	     register classes are valid.  If not, we ignore this alternative,	     since we want to assume that all pseudos get allocated for	     register preferencing.  If some register class is valid, compute	     the costs of moving the pseudo into that class.  */	  if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)	    {	      if (classes[i] == NO_REGS)		alt_fail = 1;	      else		{		  struct costs *pp = &this_op_costs[i];		  for (class = 0; class < N_REG_CLASSES; class++)		    pp->cost[class] = may_move_cost[class][(int) classes[i]];		  /* If the alternative actually allows memory, make things		     a bit cheaper since we won't need an extra insn to		     load it.  */		  pp->mem_cost = MEMORY_MOVE_COST (mode) - allows_mem;		  /* If we have assigned a class to this register in our		     first pass, add a cost to this alternative corresponding		     to what we would add if this register were not in the		     appropriate class.  */		  if (prefclass)		    alt_cost		      += may_move_cost[prefclass[REGNO (op)]][(int) classes[i]];		}	    }	  /* Otherwise, if this alternative wins, either because we	     have already determined that or if we have a hard register of	     the proper class, there is no cost for this alternative.  */	  else if (win		   || (GET_CODE (op) == REG		       && reg_fits_class_p (op, classes[i], 0, GET_MODE (op))))	    ;	  /* If registers are valid, the cost of this alternative includes	     copying the object to and/or from a register.  */	  else if (classes[i] != NO_REGS)	    {	      if (op_types[i] != OP_WRITE)		alt_cost += copy_cost (op, mode, classes[i], 1);	      if (op_types[i] != OP_READ)		alt_cost += copy_cost (op, mode, classes[i], 0);	    }	  /* The only other way this alternative can be used is if this is a	     constant that could be placed into memory.  */	  else if (CONSTANT_P (op) && allows_mem)	    alt_cost += MEMORY_MOVE_COST (mode);	  else	    alt_fail = 1;	}      if (alt_fail)	continue;      /* Finally, update the costs with the information we've calculated	 about this alternative.  */      for (i = 0; i < n_ops; i++)	if (GET_CODE (ops[i]) == REG	    && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)	  {	    struct costs *pp = &op_costs[i], *qq = &this_op_costs[i];	    int scale = 1 + (op_types[i] == OP_READ_WRITE);	    pp->mem_cost = MIN (pp->mem_cost,				(qq->mem_cost + alt_cost) * scale);	    for (class = 0; class < N_REG_CLASSES; class++)	      pp->cost[class] = MIN (pp->cost[class],				     (qq->cost[class] + alt_cost) * scale);	  }    }  /* If this insn is a single set copying operand 1 to operand 0     and one is a pseudo with the other a hard reg that is in its     own register class, set the cost of that register class to -1.  */  if ((set = single_set (insn)) != 0      && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)      && GET_CODE (ops[0]) == REG && GET_CODE (ops[1]) == REG)    for (i = 0; i <= 1; i++)      if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)	{	  int regno = REGNO (ops[!i]);	  enum machine_mode mode = GET_MODE (ops[!i]);	  int class;	  int nr;	  if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0	      && (reg_class_size[prefclass[regno]]		  == CLASS_MAX_NREGS (prefclass[regno], mode)))	    op_costs[i].cost[prefclass[regno]] = -1;	  else if (regno < FIRST_PSEUDO_REGISTER)	    for (class = 0; class < N_REG_CLASSES; class++)	      if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)		  && reg_class_size[class] == CLASS_MAX_NREGS (class, mode))		{		  if (reg_class_size[class] == 1)		    op_costs[i].cost[class] = -1;		  else		    {		      for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++)			{			  if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr))			    break;			}		      if (nr == HARD_REGNO_NREGS(regno,mode))			op_costs[i].cost[class] = -1;		    }		}	}}/* Compute the cost of loading X into (if TO_P is non-zero) or from (if   TO_P is zero) a register of class CLASS in mode MODE.   X must not be a pseudo.  */static intcopy_cost (x, mode, class, to_p)     rtx x;     enum machine_mode mode;     enum reg_class class;     int to_p;{  enum reg_class secondary_class = NO_REGS;  /* If X is a SCRATCH, there is actually nothing to move since we are     assuming optimal allocation.  */  if (GET_CODE (x) == SCRATCH)    return 0;  /* Get the class we will actually use for a reload.  */  class = PREFERRED_RELOAD_CLASS (x, class);#ifdef HAVE_SECONDARY_RELOADS  /* If we need a secondary reload (we assume here that we are using      the secondary reload as an intermediate, not a scratch register), the     cost is that to load the input into the intermediate register, then     to copy them.  We use a special value of TO_P to avoid recursion.  */#ifdef SECONDARY_INPUT_RELOAD_CLASS  if (to_p == 1)

⌨️ 快捷键说明

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