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

📄 reload.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	  /* Now get the operand values and constraints out of the insn.  */	  decode_asm_operands (body, recog_operand, recog_operand_loc,			       constraints, operand_mode);	  if (noperands > 0)	    {	      bcopy (constraints, constraints1, noperands * sizeof (char *));	      n_alternatives = n_occurrences (',', constraints[0]) + 1;	      for (i = 1; i < noperands; i++)		if (n_alternatives != n_occurrences (',', constraints[0]) + 1)		  {		    error_for_asm (insn, "operand constraints differ in number of alternatives");		    /* Avoid further trouble with this insn.  */		    PATTERN (insn) = gen_rtx (USE, VOIDmode, const0_rtx);		    n_reloads = 0;		    return;		  }	    }	  break;	}    default:      /* Ordinary insn: recognize it, allocate space for operands and	 constraints, and get them out via insn_extract.  */      insn_code_number = recog_memoized (insn);      noperands = insn_n_operands[insn_code_number];      n_alternatives = insn_n_alternatives[insn_code_number];      /* Just return "no reloads" if insn has no operands with constraints.  */      if (n_alternatives == 0)	return;      insn_extract (insn);      for (i = 0; i < noperands; i++)	{	  constraints[i] = constraints1[i]	    = insn_operand_constraint[insn_code_number][i];	  operand_mode[i] = insn_operand_mode[insn_code_number][i];	}    }  if (noperands == 0)    return;  commutative = -1;  /* If we will need to know, later, whether some pair of operands     are the same, we must compare them now and save the result.     Reloading the base and index registers will clobber them     and afterward they will fail to match.  */  for (i = 0; i < noperands; i++)    {      register char *p;      register int c;      substed_operand[i] = recog_operand[i];      p = constraints[i];      /* Scan this operand's constraint to see if it should match another.  */      while (c = *p++)	if (c == '%')	  commutative = i;	else if (c >= '0' && c <= '9')	  {	    c -= '0';	    operands_match[c][i]	      = operands_match_p (recog_operand[c], recog_operand[i]);	    /* If C can be commuted with C+1, and C might need to match I,	       then C+1 might also need to match I.  */	    if (commutative >= 0)	      {		if (c == commutative || c == commutative + 1)		  {		    int other = c + (c == commutative ? 1 : -1);		    operands_match[other][i]		      = operands_match_p (recog_operand[other], recog_operand[i]);		  }		if (i == commutative || i == commutative + 1)		  {		    int other = i + (i == commutative ? 1 : -1);		    operands_match[c][other]		    = operands_match_p (recog_operand[c], recog_operand[other]);		  }		/* Note that C is supposed to be less than I.		   No need to consider altering both C and I		   because in that case we would alter one into the other.  */	      }	  }    }  /* Examine each operand that is a memory reference or memory address     and reload parts of the addresses into index registers.     While we are at it, initialize the array `modified'.     Also here any references to pseudo regs that didn't get hard regs     but are equivalent to constants get replaced in the insn itself     with those constants.  Nobody will ever see them again.  */  for (i = 0; i < noperands; i++)    {      register RTX_CODE code = GET_CODE (recog_operand[i]);      modified[i] = RELOAD_READ;      address_reloaded[i] = 0;      if (constraints[i][0] == 'p')	{	  find_reloads_address (VOIDmode, 0,				recog_operand[i], recog_operand_loc[i],				recog_operand[i]);	  substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];	}      else if (code == MEM)	{	  if (find_reloads_address (GET_MODE (recog_operand[i]),				    recog_operand_loc[i],				    XEXP (recog_operand[i], 0),				    &XEXP (recog_operand[i], 0),				    recog_operand[i]))	    address_reloaded[i] = 1;	  substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];	}      else if (code == SUBREG)	substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]	  = find_reloads_toplev (recog_operand[i]);      else if (code == REG)	{	  /* This is equivalent to calling find_reloads_toplev.	     The code is duplicated for speed.  */	  register int regno = REGNO (recog_operand[i]);	  if (reg_equiv_constant[regno] != 0)	    substed_operand[i] = recog_operand[i]	      = reg_equiv_constant[regno];#if 0 /* This might screw code in reload1.c to delete prior output-reload	 that feeds this insn.  */	  if (reg_equiv_mem[regno] != 0)	    substed_operand[i] = recog_operand[i]	      = reg_equiv_mem[regno];#endif	  if (reg_equiv_address[regno] != 0)	    {	      *recog_operand_loc[i] = recog_operand[i]		= gen_rtx (MEM, GET_MODE (recog_operand[i]),			   reg_equiv_address[regno]);	      find_reloads_address (GET_MODE (recog_operand[i]),				    recog_operand_loc[i],				    XEXP (recog_operand[i], 0),				    &XEXP (recog_operand[i], 0),				    recog_operand[i]);	      substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];	    }	}    }  /* Now see what we need for pseudo-regs that didn't get hard regs     or got the wrong kind of hard reg.  For this, we must consider     all the operands together against the register constraints.  */  best = MAX_RECOG_OPERANDS + 100;  swapped = 0; try_swapped:  /* The constraints are made of several alternatives.     Each operand's constraint looks like foo,bar,... with commas     separating the alternatives.  The first alternatives for all     operands go together, the second alternatives go together, etc.     First loop over alternatives.  */  for (this_alternative_number = 0;       this_alternative_number < n_alternatives;       this_alternative_number++)    {      /* Loop over operands for one constraint alternative.  */      /* LOSERS counts those that don't fit this alternative	 and would require loading.  */      int losers = 0;      /* BAD is set to 1 if it some operand can't fit this alternative	 even after reloading.  */      int bad = 0;      /* REJECT is a count of how undesirable this alternative says it is	 if any reloading is required.  If the alternative matches exactly	 then REJECT is ignored, but otherwise it gets this much	 counted against it in addition to the reloading needed.  */      int reject = 0;      this_earlyclobber = 0;      for (i = 0; i < noperands; i++)	{	  register char *p = constraints[i];	  register int win = 0;	  /* 0 => this operand can be reloaded somehow for this alternative */	  int badop = 1;	  /* 0 => this operand can be reloaded if the alternative allows regs.  */	  int winreg = 0;	  int c;	  register rtx operand = recog_operand[i];	  int offset = 0;	  /* Nonzero means this is a MEM that must be reloaded into a reg	     regardless of what the constraint says.  */	  int force_reload = 0;	  int offmemok = 0;	  int earlyclobber = 0;	  /* If the operand is a SUBREG, extract	     the REG or MEM (or maybe even a constant) within.	     (Constants can occur as a result of reg_equiv_constant.)  */	  while (GET_CODE (operand) == SUBREG)	    {	      offset += SUBREG_WORD (operand);	      operand = SUBREG_REG (operand);	      if (GET_CODE (operand) != REG)		force_reload = 1;	    }	  this_alternative[i] = (int) NO_REGS;	  this_alternative_win[i] = 0;	  this_alternative_offmemok[i] = 0;	  this_alternative_earlyclobber[i] = 0;	  this_alternative_matches[i] = -1;	  /* An empty constraint or empty alternative	     allows anything which matched the pattern.  */	  if (*p == 0 || *p == ',')	    win = 1, badop = 0;	  /* Scan this alternative's specs for this operand;	     set WIN if the operand fits any letter in this alternative.	     Otherwise, clear BADOP if this operand could	     fit some letter after reloads,	     or set WINREG if this operand could fit after reloads	     provided the constraint allows some registers.  */	  while (*p && (c = *p++) != ',')	    switch (c)	      {	      case '=':		modified[i] = RELOAD_WRITE;		break;	      case '+':		modified[i] = RELOAD_READ_WRITE;		break;	      case '*':		break;	      case '%':		commutative = i;		break;	      case '?':		reject++;		break;	      case '!':		reject = 100;		break;	      case '#':		/* Ignore rest of this alternative as far as		   reloading is concerned.  */		while (*p && *p != ',') p++;		break;	      case '0':	      case '1':	      case '2':	      case '3':	      case '4':		c -= '0';		this_alternative_matches[i] = c;		/* We are supposed to match a previous operand.		   If we do, we win if that one did.		   If we do not, count both of the operands as losers.		   (This is too conservative, since most of the time		   only a single reload insn will be needed to make		   the two operands win.  As a result, this alternative		   may be rejected when it is actually desirable.)  */		if ((swapped && (c != commutative || i != commutative + 1))		    /* If we are matching as if two operands were swapped,		       also pretend that operands_match had been computed		       with swapped.		       But if I is the second of those and C is the first,		       don't exchange them, because operands_match is valid		       only on one side of its diagonal.  */		    ? (operands_match		        [(c == commutative || c == commutative + 1)			 ? 2*commutative + 1 - c : c]		        [(i == commutative || i == commutative + 1)			 ? 2*commutative + 1 - i : i])		    : operands_match[c][i])		  win = this_alternative_win[c];		else		  {		    /* Operands don't match.  */		    rtx value;		    /* Retroactively mark the operand we had to match		       as a loser, if it wasn't already.  */		    if (this_alternative_win[c])		      losers++;		    this_alternative_win[c] = 0;		    if (this_alternative[c] == (int) NO_REGS)		      bad = 1;		    /* But count the pair only once in the total badness of		       this alternative, if the pair can be a dummy reload.  */		    value		      = find_dummy_reload (recog_operand[i], recog_operand[c],					   recog_operand_loc[i], recog_operand_loc[c],					   this_alternative[c], -1);		    if (value != 0)		      losers--;		  }		/* This can be fixed with reloads if the operand		   we are supposed to match can be fixed with reloads.  */		badop = 0;		this_alternative[i] = this_alternative[c];		break;	      case 'p':		/* All necessary reloads for an address_operand		   were handled in find_reloads_address.  */		this_alternative[i] = (int) ALL_REGS;		win = 1;		break;	      case 'm':		if (force_reload)		  break;		if (GET_CODE (operand) == MEM		    || (GET_CODE (operand) == REG			&& REGNO (operand) >= FIRST_PSEUDO_REGISTER			&& reg_renumber[REGNO (operand)] < 0))		  win = 1;		if (GET_CODE (operand) == CONST_DOUBLE		    || CONSTANT_P (operand))		  badop = 0;		break;	      case '<':		if (GET_CODE (operand) == MEM		    && ! address_reloaded[i]		    && (GET_CODE (XEXP (operand, 0)) == PRE_DEC			|| GET_CODE (XEXP (operand, 0)) == POST_DEC))		  win = 1;		break;	      case '>':		if (GET_CODE (operand) == MEM		    && ! address_reloaded[i]		    && (GET_CODE (XEXP (operand, 0)) == PRE_INC			|| GET_CODE (XEXP (operand, 0)) == POST_INC))		  win = 1;		break;		/* Memory operand whose address is offsettable.  */	      case 'o':		if (force_reload)		  break;		if ((GET_CODE (operand) == MEM		     && offsettable_memref_p (operand))		    /* Certain mem addresses will become offsettable		       after they themselves are reloaded.  This is important;		       we don't want our own handling of unoffsettables		       to override the handling of reg_equiv_address.  */		    || (GET_CODE (operand) == MEM			&& GET_CODE (XEXP (operand, 0)) == REG			&& (! ind_ok			    || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0))		    || (GET_CODE (operand) == REG			&& REGNO (operand) >= FIRST_PSEUDO_REGISTER			&& reg_renumber[REGNO (operand)] < 0))		  win = 1;		if (GET_CODE (operand) == CONST_DOUBLE		    || CONSTANT_P (operand)		    || GET_CODE (operand) == MEM)		  badop = 0;		offmemok = 1;		break;	      case '&':		/* Output operand that is stored before the need for the		   input operands (and their index registers) is over.  */		if (GET_CODE (operand) == REG		    || GET_CODE (operand) == MEM)		  earlyclobber = 1, this_earlyclobber = 1;		break;	      case 'F':		if (GET_CODE (operand) == CONST_DOUBLE)		  win = 1;		break;	      case 'G':	      case 'H':		if (GET_CODE (operand) == CONST_DOUBLE		    && CONST_DOUBLE_OK_FOR_LETTER_P (operand, c))		  win = 1;		break;	      case 's':		if (GET_CODE (operand) == CONST_INT)		  break;	      case 'i':		if (CONSTANT_P (operand))

⌨️ 快捷键说明

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