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

📄 reorg.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    }	  res->memory = 1;	  SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);	  if (frame_pointer_needed)	    {	      SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM	      SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);#endif	    }	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	    if (global_regs[i])	      SET_HARD_REG_BIT (res->regs, i);	  /* Check for a NOTE_INSN_SETJMP.  If it exists, then we must	     assume that this call can need any register.	     This is done to be more conservative about how we handle setjmp.	     We assume that they both use and set all registers.  Using all	     registers ensures that a register will not be considered dead	     just because it crosses a setjmp call.  A register should be	     considered dead only if the setjmp call returns non-zero.  */	  if (next && GET_CODE (next) == NOTE	      && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)	    SET_HARD_REG_SET (res->regs);	  {	    rtx link;	    for (link = CALL_INSN_FUNCTION_USAGE (x);		 link;		 link = XEXP (link, 1))	      if (GET_CODE (XEXP (link, 0)) == USE)		{		  for (i = 1; i < seq_size; i++)		    {		      rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));		      if (GET_CODE (slot_pat) == SET			  && rtx_equal_p (SET_DEST (slot_pat),					  SET_DEST (XEXP (link, 0))))			break;		    }		  if (i >= seq_size)		    mark_referenced_resources (SET_DEST (XEXP (link, 0)),					       res, 0);		}	  }	}      /* ... fall through to other INSN processing ...  */    case INSN:    case JUMP_INSN:#ifdef INSN_REFERENCES_ARE_DELAYED      if (! include_delayed_effects	  && INSN_REFERENCES_ARE_DELAYED (x))	return;#endif      /* No special processing, just speed up.  */      mark_referenced_resources (PATTERN (x), res, include_delayed_effects);      return;    }  /* Process each sub-expression and flag what it needs.  */  format_ptr = GET_RTX_FORMAT (code);  for (i = 0; i < GET_RTX_LENGTH (code); i++)    switch (*format_ptr++)      {      case 'e':	mark_referenced_resources (XEXP (x, i), res, include_delayed_effects);	break;      case 'E':	for (j = 0; j < XVECLEN (x, i); j++)	  mark_referenced_resources (XVECEXP (x, i, j), res,				     include_delayed_effects);	break;      }}/* Given X, a part of an insn, and a pointer to a `struct resource', RES,   indicate which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE   is nonzero, also mark resources potentially set by the called routine.   If IN_DEST is nonzero, it means we are inside a SET.  Otherwise,   objects are being referenced instead of set.   We never mark the insn as modifying the condition code unless it explicitly   SETs CC0 even though this is not totally correct.  The reason for this is   that we require a SET of CC0 to immediately precede the reference to CC0.   So if some other insn sets CC0 as a side-effect, we know it cannot affect   our computation and thus may be placed in a delay slot.   */static voidmark_set_resources (x, res, in_dest, include_delayed_effects)     register rtx x;     register struct resources *res;     int in_dest;     int include_delayed_effects;{  register enum rtx_code code;  register int i, j;  register char *format_ptr; restart:  code = GET_CODE (x);  switch (code)    {    case NOTE:    case BARRIER:    case CODE_LABEL:    case USE:    case CONST_INT:    case CONST_DOUBLE:    case LABEL_REF:    case SYMBOL_REF:    case CONST:    case PC:      /* These don't set any resources.  */      return;    case CC0:      if (in_dest)	res->cc = 1;      return;    case CALL_INSN:      /* Called routine modifies the condition code, memory, any registers	 that aren't saved across calls, global registers and anything	 explicitly CLOBBERed immediately after the CALL_INSN.  */      if (include_delayed_effects)	{	  rtx next = NEXT_INSN (x);	  rtx prev = PREV_INSN (x);	  rtx link;	  res->cc = res->memory = 1;	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	    if (call_used_regs[i] || global_regs[i])	      SET_HARD_REG_BIT (res->regs, i);	  /* If X is part of a delay slot sequence, then NEXT should be	     the first insn after the sequence.  */	  if (NEXT_INSN (prev) != x)	    next = NEXT_INSN (NEXT_INSN (prev));	  for (link = CALL_INSN_FUNCTION_USAGE (x);	       link; link = XEXP (link, 1))	    if (GET_CODE (XEXP (link, 0)) == CLOBBER)	      mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, 0);	  /* Check for a NOTE_INSN_SETJMP.  If it exists, then we must	     assume that this call can clobber any register.  */	  if (next && GET_CODE (next) == NOTE	      && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)	    SET_HARD_REG_SET (res->regs);	}      /* ... and also what it's RTL says it modifies, if anything.  */    case JUMP_INSN:    case INSN:	/* An insn consisting of just a CLOBBER (or USE) is just for flow	   and doesn't actually do anything, so we ignore it.  */#ifdef INSN_SETS_ARE_DELAYED      if (! include_delayed_effects	  && INSN_SETS_ARE_DELAYED (x))	return;#endif      x = PATTERN (x);      if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)	goto restart;      return;    case SET:      /* If the source of a SET is a CALL, this is actually done by	 the called routine.  So only include it if we are to include the	 effects of the calling routine.  */      mark_set_resources (SET_DEST (x), res,			  (include_delayed_effects			   || GET_CODE (SET_SRC (x)) != CALL),			  0);      mark_set_resources (SET_SRC (x), res, 0, 0);      return;    case CLOBBER:      mark_set_resources (XEXP (x, 0), res, 1, 0);      return;          case SEQUENCE:      for (i = 0; i < XVECLEN (x, 0); i++)	if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))	       && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))	  mark_set_resources (XVECEXP (x, 0, i), res, 0,			      include_delayed_effects);      return;    case POST_INC:    case PRE_INC:    case POST_DEC:    case PRE_DEC:      mark_set_resources (XEXP (x, 0), res, 1, 0);      return;    case ZERO_EXTRACT:      mark_set_resources (XEXP (x, 0), res, in_dest, 0);      mark_set_resources (XEXP (x, 1), res, 0, 0);      mark_set_resources (XEXP (x, 2), res, 0, 0);      return;    case MEM:      if (in_dest)	{	  res->memory = 1;	  res->unch_memory = RTX_UNCHANGING_P (x);	  res->volatil = MEM_VOLATILE_P (x);	}      mark_set_resources (XEXP (x, 0), res, 0, 0);      return;    case SUBREG:      if (in_dest)	{	  if (GET_CODE (SUBREG_REG (x)) != REG)	    mark_set_resources (SUBREG_REG (x), res,				in_dest, include_delayed_effects);	  else	    {	      int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);	      int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));	      for (i = regno; i < last_regno; i++)		SET_HARD_REG_BIT (res->regs, i);	    }	}      return;    case REG:      if (in_dest)        for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)	  SET_HARD_REG_BIT (res->regs, REGNO (x) + i);      return;    }  /* Process each sub-expression and flag what it needs.  */  format_ptr = GET_RTX_FORMAT (code);  for (i = 0; i < GET_RTX_LENGTH (code); i++)    switch (*format_ptr++)      {      case 'e':	mark_set_resources (XEXP (x, i), res, in_dest, include_delayed_effects);	break;      case 'E':	for (j = 0; j < XVECLEN (x, i); j++)	  mark_set_resources (XVECEXP (x, i, j), res, in_dest,			      include_delayed_effects);	break;      }}/* Return TRUE if this insn should stop the search for insn to fill delay   slots.  LABELS_P indicates that labels should terminate the search.   In all cases, jumps terminate the search.  */static intstop_search_p (insn, labels_p)     rtx insn;     int labels_p;{  if (insn == 0)    return 1;  switch (GET_CODE (insn))    {    case NOTE:    case CALL_INSN:      return 0;    case CODE_LABEL:      return labels_p;    case JUMP_INSN:    case BARRIER:      return 1;    case INSN:      /* OK unless it contains a delay slot or is an `asm' insn of some type.	 We don't know anything about these.  */      return (GET_CODE (PATTERN (insn)) == SEQUENCE	      || GET_CODE (PATTERN (insn)) == ASM_INPUT	      || asm_noperands (PATTERN (insn)) >= 0);    default:      abort ();    }}/* Return TRUE if any resources are marked in both RES1 and RES2 or if either   resource set contains a volatile memory reference.  Otherwise, return FALSE.  */static intresource_conflicts_p (res1, res2)     struct resources *res1, *res2;{  if ((res1->cc && res2->cc) || (res1->memory && res2->memory)      || (res1->unch_memory && res2->unch_memory)      || res1->volatil || res2->volatil)    return 1;#ifdef HARD_REG_SET  return (res1->regs & res2->regs) != HARD_CONST (0);#else  {    int i;    for (i = 0; i < HARD_REG_SET_LONGS; i++)      if ((res1->regs[i] & res2->regs[i]) != 0)	return 1;    return 0;  }#endif}/* Return TRUE if any resource marked in RES, a `struct resources', is   referenced by INSN.  If INCLUDE_CALLED_ROUTINE is set, return if the called   routine is using those resources.   We compute this by computing all the resources referenced by INSN and   seeing if this conflicts with RES.  It might be faster to directly check   ourselves, and this is the way it used to work, but it means duplicating   a large block of complex code.  */static intinsn_references_resource_p (insn, res, include_delayed_effects)     register rtx insn;     register struct resources *res;     int include_delayed_effects;{  struct resources insn_res;  CLEAR_RESOURCE (&insn_res);  mark_referenced_resources (insn, &insn_res, include_delayed_effects);  return resource_conflicts_p (&insn_res, res);}/* Return TRUE if INSN modifies resources that are marked in RES.   INCLUDE_CALLED_ROUTINE is set if the actions of that routine should be   included.   CC0 is only modified if it is explicitly set; see comments   in front of mark_set_resources for details.  */static intinsn_sets_resource_p (insn, res, include_delayed_effects)     register rtx insn;     register struct resources *res;     int include_delayed_effects;{  struct resources insn_sets;  CLEAR_RESOURCE (&insn_sets);  mark_set_resources (insn, &insn_sets, 0, include_delayed_effects);  return resource_conflicts_p (&insn_sets, res);}/* Find a label at the end of the function or before a RETURN.  If there is   none, make one.  */static rtxfind_end_label (){  rtx insn;  /* If we found one previously, return it.  */  if (end_of_function_label)    return end_of_function_label;  /* Otherwise, see if there is a label at the end of the function.  If there     is, it must be that RETURN insns aren't needed, so that is our return     label and we don't have to do anything else.  */  insn = get_last_insn ();  while (GET_CODE (insn) == NOTE	 || (GET_CODE (insn) == INSN	     && (GET_CODE (PATTERN (insn)) == USE		 || GET_CODE (PATTERN (insn)) == CLOBBER)))    insn = PREV_INSN (insn);  /* When a target threads its epilogue we might already have a      suitable return insn.  If so put a label before it for the     end_of_function_label.  */  if (GET_CODE (insn) == BARRIER      && GET_CODE (PREV_INSN (insn)) == JUMP_INSN      && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)

⌨️ 快捷键说明

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