diff options
| -rw-r--r-- | gcc/ChangeLog | 20 | ||||
| -rw-r--r-- | gcc/basic-block.h | 1 | ||||
| -rw-r--r-- | gcc/flow.c | 122 | ||||
| -rw-r--r-- | gcc/toplev.c | 2 | 
4 files changed, 113 insertions, 32 deletions
| diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 30db51b..010e14c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Wed Jul 25 01:41:27 CEST 2001  Jan Hubicka  <jh@suse.cz> + +	* flow.c (try_simplify_condjump): Avoid duplicated edges. +	(verify_flow_info): Check for duplicated edges; clarify +	error reporting. + +	* flow.c (block_label): Update basic_block_for_insn. +	(commit_edge_insertions): Call compute_bb_for_insn. + +	* flow.c (purge_dead_edges): Handle conditional jumps and conditional +	returns too. + +	* flow.c (redirect_edge_and_branch, +	try_optimize_cfg): Use redirect_edge_succ_nodup +	(redirect_edge_succ_nodup): New. +	* basic_block.h (redirect_edge_succ_nodup): Declare. + +	* toplev.c (rest_of_compilation): Rebuild CFG before cfg_cleanup +	after gcse. +  Wed Jul 25 00:32:49 CEST 2001  Jan Hubicka  <jh@suse.cz>  	* flow.c (try_forward_edges): Accept fallthru edge; Update comment. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index b6e8c11..c069ad5 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -296,6 +296,7 @@ extern void make_edge			PARAMS ((sbitmap *, basic_block,  						 basic_block, int));  extern void remove_edge			PARAMS ((edge));  extern void redirect_edge_succ		PARAMS ((edge, basic_block)); +extern void redirect_edge_succ_nodup	PARAMS ((edge, basic_block));  extern void redirect_edge_pred		PARAMS ((edge, basic_block));  extern void create_basic_block		PARAMS ((int, rtx, rtx, rtx));  extern int flow_delete_block		PARAMS ((basic_block)); @@ -1592,7 +1592,11 @@ block_label (block)    if (block == EXIT_BLOCK_PTR)      return NULL_RTX;    if (GET_CODE (block->head) != CODE_LABEL) -    block->head = emit_label_before (gen_label_rtx (), block->head); +    { +      block->head = emit_label_before (gen_label_rtx (), block->head); +      if (basic_block_for_insn) +	set_block_for_insn (block->head, block); +    }    return block->head;  } @@ -1834,22 +1838,7 @@ redirect_edge_and_branch (e, target)      fprintf (rtl_dump_file, "Edge %i->%i redirected to %i\n",  	     e->src->index, e->dest->index, target->index);    if (e->dest != target) -    { -      edge s; -      /* Check whether the edge is already present.  */ -      for (s = src->succ; s; s=s->succ_next) -	if (s->dest == target) -	  break; -      if (s) -	{ -	  s->flags |= e->flags; -	  s->probability += e->probability; -	  s->count += e->count; -	  remove_edge (e); -	} -      else -	redirect_edge_succ (e, target); -    } +    redirect_edge_succ_nodup (e, target);    return true;  } @@ -2293,6 +2282,7 @@ commit_edge_insertions ()  {    int i;    basic_block bb; +  compute_bb_for_insn (get_max_uid ());  #ifdef ENABLE_CHECKING    verify_flow_info (); @@ -3076,8 +3066,8 @@ try_simplify_condjump (cbranch_block)    /* Success.  Update the CFG to match.  Note that after this point       the edge variable names appear backwards; the redirection is done       this way to preserve edge profile data.  */ -  redirect_edge_succ (cbranch_jump_edge, cbranch_dest_block); -  redirect_edge_succ (cbranch_fallthru_edge, jump_dest_block); +  redirect_edge_succ_nodup (cbranch_jump_edge, cbranch_dest_block); +  redirect_edge_succ_nodup (cbranch_fallthru_edge, jump_dest_block);    cbranch_jump_edge->flags |= EDGE_FALLTHRU;    cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU; @@ -3820,7 +3810,7 @@ try_optimize_cfg (mode)  		fprintf (rtl_dump_file, "Deleting fallthru block %i.\n",  			 b->index);  	      c = BASIC_BLOCK (b->index ? b->index - 1 : 1); -	      redirect_edge_succ (b->pred, b->succ->dest); +	      redirect_edge_succ_nodup (b->pred, b->succ->dest);  	      flow_delete_block (b);  	      changed = true;  	      b = c; @@ -7979,11 +7969,13 @@ verify_flow_info ()    const int max_uid = get_max_uid ();    const rtx rtx_first = get_insns ();    rtx last_head = get_last_insn (); -  basic_block *bb_info; +  basic_block *bb_info, *last_visited;    rtx x;    int i, last_bb_num_seen, num_bb_notes, err = 0;    bb_info = (basic_block *) xcalloc (max_uid, sizeof (basic_block)); +  last_visited = (basic_block *) xcalloc (n_basic_blocks + 2, +					  sizeof (basic_block));    for (i = n_basic_blocks - 1; i >= 0; i--)      { @@ -8040,6 +8032,14 @@ verify_flow_info ()        e = bb->succ;        while (e)  	{ +	  if (last_visited [e->dest->index + 2] == bb) +	    { +	      error ("verify_flow_info: Duplicate edge %i->%i", +		     e->src->index, e->dest->index); +	      err = 1; +	    } +	  last_visited [e->dest->index + 2] = bb; +  	  if ((e->flags & EDGE_FALLTHRU)  	      && e->src != ENTRY_BLOCK_PTR  	      && e->dest != EXIT_BLOCK_PTR @@ -8166,8 +8166,7 @@ verify_flow_info ()  	  basic_block bb = NOTE_BASIC_BLOCK (x);  	  num_bb_notes++;  	  if (bb->index != last_bb_num_seen + 1) -	    /* Basic blocks not numbered consecutively.  */ -	    abort (); +	    internal_error ("Basic blocks not numbered consecutively.");  	  last_bb_num_seen = bb->index;  	} @@ -8213,10 +8212,11 @@ verify_flow_info ()         num_bb_notes, n_basic_blocks);    if (err) -    abort (); +    internal_error ("verify_flow_info failed.");    /* Clean up.  */    free (bb_info); +  free (last_visited);  }  /* Functions to access an edge list with a vector representation. @@ -8629,6 +8629,29 @@ redirect_edge_succ (e, new_succ)    e->dest = new_succ;  } +/* Like previous but avoid possible dupplicate edge.  */ + +void +redirect_edge_succ_nodup (e, new_succ) +     edge e; +     basic_block new_succ; +{ +  edge s; +  /* Check whether the edge is already present.  */ +  for (s = e->src->succ; s; s = s->succ_next) +    if (s->dest == new_succ && s != e) +      break; +  if (s) +    { +      s->flags |= e->flags; +      s->probability += e->probability; +      s->count += e->count; +      remove_edge (e); +    } +  else +    redirect_edge_succ (e, new_succ); +} +  /* Redirect an edge's predecessor from one block to another.  */  void @@ -9794,21 +9817,56 @@ purge_dead_edges (bb)      return;    if (GET_CODE (insn) == JUMP_INSN)      { +      int removed = 0; +      rtx note; +      edge b,f; +      /* We do care only about conditional jumps and simplejumps.  */ +      if (!any_condjump_p (insn) +	  && !returnjump_p (insn) +	  && !simplejump_p (insn)) +	return;        for (e = bb->succ; e; e = next)  	{  	  next = e->succ_next; -	  if (e->dest == EXIT_BLOCK_PTR || e->dest->head != JUMP_LABEL (insn)) -	    remove_edge (e); + +	  /* Check purposes we can have edge.  */ +	  if ((e->flags & EDGE_FALLTHRU) +	      && any_condjump_p (insn)) +	    continue; +	  if (e->dest != EXIT_BLOCK_PTR +	      && e->dest->head == JUMP_LABEL (insn)) +	    continue; +	  if (e->dest == EXIT_BLOCK_PTR +	      && returnjump_p (insn)) +	    continue; +	  removed = 1; +	  remove_edge (e);  	} -      if (bb->succ && bb->succ->succ_next) -	abort (); -      if (!bb->succ) +      if (!bb->succ || !removed)  	return; -      bb->succ->probability = REG_BR_PROB_BASE; -      bb->succ->count = bb->count; -        if (rtl_dump_file)  	fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index); +      if (!optimize) +	return; + +      /* Redistribute probabilities.  */ +      if (!bb->succ->succ_next) +	{ +	  bb->succ->probability = REG_BR_PROB_BASE; +	  bb->succ->count = bb->count; +        } +      else +	{ +	  note = find_reg_note (insn, REG_BR_PROB, NULL); +	  if (!note) +	    return; +	  b = BRANCH_EDGE (bb); +	  f = FALLTHRU_EDGE (bb); +	  b->probability = INTVAL (XEXP (note, 0)); +	  f->probability = REG_BR_PROB_BASE - b->probability; +	  b->count = bb->count * b->probability / REG_BR_PROB_BASE; +	  f->count = bb->count * f->probability / REG_BR_PROB_BASE; +	}        return;      }    /* If we don't see a jump insn, we don't know exactly why the block would diff --git a/gcc/toplev.c b/gcc/toplev.c index a7bd5e3..02bb24a 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3060,6 +3060,8 @@ rest_of_compilation (decl)  	  tem = tem2 = 0;  	  timevar_push (TV_JUMP);  	  rebuild_jump_labels (insns); +	  delete_trivially_dead_insns (insns, max_reg_num (), 0); +	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);  	  cleanup_cfg (CLEANUP_EXPENSIVE);  	  timevar_pop (TV_JUMP); | 
