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

📄 regclass.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
      /* Now for each register look at how desirable each class is	 and find which class is preferred.  Store that in	 `prefclass[REGNO]'.  Record in `altclass[REGNO]' the largest register	 class any of whose registers is better than memory.  */          if (pass == 0)	{	  prefclass = (char *) oballoc (nregs);	  altclass = (char *) oballoc (nregs);	}      for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)	{	  register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;	  enum reg_class best = ALL_REGS, alt = NO_REGS;	  /* This is an enum reg_class, but we call it an int	     to save lots of casts.  */	  register int class;	  register struct costs *p = &costs[i];	  for (class = (int) ALL_REGS - 1; class > 0; class--)	    {	      /* Ignore classes that are too small for this operand or		 invalid for a operand that was auto-incremented.  */	      if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i))		  > reg_class_size[class]#ifdef FORBIDDEN_INC_DEC_CLASSES		  || (in_inc_dec[i] && forbidden_inc_dec_class[class])#endif		  )		;	      else if (p->cost[class] < best_cost)		{		  best_cost = p->cost[class];		  best = (enum reg_class) class;		}	      else if (p->cost[class] == best_cost)		best = reg_class_subunion[(int)best][class];	    }	  /* Record the alternate register class; i.e., a class for which	     every register in it is better than using memory.  If adding a	     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;  /* 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.  */		  if (rtx_equal_p (ops[j], op))		    ;		  /* If we can't put the other operand into a register, this		     alternative can't be used.  */		  else if (classes[j] == NO_REGS)		    alt_fail = 1;		  /* Otherwise, add to the cost of this alternative the cost		     to copy this operand to the register used for the other		     operand.  */		  else		    alt_cost += copy_cost (op, mode, classes[j], 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 (! find_reg_note (insn, REG_DEAD, op))		    alt_cost += 2;		  /* This is in place of ordinary cost computation		     for this operand.  */		  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 distingishing 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':		/* 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;		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;	}

⌨️ 快捷键说明

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