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

📄 reorg.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
      || ! single_set (XVECEXP (seq, 0, 0)))    return delay_list;  for (i = 1; i < XVECLEN (seq, 0); i++)    {      rtx trial = XVECEXP (seq, 0, i);      int flags;      if (insn_references_resource_p (trial, sets, 0)	  || insn_sets_resource_p (trial, needed, 0)	  || insn_sets_resource_p (trial, sets, 0)#ifdef HAVE_cc0	  /* If TRIAL sets CC0, we can't copy it, so we can't steal this	     delay list.  */	  || find_reg_note (trial, REG_CC_USER, NULL_RTX)#endif	  /* If TRIAL is from the fallthrough code of an annulled branch insn	     in SEQ, we cannot use it.  */	  || (INSN_ANNULLED_BRANCH_P (XVECEXP (seq, 0, 0))	      && ! INSN_FROM_TARGET_P (trial)))	return delay_list;      /* If this insn was already done (usually in a previous delay slot),	 pretend we put it in our delay slot.  */      if (redundant_insn (trial, insn, new_delay_list))	continue;      /* We will end up re-vectoring this branch, so compute flags	 based on jumping to the new label.  */      flags = get_jump_flags (insn, JUMP_LABEL (XVECEXP (seq, 0, 0)));      if (! must_annul	  && ((condition == const_true_rtx	       || (! insn_sets_resource_p (trial, other_needed, 0)		   && ! may_trap_p (PATTERN (trial)))))	  ? eligible_for_delay (insn, total_slots_filled, trial, flags)	  : (must_annul = 1,	     eligible_for_annul_false (insn, total_slots_filled, trial, flags)))	{	  temp = copy_rtx (trial);	  INSN_FROM_TARGET_P (temp) = 1;	  new_delay_list = add_to_delay_list (temp, new_delay_list);	  total_slots_filled++;	  if (--slots_remaining == 0)	    break;	}      else	return delay_list;    }  /* Show the place to which we will be branching.  */  *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));  /* Add any new insns to the delay list and update the count of the     number of slots filled.  */  *pslots_filled = total_slots_filled;  *pannul_p = must_annul;  if (delay_list == 0)    return new_delay_list;  for (temp = new_delay_list; temp; temp = XEXP (temp, 1))    delay_list = add_to_delay_list (XEXP (temp, 0), delay_list);  return delay_list;}/* Similar to steal_delay_list_from_target except that SEQ is on the    fallthrough path of INSN.  Here we only do something if the delay insn   of SEQ is an unconditional branch.  In that case we steal its delay slot   for INSN since unconditional branches are much easier to fill.  */static rtxsteal_delay_list_from_fallthrough (insn, condition, seq, 				   delay_list, sets, needed, other_needed,				   slots_to_fill, pslots_filled, pannul_p)     rtx insn, condition;     rtx seq;     rtx delay_list;     struct resources *sets, *needed, *other_needed;     int slots_to_fill;     int *pslots_filled;     int *pannul_p;{  int i;  int flags;  flags = get_jump_flags (insn, JUMP_LABEL (insn));  /* We can't do anything if SEQ's delay insn isn't an     unconditional branch.  */  if (! simplejump_p (XVECEXP (seq, 0, 0))      && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) != RETURN)    return delay_list;  for (i = 1; i < XVECLEN (seq, 0); i++)    {      rtx trial = XVECEXP (seq, 0, i);      /* If TRIAL sets CC0, stealing it will move it too far from the use	 of CC0.  */      if (insn_references_resource_p (trial, sets, 0)	  || insn_sets_resource_p (trial, needed, 0)	  || insn_sets_resource_p (trial, sets, 0)#ifdef HAVE_cc0	  || sets_cc0_p (PATTERN (trial))#endif	  )	break;      /* If this insn was already done, we don't need it.  */      if (redundant_insn (trial, insn, delay_list))	{	  delete_from_delay_slot (trial);	  continue;	}      if (! *pannul_p	  && ((condition == const_true_rtx	       || (! insn_sets_resource_p (trial, other_needed, 0)		   && ! may_trap_p (PATTERN (trial)))))	  ? eligible_for_delay (insn, *pslots_filled, trial, flags)	  : (*pannul_p = 1,	     eligible_for_annul_true (insn, *pslots_filled, trial, flags)))	{	  delete_from_delay_slot (trial);	  delay_list = add_to_delay_list (trial, delay_list);	  if (++(*pslots_filled) == slots_to_fill)	    break;	}      else	break;    }  return delay_list;}/* Try merging insns starting at THREAD which match exactly the insns in   INSN's delay list.   If all insns were matched and the insn was previously annulling, the   annul bit will be cleared.   For each insn that is merged, if the branch is or will be non-annulling,   we delete the merged insn.  */static voidtry_merge_delay_insns (insn, thread)     rtx insn, thread;{  rtx trial, next_trial;  rtx delay_insn = XVECEXP (PATTERN (insn), 0, 0);  int annul_p = INSN_ANNULLED_BRANCH_P (delay_insn);  int slot_number = 1;  int num_slots = XVECLEN (PATTERN (insn), 0);  rtx next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);  struct resources set, needed;  rtx merged_insns = 0;  int i;  int flags;  flags = get_jump_flags (delay_insn, JUMP_LABEL (delay_insn));  CLEAR_RESOURCE (&needed);  CLEAR_RESOURCE (&set);  /* If this is not an annulling branch, take into account anything needed in     NEXT_TO_MATCH.  This prevents two increments from being incorrectly     folded into one.  If we are annulling, this would be the correct     thing to do.  (The alternative, looking at things set in NEXT_TO_MATCH     will essentially disable this optimization.  This method is somewhat of     a kludge, but I don't see a better way.)  */  if (! annul_p)    mark_referenced_resources (next_to_match, &needed, 1);  for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)    {      rtx pat = PATTERN (trial);      rtx oldtrial = trial;      next_trial = next_nonnote_insn (trial);      /* TRIAL must be a CALL_INSN or INSN.  Skip USE and CLOBBER.  */      if (GET_CODE (trial) == INSN	  && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER))	continue;      if (GET_CODE (next_to_match) == GET_CODE (trial)#ifdef HAVE_cc0	  /* We can't share an insn that sets cc0.  */	  && ! sets_cc0_p (pat)#endif	  && ! insn_references_resource_p (trial, &set, 1)	  && ! insn_sets_resource_p (trial, &set, 1)	  && ! insn_sets_resource_p (trial, &needed, 1)	  && (trial = try_split (pat, trial, 0)) != 0	  /* Update next_trial, in case try_split succeeded.  */	  && (next_trial = next_nonnote_insn (trial))	  /* Likewise THREAD.  */	  && (thread = oldtrial == thread ? trial : thread)	  && rtx_equal_p (PATTERN (next_to_match), PATTERN (trial))	  /* Have to test this condition if annul condition is different	     from (and less restrictive than) non-annulling one.  */	  && eligible_for_delay (delay_insn, slot_number - 1, trial, flags))	{	  if (! annul_p)	    {	      update_block (trial, thread);	      if (trial == thread)		thread = next_active_insn (thread);	      delete_insn (trial);	      INSN_FROM_TARGET_P (next_to_match) = 0;	    }	  else	    merged_insns = gen_rtx (INSN_LIST, VOIDmode, trial, merged_insns);	  if (++slot_number == num_slots)	    break;	  next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);	  if (! annul_p)	    mark_referenced_resources (next_to_match, &needed, 1);	}      mark_set_resources (trial, &set, 0, 1);      mark_referenced_resources (trial, &needed, 1);    }  /* See if we stopped on a filled insn.  If we did, try to see if its     delay slots match.  */  if (slot_number != num_slots      && trial && GET_CODE (trial) == INSN      && GET_CODE (PATTERN (trial)) == SEQUENCE      && ! INSN_ANNULLED_BRANCH_P (XVECEXP (PATTERN (trial), 0, 0)))    {      rtx pat = PATTERN (trial);      rtx filled_insn = XVECEXP (pat, 0, 0);      /* Account for resources set/needed by the filled insn.  */      mark_set_resources (filled_insn, &set, 0, 1);      mark_referenced_resources (filled_insn, &needed, 1);      for (i = 1; i < XVECLEN (pat, 0); i++)	{	  rtx dtrial = XVECEXP (pat, 0, i);	  if (! insn_references_resource_p (dtrial, &set, 1)	      && ! insn_sets_resource_p (dtrial, &set, 1)	      && ! insn_sets_resource_p (dtrial, &needed, 1)#ifdef HAVE_cc0	      && ! sets_cc0_p (PATTERN (dtrial))#endif	      && rtx_equal_p (PATTERN (next_to_match), PATTERN (dtrial))	      && eligible_for_delay (delay_insn, slot_number - 1, dtrial, flags))	    {	      if (! annul_p)		{		  update_block (dtrial, thread);		  delete_from_delay_slot (dtrial);		  INSN_FROM_TARGET_P (next_to_match) = 0;		}	      else		merged_insns = gen_rtx (INSN_LIST, SImode, dtrial,					merged_insns);	      if (++slot_number == num_slots)		break;	      next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);	    }	}    }  /* If all insns in the delay slot have been matched and we were previously     annulling the branch, we need not any more.  In that case delete all the     merged insns.  Also clear the INSN_FROM_TARGET_P bit of each insn the     the delay list so that we know that it isn't only being used at the     target.  */  if (slot_number == num_slots && annul_p)    {      for (; merged_insns; merged_insns = XEXP (merged_insns, 1))	{	  if (GET_MODE (merged_insns) == SImode)	    {	      update_block (XEXP (merged_insns, 0), thread);	      delete_from_delay_slot (XEXP (merged_insns, 0));	    }	  else	    {	      update_block (XEXP (merged_insns, 0), thread);	      delete_insn (XEXP (merged_insns, 0));	    }	}      INSN_ANNULLED_BRANCH_P (delay_insn) = 0;      for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)	INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) = 0;    }}/* See if INSN is redundant with an insn in front of TARGET.  Often this   is called when INSN is a candidate for a delay slot of TARGET.   DELAY_LIST are insns that will be placed in delay slots of TARGET in front   of INSN.  Often INSN will be redundant with an insn in a delay slot of   some previous insn.  This happens when we have a series of branches to the   same label; in that case the first insn at the target might want to go   into each of the delay slots.   If we are not careful, this routine can take up a significant fraction   of the total compilation time (4%), but only wins rarely.  Hence we   speed this routine up by making two passes.  The first pass goes back   until it hits a label and sees if it find an insn with an identical   pattern.  Only in this (relatively rare) event does it check for   data conflicts.   We do not split insns we encounter.  This could cause us not to find a   redundant insn, but the cost of splitting seems greater than the possible   gain in rare cases.  */static rtxredundant_insn (insn, target, delay_list)     rtx insn;     rtx target;     rtx delay_list;{  rtx target_main = target;  rtx ipat = PATTERN (insn);  rtx trial, pat;  struct resources needed, set;  int i;  /* Scan backwards looking for a match.  */  for (trial = PREV_INSN (target); trial; trial = PREV_INSN (trial))    {      if (GET_CODE (trial) == CODE_LABEL)	return 0;      if (GET_RTX_CLASS (GET_CODE (trial)) != 'i')	continue;      pat = PATTERN (trial);      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)	continue;      if (GET_CODE (pat) == SEQUENCE)	{	  /* Stop for a CALL and its delay slots because it is difficult to	     track its resource needs correctly.  */	  if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL_INSN)	    return 0;	  /* Stop for an INSN or JUMP_INSN with delayed effects and its delay	     slots because it is difficult to track its resource needs 	     correctly.  */#ifdef INSN_SETS_ARE_DELAYED	  if (INSN_SETS_ARE_DELAYED (XVECEXP (pat, 0, 0)))	    return 0; #endif#ifdef INSN_REFERENCES_ARE_DELAYED	  if (INSN_REFERENCES_ARE_DELAYED (XVECEXP (pat, 0, 0)))	    return 0; #endif	  /* See if any of the insns in the delay slot match, updating	     resource requirements as we go.  */	  for (i = XVECLEN (pat, 0) - 1; i > 0; i--)	    if (GET_CODE (XVECEXP (pat, 0, i)) == GET_CODE (insn)		&& rtx_equal_p (PATTERN (XVECEXP (pat, 0, i)), ipat))	      break;	  /* If found a match, exit this loop early.  */	  if (i > 0)	    break;	}      else if (GET_CODE (trial) == GET_CODE (insn) && rtx_equal_p (pat, ipat))	break;    }  /* If we didn't find an insn that matches, return 0.  */  if (trial == 0)    return 0;  /* See what resources this insn sets and needs.  If they overlap, or     if this insn references CC0, it can't be redundant.  */  CLEAR_RESOURCE (&needed);  CLEAR_RESOURCE (&set);  mark_set_resources (insn, &set, 0, 1);  mark_referenced_resources (insn, &needed, 1);  /* If TARGET is a SEQUENCE, get the main insn.  */  if (GET_CODE (target) == INSN && GET_CODE

⌨️ 快捷键说明

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