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

📄 reorg.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
     register struct resources *res;     int in_dest;     int include_called_routine;{  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_called_routine)	{	  rtx next = NEXT_INSN (x);	  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);	  /* Skip any possible labels between the CALL_INSN and CLOBBERs.  */	  while (GET_CODE (next) == CODE_LABEL)	    next = NEXT_INSN (next);	  for (; (next && GET_CODE (next) == INSN		  && GET_CODE (PATTERN (next)) == CLOBBER);	       next = NEXT_INSN (next))	    mark_set_resources (XEXP (PATTERN (next), 0), res, 1, 0);	}      /* ... 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.  */      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_called_routine			   || 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_called_routine);      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->volatil = MEM_VOLATILE_P (x);	}      mark_set_resources (XEXP (x, 0), res, 0, 0);      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_called_routine);	break;      case 'E':	for (j = 0; j < XVECLEN (x, i); j++)	  mark_set_resources (XVECEXP (x, i, j), res, in_dest,			      include_called_routine);	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->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_called_routine)     register rtx insn;     register struct resources *res;     int include_called_routine;{  struct resources insn_res;  CLEAR_RESOURCE (&insn_res);  mark_referenced_resources (insn, &insn_res, include_called_routine);  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_called_routine)     register rtx insn;     register struct resources *res;     int include_called_routine;{  struct resources insn_sets;  CLEAR_RESOURCE (&insn_sets);  mark_set_resources (insn, &insn_sets, 0, include_called_routine);  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);  if (GET_CODE (insn) == CODE_LABEL)   end_of_function_label = insn;  else    {      /* Otherwise, make a new label and emit a RETURN and BARRIER,	 if needed.  */      end_of_function_label = gen_label_rtx ();      LABEL_NUSES (end_of_function_label) = 0;      emit_label (end_of_function_label);#ifdef HAVE_return      if (HAVE_return)	{	  emit_jump_insn (gen_return ());	  emit_barrier ();	}#endif    }  /* Show one additional use for this label so it won't go away until     we are done.  */  ++LABEL_NUSES (end_of_function_label);  return end_of_function_label;}/* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace   the pattern of INSN with the SEQUENCE.   Chain the insns so that NEXT_INSN of each insn in the sequence points to   the next and NEXT_INSN of the last insn in the sequence points to   the first insn after the sequence.  Similarly for PREV_INSN.  This makes   it easier to scan all insns.   Returns the SEQUENCE that replaces INSN.  */static rtxemit_delay_sequence (insn, list, length, avail)     rtx insn;     rtx list;     int length;     int avail;{  register int i = 1;  register rtx li;  int had_barrier = 0;  /* Allocate the the rtvec to hold the insns and the SEQUENCE. */  rtvec seqv = rtvec_alloc (length + 1);  rtx seq = gen_rtx (SEQUENCE, VOIDmode, seqv);  rtx seq_insn = make_insn_raw (seq);  rtx first = get_insns ();  rtx last = get_last_insn ();  /* Make a copy of the insn having delay slots. */  rtx delay_insn = copy_rtx (insn);  /* If INSN is followed by a BARRIER, delete the BARRIER since it will only     confuse further processing.  Update LAST in case it was the last insn.       We will put the BARRIER back in later.  */  if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == BARRIER)    {      delete_insn (NEXT_INSN (insn));      last = get_last_insn ();      had_barrier = 1;    }  /* Splice our SEQUENCE into the insn stream where INSN used to be.  */  NEXT_INSN (seq_insn) = NEXT_INSN (insn);  PREV_INSN (seq_insn) = PREV_INSN (insn);  if (insn == last)    set_new_first_and_last_insn (first, seq_insn);  else    PREV_INSN (NEXT_INSN (seq_insn)) = seq_insn;  if (insn == first)    set_new_first_and_last_insn (seq_insn, last);  else    NEXT_INSN (PREV_INSN (seq_insn)) = seq_insn;  /* Build our SEQUENCE and rebuild the insn chain.  */  XVECEXP (seq, 0, 0) = delay_insn;  INSN_DELETED_P (delay_insn) = 0;  PREV_INSN (delay_insn) = PREV_INSN (seq_insn);  for (li = list; li; li = XEXP (li, 1), i++)    {      rtx tem = XEXP (li, 0);      rtx note;      /* Show that this copy of the insn isn't deleted.  */      INSN_DELETED_P (tem) = 0;      XVECEXP (seq, 0, i) = tem;      PREV_INSN (tem) = XVECEXP (seq, 0, i - 1);      NEXT_INSN (XVECEXP (seq, 0, i - 1)) = tem;      /* Remove any REG_DEAD notes because we can't rely on them now	 that the insn has been moved.  */      for (note = REG_NOTES (tem); note; note = XEXP (note, 1))	if (REG_NOTE_KIND (note) == REG_DEAD)	  XEXP (note, 0) = const0_rtx;    }  NEXT_INSN (XVECEXP (seq, 0, length)) = NEXT_INSN (seq_insn);  /* If the previous insn is a SEQUENCE, update the NEXT_INSN pointer on the     last insn in that SEQUENCE to point to us.  Similarly for the first     insn in the following insn if it is a SEQUENCE.  */  if (PREV_INSN (seq_insn) && GET_CODE (PREV_INSN (seq_insn)) == INSN      && GET_CODE (PATTERN (PREV_INSN (seq_insn))) == SEQUENCE)    NEXT_INSN (XVECEXP (PATTERN (PREV_INSN (seq_insn)), 0,			XVECLEN (PATTERN (PREV_INSN (seq_insn)), 0) - 1))      = seq_insn;  if (NEXT_INSN (seq_insn) && GET_CODE (NEXT_INSN (seq_insn)) == INSN      && GET_CODE (PATTERN (NEXT_INSN (seq_insn))) == SEQUENCE)    PREV_INSN (XVECEXP (PATTERN (NEXT_INSN (seq_insn)), 0, 0)) = seq_insn;      /* If there used to be a BARRIER, put it back.  */  if (had_barrier)    emit_barrier_after (seq_insn);  if (i != length + 1)    abort ();  return seq_insn;}/* Add INSN to DELAY_LIST and return the head of the new list.  The list must   be in the order in which the insns are to be executed.  */static rtxadd_to_delay_list (insn, delay_list)     rtx insn;     rtx delay_list;{  /* If we have an empty list, just make a new list element.  */  if (delay_list == 0)    return gen_rtx (INSN_LIST, VOIDmode, insn, NULL_RTX);  /* Otherwise this must be an INSN_LIST.  Add INSN to the end of the     list.  */  XEXP (delay_list, 1) = add_to_delay_list (insn, XEXP (delay_list, 1));  return delay_list;

⌨️ 快捷键说明

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