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

📄 reg-stack.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
  find_blocks (first);  stack_reg_life_analysis (first, &stackentry);  /* Dump the life analysis debug information before jump     optimization, as that will destroy the LABEL_REFS we keep the     information in. */  if (file)    dump_stack_info (file);  convert_regs ();  if (optimize)    jump_optimize (first, 2, 0, 0);}/* Check PAT, which is in INSN, for LABEL_REFs.  Add INSN to the   label's chain of references, and note which insn contains each   reference. */static voidrecord_label_references (insn, pat)     rtx insn, pat;{  register enum rtx_code code = GET_CODE (pat);  register int i;  register char *fmt;  if (code == LABEL_REF)    {      register rtx label = XEXP (pat, 0);      register rtx ref;      if (GET_CODE (label) != CODE_LABEL)	abort ();      /* Don't make a duplicate in the code_label's chain. */      for (ref = LABEL_REFS (label);	   ref && ref != label;	   ref = LABEL_NEXTREF (ref))	if (CONTAINING_INSN (ref) == insn)	  return;      CONTAINING_INSN (pat) = insn;      LABEL_NEXTREF (pat) = LABEL_REFS (label);      LABEL_REFS (label) = pat;      return;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	record_label_references (insn, XEXP (pat, i));      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (pat, i); j++)	    record_label_references (insn, XVECEXP (pat, i, j));	}    }}/* Return a pointer to the REG expression within PAT.  If PAT is not a   REG, possible enclosed by a conversion rtx, return the inner part of   PAT that stopped the search. */static rtx *get_true_reg (pat)     rtx *pat;{  for (;;)     switch (GET_CODE (*pat))      {	case SUBREG:		/* eliminate FP subregister accesses in favour of the		   actual FP register in use. */	 {	   rtx subreg;	   if (FP_REG_P (subreg = SUBREG_REG (*pat)))	    {	      *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),				  GET_MODE (subreg));	default:	      return pat;	    }	 }	case FLOAT:	case FIX:	case FLOAT_EXTEND:	   pat = & XEXP (*pat, 0);      }}/* Scan the OPERANDS and OPERAND_CONSTRAINTS of an asm_operands.   N_OPERANDS is the total number of operands.  Return which alternative   matched, or -1 is no alternative matches.   OPERAND_MATCHES is an array which indicates which operand this   operand matches due to the constraints, or -1 if no match is required.   If two operands match by coincidence, but are not required to match by   the constraints, -1 is returned.   OPERAND_CLASS is an array which indicates the smallest class   required by the constraints.  If the alternative that matches calls   for some class `class', and the operand matches a subclass of `class',   OPERAND_CLASS is set to `class' as required by the constraints, not to   the subclass. If an alternative allows more than one class,   OPERAND_CLASS is set to the smallest class that is a union of the   allowed classes. */static intconstrain_asm_operands (n_operands, operands, operand_constraints,			operand_matches, operand_class)     int n_operands;     rtx *operands;     char **operand_constraints;     int *operand_matches;     enum reg_class *operand_class;{  char **constraints = (char **) alloca (n_operands * sizeof (char *));  char *q;  int this_alternative, this_operand;  int n_alternatives;  int j;  for (j = 0; j < n_operands; j++)    constraints[j] = operand_constraints[j];  /* Compute the number of alternatives in the operands.  reload has     already guaranteed that all operands have the same number of     alternatives.  */  n_alternatives = 1;  for (q = constraints[0]; *q; q++)    n_alternatives += (*q == ',');  this_alternative = 0;  while (this_alternative < n_alternatives)    {      int lose = 0;      int i;      /* No operands match, no narrow class requirements yet.  */      for (i = 0; i < n_operands; i++)	{	  operand_matches[i] = -1;	  operand_class[i] = NO_REGS;	}      for (this_operand = 0; this_operand < n_operands; this_operand++)	{	  rtx op = operands[this_operand];	  enum machine_mode mode = GET_MODE (op);	  char *p = constraints[this_operand];	  int offset = 0;	  int win = 0;	  int c;	  if (GET_CODE (op) == SUBREG)	    {	      if (GET_CODE (SUBREG_REG (op)) == REG		  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)		offset = SUBREG_WORD (op);	      op = SUBREG_REG (op);	    }	  /* An empty constraint or empty alternative	     allows anything which matched the pattern.  */	  if (*p == 0 || *p == ',')	    win = 1;	  while (*p && (c = *p++) != ',')	    switch (c)	      {	      case '=':	      case '+':	      case '?':	      case '&':	      case '!':	      case '*':	      case '%':		/* Ignore these. */		break;	      case '#':		/* Ignore rest of this alternative. */		while (*p && *p != ',') p++;		break;	      case '0':	      case '1':	      case '2':	      case '3':	      case '4':	      case '5':		/* This operand must be the same as a previous one.		   This kind of constraint is used for instructions such		   as add when they take only two operands.		   Note that the lower-numbered operand is passed first. */		if (operands_match_p (operands[c - '0'],				      operands[this_operand]))		  {		    operand_matches[this_operand] = c - '0';		    win = 1;		  }		break;	      case 'p':		/* p is used for address_operands.  Since this is an asm,		   just to make sure that the operand is valid for Pmode. */		if (strict_memory_address_p (Pmode, op))		  win = 1;		break;	      case 'g':		/* Anything goes unless it is a REG and really has a hard reg		   but the hard reg is not in the class GENERAL_REGS.  */		if (GENERAL_REGS == ALL_REGS		    || GET_CODE (op) != REG		    || reg_fits_class_p (op, GENERAL_REGS, offset, mode))		  {		    if (GET_CODE (op) == REG)		      operand_class[this_operand]			= reg_class_subunion[(int) operand_class[this_operand]][(int) GENERAL_REGS];		    win = 1;		  }		break;	      case 'r':		if (GET_CODE (op) == REG		    && (GENERAL_REGS == ALL_REGS			|| reg_fits_class_p (op, GENERAL_REGS, offset, mode)))		  {		    operand_class[this_operand]		      = reg_class_subunion[(int) operand_class[this_operand]][(int) GENERAL_REGS];		    win = 1;		  }		break;	      case 'X':		/* This is used for a MATCH_SCRATCH in the cases when we		   don't actually need anything.  So anything goes any time. */		win = 1;		break;	      case 'm':		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 CONST_DOUBLE, 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_CODE (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;		/* Fall through */	      case 'i':		if (CONSTANT_P (op))		  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;#ifdef EXTRA_CONSTRAINT              case 'Q':              case 'R':              case 'S':              case 'T':              case 'U':		if (EXTRA_CONSTRAINT (op, c))		  win = 1;		break;#endif	      case 'V':		if (GET_CODE (op) == MEM && ! offsettable_memref_p (op))		  win = 1;		break;	      case 'o':		if (offsettable_memref_p (op))		  win = 1;		break;	      default:		if (GET_CODE (op) == REG		    && reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),					 offset, mode))		  {		    operand_class[this_operand]		      = reg_class_subunion[(int)operand_class[this_operand]][(int) REG_CLASS_FROM_LETTER (c)];		    win = 1;		  }	      }	  constraints[this_operand] = p;	  /* If this operand did not win somehow,	     this alternative loses.  */	  if (! win)	    lose = 1;	}      /* This alternative won; the operands are ok.	 Change whichever operands this alternative says to change.  */      if (! lose)	break;      this_alternative++;    }  /* For operands constrained to match another operand, copy the other     operand's class to this operand's class. */  for (j = 0; j < n_operands; j++)    if (operand_matches[j] >= 0)      operand_class[j] = operand_class[operand_matches[j]];  return this_alternative == n_alternatives ? -1 : this_alternative;}/* Record the life info of each stack reg in INSN, updating REGSTACK.   N_INPUTS is the number of inputs; N_OUTPUTS the outputs.  CONSTRAINTS   is an array of the constraint strings used in the asm statement.   OPERANDS is an array of all operands for the insn, and is assumed to   contain all output operands, then all inputs operands.   There are many rules that an asm statement for stack-like regs must   follow.  Those rules are explained at the top of this file: the rule   numbers below refer to that explanation. */static voidrecord_asm_reg_life (insn, regstack, operands, constraints,		     n_inputs, n_outputs)     rtx insn;     stack regstack;     rtx *operands;     char **constraints;     int n_inputs, n_outputs;{  int i;  int n_operands = n_inputs + n_outputs;  int first_input = n_outputs;  int n_clobbers;  int malformed_asm = 0;  rtx body = PATTERN (insn);  int *operand_matches = (int *) alloca (n_operands * sizeof (int *));  enum reg_class *operand_class     = (enum reg_class *) alloca (n_operands * sizeof (enum reg_class *));  int reg_used_as_output[FIRST_PSEUDO_REGISTER];  int implicitly_dies[FIRST_PSEUDO_REGISTER];  rtx *clobber_reg;  /* Find out what the constraints require.  If no constraint     alternative matches, this asm is malformed.  */  i = constrain_asm_operands (n_operands, operands, constraints,			      operand_matches, operand_class);  if (i < 0)    malformed_asm = 1;  /* Strip SUBREGs here to make the following code simpler. */  for (i = 0; i < n_operands; i++)    if (GET_CODE (operands[i]) == SUBREG	&& GET_CODE (SUBREG_REG (operands[i])) == REG)      operands[i] = SUBREG_REG (operands[i]);  /* Set up CLOBBER_REG.  */  n_clobbers = 0;  if (GET_CODE (body) == PARALLEL)    {      clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx *));      for (i = 0; i < XVECLEN (body, 0); i++)	if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)	  {	    rtx clobber = XVECEXP (body, 0, i);	    rtx reg = XEXP (clobber, 0);	    if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)	      reg = SUBREG_REG (reg);	    if (STACK_REG_P (reg))	      {

⌨️ 快捷键说明

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