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

📄 recog.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 4 页
字号:
  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	validate_replace_rtx_1 (&XEXP (x, i), from, to, object);      else if (fmt[i] == 'E')	for (j = XVECLEN (x, i) - 1; j >= 0; j--)	  validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);    }}/* Try replacing every occurrence of FROM in INSN with TO.  After all   changes have been made, validate by seeing if INSN is still valid.  */intvalidate_replace_rtx (from, to, insn)     rtx from, to, insn;{  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);  return apply_change_group ();}#ifdef HAVE_cc0/* Return 1 if the insn using CC0 set by INSN does not contain   any ordered tests applied to the condition codes.   EQ and NE tests do not count.  */intnext_insn_tests_no_inequality (insn)     rtx insn;{  register rtx next = next_cc0_user (insn);  /* If there is no next insn, we have to take the conservative choice.  */  if (next == 0)    return 0;  return ((GET_CODE (next) == JUMP_INSN	   || GET_CODE (next) == INSN	   || GET_CODE (next) == CALL_INSN)	  && ! inequality_comparisons_p (PATTERN (next)));}#if 0  /* This is useless since the insn that sets the cc's	  must be followed immediately by the use of them.  *//* Return 1 if the CC value set up by INSN is not used.  */intnext_insns_test_no_inequality (insn)     rtx insn;{  register rtx next = NEXT_INSN (insn);  for (; next != 0; next = NEXT_INSN (next))    {      if (GET_CODE (next) == CODE_LABEL	  || GET_CODE (next) == BARRIER)	return 1;      if (GET_CODE (next) == NOTE)	continue;      if (inequality_comparisons_p (PATTERN (next)))	return 0;      if (sets_cc0_p (PATTERN (next)) == 1)	return 1;      if (! reg_mentioned_p (cc0_rtx, PATTERN (next)))	return 1;    }  return 1;}#endif#endif/* This is used by find_single_use to locate an rtx that contains exactly one   use of DEST, which is typically either a REG or CC0.  It returns a   pointer to the innermost rtx expression containing DEST.  Appearances of   DEST that are being used to totally replace it are not counted.  */static rtx *find_single_use_1 (dest, loc)     rtx dest;     rtx *loc;{  rtx x = *loc;  enum rtx_code code = GET_CODE (x);  rtx *result = 0;  rtx *this_result;  int i;  char *fmt;  switch (code)    {    case CONST_INT:    case CONST:    case LABEL_REF:    case SYMBOL_REF:    case CONST_DOUBLE:    case CLOBBER:      return 0;    case SET:      /* If the destination is anything other than CC0, PC, a REG or a SUBREG	 of a REG that occupies all of the REG, the insn uses DEST if	 it is mentioned in the destination or the source.  Otherwise, we	 need just check the source.  */      if (GET_CODE (SET_DEST (x)) != CC0	  && GET_CODE (SET_DEST (x)) != PC	  && GET_CODE (SET_DEST (x)) != REG	  && ! (GET_CODE (SET_DEST (x)) == SUBREG		&& GET_CODE (SUBREG_REG (SET_DEST (x))) == REG		&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))		      + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)		    == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))			 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))	break;      return find_single_use_1 (dest, &SET_SRC (x));    case MEM:    case SUBREG:      return find_single_use_1 (dest, &XEXP (x, 0));    }  /* If it wasn't one of the common cases above, check each expression and     vector of this code.  Look for a unique usage of DEST.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  if (dest == XEXP (x, i)	      || (GET_CODE (dest) == REG && GET_CODE (XEXP (x, i)) == REG		  && REGNO (dest) == REGNO (XEXP (x, i))))	    this_result = loc;	  else	    this_result = find_single_use_1 (dest, &XEXP (x, i));	  if (result == 0)	    result = this_result;	  else if (this_result)	    /* Duplicate usage.  */	    return 0;	}      else if (fmt[i] == 'E')	{	  int j;	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)	    {	      if (XVECEXP (x, i, j) == dest		  || (GET_CODE (dest) == REG		      && GET_CODE (XVECEXP (x, i, j)) == REG		      && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))		this_result = loc;	      else		this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));	      if (result == 0)		result = this_result;	      else if (this_result)		return 0;	    }	}    }  return result;}/* See if DEST, produced in INSN, is used only a single time in the   sequel.  If so, return a pointer to the innermost rtx expression in which   it is used.   If PLOC is non-zero, *PLOC is set to the insn containing the single use.   This routine will return usually zero either before flow is called (because   there will be no LOG_LINKS notes) or after reload (because the REG_DEAD   note can't be trusted).   If DEST is cc0_rtx, we look only at the next insn.  In that case, we don't   care about REG_DEAD notes or LOG_LINKS.   Otherwise, we find the single use by finding an insn that has a   LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST.  If DEST is   only referenced once in that insn, we know that it must be the first   and last insn referencing DEST.  */rtx *find_single_use (dest, insn, ploc)     rtx dest;     rtx insn;     rtx *ploc;{  rtx next;  rtx *result;  rtx link;#ifdef HAVE_cc0  if (dest == cc0_rtx)    {      next = NEXT_INSN (insn);      if (next == 0	  || (GET_CODE (next) != INSN && GET_CODE (next) != JUMP_INSN))	return 0;      result = find_single_use_1 (dest, &PATTERN (next));      if (result && ploc)	*ploc = next;      return result;    }#endif  if (reload_completed || reload_in_progress || GET_CODE (dest) != REG)    return 0;  for (next = next_nonnote_insn (insn);       next != 0 && GET_CODE (next) != CODE_LABEL;       next = next_nonnote_insn (next))    if (GET_RTX_CLASS (GET_CODE (next)) == 'i' && dead_or_set_p (next, dest))      {	for (link = LOG_LINKS (next); link; link = XEXP (link, 1))	  if (XEXP (link, 0) == insn)	    break;	if (link)	  {	    result = find_single_use_1 (dest, &PATTERN (next));	    if (ploc)	      *ploc = next;	    return result;	  }      }  return 0;}/* Return 1 if OP is a valid general operand for machine mode MODE.   This is either a register reference, a memory reference,   or a constant.  In the case of a memory reference, the address   is checked for general validity for the target machine.   Register and memory references must have mode MODE in order to be valid,   but some constants have no machine mode and are valid for any mode.   If MODE is VOIDmode, OP is checked for validity for whatever mode   it has.   The main use of this function is as a predicate in match_operand   expressions in the machine description.   For an explanation of this function's behavior for registers of   class NO_REGS, see the comment for `register_operand'.  */intgeneral_operand (op, mode)     register rtx op;     enum machine_mode mode;{  register enum rtx_code code = GET_CODE (op);  int mode_altering_drug = 0;  if (mode == VOIDmode)    mode = GET_MODE (op);  /* Don't accept CONST_INT or anything similar     if the caller wants something floating.  */  if (GET_MODE (op) == VOIDmode && mode != VOIDmode      && GET_MODE_CLASS (mode) != MODE_INT      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)    return 0;  if (CONSTANT_P (op))    return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)#ifdef LEGITIMATE_PIC_OPERAND_P	    && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif	    && LEGITIMATE_CONSTANT_P (op));  /* Except for certain constants with VOIDmode, already checked for,     OP's mode must match MODE if MODE specifies a mode.  */  if (GET_MODE (op) != mode)    return 0;  if (code == SUBREG)    {#ifdef INSN_SCHEDULING      /* On machines that have insn scheduling, we want all memory	 reference to be explicit, so outlaw paradoxical SUBREGs.  */      if (GET_CODE (SUBREG_REG (op)) == MEM	  && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))	return 0;#endif      op = SUBREG_REG (op);      code = GET_CODE (op);#if 0      /* No longer needed, since (SUBREG (MEM...))	 will load the MEM into a reload reg in the MEM's own mode.  */      mode_altering_drug = 1;#endif    }  if (code == REG)    /* A register whose class is NO_REGS is not a general operand.  */    return (REGNO (op) >= FIRST_PSEUDO_REGISTER	    || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);  if (code == MEM)    {      register rtx y = XEXP (op, 0);      if (! volatile_ok && MEM_VOLATILE_P (op))	return 0;      /* Use the mem's mode, since it will be reloaded thus.  */      mode = GET_MODE (op);      GO_IF_LEGITIMATE_ADDRESS (mode, y, win);    }  return 0; win:  if (mode_altering_drug)    return ! mode_dependent_address_p (XEXP (op, 0));  return 1;}/* Return 1 if OP is a valid memory address for a memory reference   of mode MODE.   The main use of this function is as a predicate in match_operand   expressions in the machine description.  */intaddress_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return memory_address_p (mode, op);}/* Return 1 if OP is a register reference of mode MODE.   If MODE is VOIDmode, accept a register in any mode.   The main use of this function is as a predicate in match_operand   expressions in the machine description.   As a special exception, registers whose class is NO_REGS are   not accepted by `register_operand'.  The reason for this change   is to allow the representation of special architecture artifacts   (such as a condition code register) without extending the rtl   definitions.  Since registers of class NO_REGS cannot be used   as registers in any case where register classes are examined,   it is most consistent to keep this function from accepting them.  */intregister_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (op) == SUBREG)    {      /* Before reload, we can allow (SUBREG (MEM...)) as a register operand	 because it is guaranteed to be reloaded into one.	 Just make sure the MEM is valid in itself.	 (Ideally, (SUBREG (MEM)...) should not exist after reload,	 but currently it does result from (SUBREG (REG)...) where the	 reg went on the stack.)  */      if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)	return general_operand (op, mode);#ifdef CLASS_CANNOT_CHANGE_SIZE      if (GET_CODE (SUBREG_REG (op)) == REG	  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER	  && TEST_HARD_REG_BIT (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],				REGNO (SUBREG_REG (op)))	  && (GET_MODE_SIZE (mode)	      != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))	return 0;#endif      op = SUBREG_REG (op);    }  /* We don't consider registers whose class is NO_REGS     to be a register operand.  */  return (GET_CODE (op) == REG	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));}/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH   or a hard register.  */intscratch_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_MODE (op) == mode	  && (GET_CODE (op) == SCRATCH	      || (GET_CODE (op) == REG		  && REGNO (op) < FIRST_PSEUDO_REGISTER)));}/* Return 1 if OP is a valid immediate operand for mode MODE.   The main use of this function is as a predicate in match_operand   expressions in the machine description.  */intimmediate_operand (op, mode)     register rtx op;     enum machine_mode mode;{  /* Don't accept CONST_INT or anything similar     if the caller wants something floating.  */  if (GET_MODE (op) == VOIDmode && mode != VOIDmode      && GET_MODE_CLASS (mode) != MODE_INT      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)    return 0;  return (CONSTANT_P (op)	  && (GET_MODE (op) == mode || mode == VOIDmode	      || GET_MODE (op) == VOIDmode)#ifdef LEGITIMATE_PIC_OPERAND_P	  && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif	  && LEGITIMATE_CONSTANT_P (op));}/* Returns 1 if OP is an operand that is a CONST_INT.  */intconst_int_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return GET_CODE (op) == CONST_INT;}/* Returns 1 if OP is an operand that is a constant integer or constant   floating-point number.  */intconst_double_operand (op, mode)     register rtx op;     enum machine_mode mode;{  /* Don't accept CONST_INT or anything similar     if the caller wants something floating.  */  if (GET_MODE (op) == VOIDmode && mode != VOIDmode      && GET_MODE_CLASS (mode) != MODE_INT      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)    return 0;  return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)	  && (mode == VOIDmode || GET_MODE (op) == mode	      || GET_MODE (op) == VOIDmode));}/* Return 1 if OP is a general operand that is not an immediate operand.  */intnonimmediate_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (general_operand (op, mode) && ! CONSTANT_P (op));}/* Return 1 if OP is a register reference or immediate value of mode MODE.  */intnonmemory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (CONSTANT_P (op))    {      /* Don't accept CONST_INT or anything similar	 if the caller wants something floating.  */      if (GET_MODE (op) == VOIDmode && mode != VOIDmode	  && GET_MODE_CLASS (mode) != MODE_INT	  && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)	return 0;      return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)#ifdef LEGITIMATE_PIC_OPERAND_P	      && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif	      && LEGITIMATE_CONSTANT_P (op));    }  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;

⌨️ 快捷键说明

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