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

📄 flow.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  for (insn = f, i = -1, prev_code = JUMP_INSN, depth = 1;       insn; insn = NEXT_INSN (insn))    {      code = GET_CODE (insn);      if (code == NOTE)	{	  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)	    depth++;	  else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)	    depth--;	}      /* A basic block starts at label, or after something that can jump.  */      else if (code == CODE_LABEL	       || (GET_RTX_CLASS (code) == 'i'		   && (prev_code == JUMP_INSN		       || (prev_code == CALL_INSN			   && nonlocal_label_list != 0			   && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))		       || prev_code == BARRIER)))	{	  basic_block_head[++i] = insn;	  basic_block_end[i] = insn;	  basic_block_loop_depth[i] = depth;	  if (code == CODE_LABEL)	    {		LABEL_REFS (insn) = insn;		/* Any label that cannot be deleted		   is considered to start a reachable block.  */		if (LABEL_PRESERVE_P (insn))		  block_live[i] = 1;	      }	}      else if (GET_RTX_CLASS (code) == 'i')	{	  basic_block_end[i] = insn;	  basic_block_loop_depth[i] = depth;	}      if (GET_RTX_CLASS (code) == 'i')	{	  /* Make a list of all labels referred to other than by jumps.  */	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))	    if (REG_NOTE_KIND (note) == REG_LABEL)	      label_value_list = gen_rtx (EXPR_LIST, VOIDmode, XEXP (note, 0),					  label_value_list);	}      BLOCK_NUM (insn) = i;      if (code != NOTE)	prev_code = code;    }  /* During the second pass, `n_basic_blocks' is only an upper bound.     Only perform the sanity check for the first pass, and on the second     pass ensure `n_basic_blocks' is set to the correct value.  */  if (pass == 1 && i + 1 != n_basic_blocks)    abort ();  n_basic_blocks = i + 1;  for (x = forced_labels; x; x = XEXP (x, 1))    if (! LABEL_REF_NONLOCAL_P (x))      block_live[BLOCK_NUM (XEXP (x, 0))] = 1;  for (x = exception_handler_labels; x; x = XEXP (x, 1))    block_live[BLOCK_NUM (XEXP (x, 0))] = 1;  /* Record which basic blocks control can drop in to.  */  for (i = 0; i < n_basic_blocks; i++)    {      for (insn = PREV_INSN (basic_block_head[i]);	   insn && GET_CODE (insn) == NOTE; insn = PREV_INSN (insn))	;      basic_block_drops_in[i] = insn && GET_CODE (insn) != BARRIER;    }  /* Now find which basic blocks can actually be reached     and put all jump insns' LABEL_REFS onto the ref-chains     of their target labels.  */  if (n_basic_blocks > 0)    {      int something_marked = 1;      int deleted;      /* Find all indirect jump insns and mark them as possibly jumping to all	 the labels whose addresses are explicitly used.  This is because,	 when there are computed gotos, we can't tell which labels they jump	 to, of all the possibilities.  */      for (insn = f; insn; insn = NEXT_INSN (insn))	if (computed_jump_p (insn))	  {	    if (label_value_list_marked_live == 0)	      {		label_value_list_marked_live = 1;		/* This could be made smarter by only considering		   these live, if the computed goto is live.  */		/* Don't delete the labels (in this function) that		   are referenced by non-jump instructions.  */		for (x = label_value_list; x; x = XEXP (x, 1))		  if (! LABEL_REF_NONLOCAL_P (x))		    block_live[BLOCK_NUM (XEXP (x, 0))] = 1;	      }	    for (x = label_value_list; x; x = XEXP (x, 1))	      mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),			      insn, 0);	    for (x = forced_labels; x; x = XEXP (x, 1))	      mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),			      insn, 0);	  }      /* Find all call insns and mark them as possibly jumping	 to all the nonlocal goto handler labels.  */      for (insn = f; insn; insn = NEXT_INSN (insn))	if (GET_CODE (insn) == CALL_INSN	    && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))	  {	    for (x = nonlocal_label_list; x; x = XEXP (x, 1))	      mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),			      insn, 0);	    /* ??? This could be made smarter:	       in some cases it's possible to tell that certain	       calls will not do a nonlocal goto.	       For example, if the nested functions that do the	       nonlocal gotos do not have their addresses taken, then	       only calls to those functions or to other nested	       functions that use them could possibly do nonlocal	       gotos.  */	  }      /* All blocks associated with labels in label_value_list are	 trivially considered as marked live, if the list is empty.	 We do this to speed up the below code.  */      if (label_value_list == 0)	label_value_list_marked_live = 1;      /* Pass over all blocks, marking each block that is reachable	 and has not yet been marked.	 Keep doing this until, in one pass, no blocks have been marked.	 Then blocks_live and blocks_marked are identical and correct.	 In addition, all jumps actually reachable have been marked.  */      while (something_marked)	{	  something_marked = 0;	  for (i = 0; i < n_basic_blocks; i++)	    if (block_live[i] && !block_marked[i])	      {		block_marked[i] = 1;		something_marked = 1;		if (i + 1 < n_basic_blocks && basic_block_drops_in[i + 1])		  block_live[i + 1] = 1;		insn = basic_block_end[i];		if (GET_CODE (insn) == JUMP_INSN)		  mark_label_ref (PATTERN (insn), insn, 0);		if (label_value_list_marked_live == 0)		  /* Now that we know that this block is live, mark as		     live, all the blocks that we might be able to get		     to as live.  */		  for (insn = basic_block_head[i];		       insn != NEXT_INSN (basic_block_end[i]);		       insn = NEXT_INSN (insn))		    {		      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')			{			  for (note = REG_NOTES (insn);			       note;			       note = XEXP (note, 1))			    if (REG_NOTE_KIND (note) == REG_LABEL)			      {				x = XEXP (note, 0);				block_live[BLOCK_NUM (x)] = 1;			      }			}		    }	      }	}      /* ??? See if we have a "live" basic block that is not reachable.	 This can happen if it is headed by a label that is preserved or	 in one of the label lists, but no call or computed jump is in	 the loop.  It's not clear if we can delete the block or not,	 but don't for now.  However, we will mess up register status if	 it remains unreachable, so add a fake reachability from the	 previous block.  */      for (i = 1; i < n_basic_blocks; i++)	if (block_live[i] && ! basic_block_drops_in[i]	    && GET_CODE (basic_block_head[i]) == CODE_LABEL	    && LABEL_REFS (basic_block_head[i]) == basic_block_head[i])	  basic_block_drops_in[i] = 1;      /* Now delete the code for any basic blocks that can't be reached.	 They can occur because jump_optimize does not recognize	 unreachable loops as unreachable.  */      deleted = 0;      for (i = 0; i < n_basic_blocks; i++)	if (!block_live[i])	  {	    deleted++;	    /* Delete the insns in a (non-live) block.  We physically delete	       every non-note insn except the start and end (so	       basic_block_head/end needn't be updated), we turn the latter	       into NOTE_INSN_DELETED notes.	       We use to "delete" the insns by turning them into notes, but	       we may be deleting lots of insns that subsequent passes would	       otherwise have to process.  Secondly, lots of deleted blocks in	       a row can really slow down propagate_block since it will	       otherwise process insn-turned-notes multiple times when it	       looks for loop begin/end notes.  */	    if (basic_block_head[i] != basic_block_end[i])	      {		/* It would be quicker to delete all of these with a single		   unchaining, rather than one at a time, but we need to keep		   the NOTE's.  */		insn = NEXT_INSN (basic_block_head[i]);		while (insn != basic_block_end[i])		  {		    if (GET_CODE (insn) == BARRIER)		      abort ();		    else if (GET_CODE (insn) != NOTE)		      insn = flow_delete_insn (insn);		    else		      insn = NEXT_INSN (insn);		  }	      }	    insn = basic_block_head[i];	    if (GET_CODE (insn) != NOTE)	      {		/* Turn the head into a deleted insn note.  */		if (GET_CODE (insn) == BARRIER)		  abort ();		PUT_CODE (insn, NOTE);		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;	      }	    insn = basic_block_end[i];	    if (GET_CODE (insn) != NOTE)	      {		/* Turn the tail into a deleted insn note.  */		if (GET_CODE (insn) == BARRIER)		  abort ();		PUT_CODE (insn, NOTE);		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;	      }	    /* BARRIERs are between basic blocks, not part of one.	       Delete a BARRIER if the preceding jump is deleted.	       We cannot alter a BARRIER into a NOTE	       because it is too short; but we can really delete	       it because it is not part of a basic block.  */	    if (NEXT_INSN (insn) != 0		&& GET_CODE (NEXT_INSN (insn)) == BARRIER)	      delete_insn (NEXT_INSN (insn));	    /* Each time we delete some basic blocks,	       see if there is a jump around them that is	       being turned into a no-op.  If so, delete it.  */	    if (block_live[i - 1])	      {		register int j;		for (j = i + 1; j < n_basic_blocks; j++)		  if (block_live[j])		    {		      rtx label;		      insn = basic_block_end[i - 1];		      if (GET_CODE (insn) == JUMP_INSN			  /* An unconditional jump is the only possibility			     we must check for, since a conditional one			     would make these blocks live.  */			  && simplejump_p (insn)			  && (label = XEXP (SET_SRC (PATTERN (insn)), 0), 1)			  && INSN_UID (label) != 0			  && BLOCK_NUM (label) == j)			{			  PUT_CODE (insn, NOTE);			  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;			  NOTE_SOURCE_FILE (insn) = 0;			  if (GET_CODE (NEXT_INSN (insn)) != BARRIER)			    abort ();			  delete_insn (NEXT_INSN (insn));			}		      break;		    }	      }	  }      /* There are pathological cases where one function calling hundreds of	 nested inline functions can generate lots and lots of unreachable	 blocks that jump can't delete.  Since we don't use sparse matrices	 a lot of memory will be needed to compile such functions.	 Implementing sparse matrices is a fair bit of work and it is not	 clear that they win more than they lose (we don't want to	 unnecessarily slow down compilation of normal code).  By making	 another pass for the pathological case, we can greatly speed up	 their compilation without hurting normal code.  This works because	 all the insns in the unreachable blocks have either been deleted or	 turned into notes.	 Note that we're talking about reducing memory usage by 10's of	 megabytes and reducing compilation time by several minutes.  */      /* ??? The choice of when to make another pass is a bit arbitrary,	 and was derived from empirical data.  */      if (pass == 1	  && deleted > 200)	{	  pass++;	  n_basic_blocks -= deleted;	  /* `n_basic_blocks' may not be correct at this point: two previously	     separate blocks may now be merged.  That's ok though as we	     recalculate it during the second pass.  It certainly can't be	     any larger than the current value.  */	  goto restart;	}    }}/* Subroutines of find_basic_blocks.  *//* Check expression X for label references;   if one is found, add INSN to the label's chain of references.   CHECKDUP means check for and avoid creating duplicate references   from the same insn.  Such duplicates do no serious harm but   can slow life analysis.  CHECKDUP is set only when duplicates   are likely.  */static voidmark_label_ref (x, insn, checkdup)     rtx x, insn;     int checkdup;{  register RTX_CODE code;  register int i;  register char *fmt;  /* We can be called with NULL when scanning label_value_list.  */  if (x == 0)    return;  code = GET_CODE (x);  if (code == LABEL_REF)    {      register rtx label = XEXP (x, 0);      register rtx y;      if (GET_CODE (label) != CODE_LABEL)	abort ();      /* If the label was never emitted, this insn is junk,	 but avoid a crash trying to refer to BLOCK_NUM (label).	 This can happen as a result of a syntax error	 and a diagnostic has already been printed.  */      if (INSN_UID (label) == 0)	return;      CONTAINING_INSN (x) = insn;      /* if CHECKDUP is set, check for duplicate ref from same insn	 and don't insert.  */      if (checkdup)	for (y = LABEL_REFS (label); y != label; y = LABEL_NEXTREF (y))	  if (CONTAINING_INSN (y) == insn)	    return;      LABEL_NEXTREF (x) = LABEL_REFS (label);      LABEL_REFS (label) = x;      block_live_static[BLOCK_NUM (label)] = 1;      return;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	mark_label_ref (XEXP (x, i), insn, 0);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    mark_label_ref (XVECEXP (x, i, j), insn, 1);	}    }}

⌨️ 快捷键说明

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