[tree-ssa] Variety of small changes.

Andrew MacLeod amacleod@redhat.com
Mon Jun 16 18:11:00 GMT 2003



Here's a bunch of small changes which I think ought to be checked in.

I've exposed the insert_on_edge commiter to allow on demand
insert_on_edge. Dan was trying to use it in PRE, and in order to do so
successfully, you need to know certain things the edge inserter did,
such as create new blocks, or insert before/after a stmt (Its container
may have changed). So the new routine now communicates this info.

I switched the last DCe fix to use sparse bitmaps, per Diegos request.

Most of the rest are debugging aids.

They have all bootstraped an caused no regressions on x86.

OK?
Andrew

	* tree-cfg.c (find_insert_location): Check for control_altering stmts,
	and abort if its an unrecognized BB ending stmt.
	(bsi_commit_first_edge_insert): Rename to bsi_insert_on_edge_immediate,
	externalize, and change the interface to an on-demand inserter.
	(bsi_commit_edge_inserts): Call bsi_insert_on_edge_immediate().
	* tree-flow.h (bsi_insert_on_edge_immediate): Prototype.
	* tree-pretty-print.c (dump_block_info): Add 'ab' for abnormal edges.
	* tree-ssa-dce.c (process_worklist): Use sparse bitmaps.
	* tree-ssa-live.c (calculate_live_on_entry): Abort if ssa_name has a
	definition, but is also live on entry.
	* tree-ssa.c (coalesce_ssa_name): Call abort() instead of error(), and
	provide more detailed info.
	(rewrite_out_of_ssa): Provide CFG dumps before and after rewritting.


Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.108
diff -c -p -r1.1.4.108 tree-cfg.c
*** tree-cfg.c	14 Jun 2003 20:56:00 -0000	1.1.4.108
--- tree-cfg.c	16 Jun 2003 17:57:03 -0000
*************** static inline void bsi_update_from_tsi
*** 139,145 ****
  		(block_stmt_iterator *, tree_stmt_iterator);
  static tree_stmt_iterator bsi_link_after
  		(tree_stmt_iterator *, tree, basic_block, tree);
- static block_stmt_iterator bsi_commit_first_edge_insert (edge, tree);
  
  /* Values returned by location parameter of find_insert_location.  */
  
--- 139,144 ----
*************** bsi_insert_before (block_stmt_iterator *
*** 3566,3572 ****
     edges to be redirected.  
  
     Note that upon entry to this function, src is *not* the switch stmt's block
!    any more. commit_one_edge_insertion() has already split the edge from
     src->dest, so we have   original_src -> src -> dest. This new src block 
     is currently empty. 
     
--- 3565,3571 ----
     edges to be redirected.  
  
     Note that upon entry to this function, src is *not* the switch stmt's block
!    any more. bsi_insert_on_edge_immediate() has already split the edge from
     src->dest, so we have   original_src -> src -> dest. This new src block 
     is currently empty. 
     
*************** find_insert_location (basic_block src, b
*** 3795,3802 ****
  	    break;
  
  	  default:
! 	    ret = dest->head_tree_p;
! 	    break;
  	}
      }
    else
--- 3794,3812 ----
  	    break;
  
  	  default:
! 	    if (is_ctrl_altering_stmt (stmt))
! 	      {
! 	        /* The block ends in a CALL or something else which likely has
! 		   abnormal edges.  In that case, we simple create a new block
! 		   right after this one, and then fall through to the 
! 		   destination  block.  */
! 		ret = handle_switch_split (new_block, dest);
! 		*location = EDGE_INSERT_LOCATION_AFTER;
! 		break;
! 	      }
! 
! 	    /* All cases ought to have been covered by now.  */
! 	    abort ();
  	}
      }
    else
*************** find_insert_location (basic_block src, b
*** 3808,3817 ****
  /* This routine inserts a stmt on an edge. Every attempt is made to place the
     stmt in an existing basic block, but sometimes that isn't possible.  When
     it isn't possible, a new basic block is created, edges updated, and the 
!    stmt is added to the new block.  An iterator to the new stmt is returned.  */
! 
! static block_stmt_iterator 
! bsi_commit_first_edge_insert (edge e, tree stmt)
  {
    basic_block src, dest, new_bb;
    block_stmt_iterator bsi, tmp;
--- 3818,3833 ----
  /* This routine inserts a stmt on an edge. Every attempt is made to place the
     stmt in an existing basic block, but sometimes that isn't possible.  When
     it isn't possible, a new basic block is created, edges updated, and the 
!    stmt is added to the new block.  An iterator to the new stmt is returned.
!    If a pointer to a BSI is passed in, and the stmt is inserted before or after
!    an existing stmt in a block, old_bsi will be returned with an iterator for
!    that stmt (The equivilent of BSI_SAME_STMT on an insert_before or after.
!    If a created_block is passed in, and the edge is split, the new block is
!    returned through this parameter.  */
! 
! block_stmt_iterator 
! bsi_insert_on_edge_immediate (edge e, tree stmt, block_stmt_iterator *old_bsi,
! 			      basic_block *created_block)
  {
    basic_block src, dest, new_bb;
    block_stmt_iterator bsi, tmp;
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3822,3827 ****
--- 3838,3848 ----
    bb_ann_t ann;
    edge e2;
  
+   if (old_bsi)
+     old_bsi->tp = (tree *)NULL;
+   if (created_block)
+     *created_block = (basic_block)NULL;
+ 
    first = last = NULL_TREE;
    src = e->src;
    dest = e->dest;
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3830,3835 ****
--- 3851,3860 ----
    if (e->flags & EDGE_ABNORMAL)
      abort ();
  
+   /* No immediate edge insertion if there are already pending inserts.  */
+   if (PENDING_STMT (e))
+     abort ();
+ 
    num_exit = num_entry = 0;
  
    /* Multiple successors on abnormal edges do not cause an edge to be split. 
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3851,3877 ****
        /* If it is an empty block, simply insert after this bsi, and the new stmt
  	 will become the only stmt in the block.  */
        if (bsi_end_p (bsi))
!         {
  	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
!         }
  
        last = bsi_stmt (bsi);
  
        /* If the last stmt isn't a control altering stmt, then we can simply
!          append this stmt to the basic block. This should mean the edge is
  	 a fallthrough edge.  */
  
        if (!is_ctrl_stmt (last) && !is_ctrl_altering_stmt (last))
  	{
! 	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
  	}
  
        /* If the last stmt is a GOTO, the we can simply insert before it.  */
        if (TREE_CODE (last) == GOTO_EXPR || TREE_CODE (last) == LOOP_EXPR)
!         {
  	  bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
  	}
      }
--- 3876,3910 ----
        /* If it is an empty block, simply insert after this bsi, and the new stmt
  	 will become the only stmt in the block.  */
        if (bsi_end_p (bsi))
! 	{
  	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
! 	}
  
        last = bsi_stmt (bsi);
  
        /* If the last stmt isn't a control altering stmt, then we can simply
! 	 append this stmt to the basic block. This should mean the edge is
  	 a fallthrough edge.  */
  
        if (!is_ctrl_stmt (last) && !is_ctrl_altering_stmt (last))
  	{
! 	  bsi_insert_after (&bsi, stmt, BSI_SAME_STMT);
! 	  if (old_bsi)
! 	    *old_bsi = bsi;
! 	  bsi_next (&bsi);
  	  return bsi;
  	}
  
        /* If the last stmt is a GOTO, the we can simply insert before it.  */
        if (TREE_CODE (last) == GOTO_EXPR || TREE_CODE (last) == LOOP_EXPR)
! 	{
  	  bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ 	  if (old_bsi)
+ 	    {
+ 	      *old_bsi = bsi;
+ 	      bsi_next (old_bsi);
+ 	    }
  	  return bsi;
  	}
      }
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3885,3900 ****
        /* If it is an empty block, simply insert after this bsi, and the new stmt
  	 will become the only stmt in the block.  */
        if (bsi_end_p (bsi))
!         {
  	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
!         }
  
        /* If the first stmt isnt a label, insert before it.  */
        first = bsi_stmt (bsi);
        if (!is_label_stmt (first))
!         {
  	  bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
  	}
  
--- 3918,3938 ----
        /* If it is an empty block, simply insert after this bsi, and the new stmt
  	 will become the only stmt in the block.  */
        if (bsi_end_p (bsi))
! 	{
  	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
  	  return bsi;
! 	}
  
        /* If the first stmt isnt a label, insert before it.  */
        first = bsi_stmt (bsi);
        if (!is_label_stmt (first))
! 	{
  	  bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ 	  if (old_bsi)
+ 	    {
+ 	      *old_bsi = bsi;
+ 	      bsi_next (old_bsi);
+ 	    }
  	  return bsi;
  	}
  
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3904,3917 ****
  	  if (!is_label_stmt (bsi_stmt (bsi)))
  	    {
  	      bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
  	      return bsi;
  	    }
  	  tmp = bsi;
  	}
!         
        /* If this point is reached, then the block consists of nothing but 
  	 labels, and tmp points to the last one. Insert after it.  */
!       bsi_insert_after (&tmp, stmt, BSI_NEW_STMT);
        return tmp;
      }
  
--- 3942,3963 ----
  	  if (!is_label_stmt (bsi_stmt (bsi)))
  	    {
  	      bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+ 	      if (old_bsi)
+ 		{
+ 		  *old_bsi = bsi;
+ 		  bsi_next (old_bsi);
+ 		}
  	      return bsi;
  	    }
  	  tmp = bsi;
  	}
! 
        /* If this point is reached, then the block consists of nothing but 
  	 labels, and tmp points to the last one. Insert after it.  */
!       bsi_insert_after (&tmp, stmt, BSI_SAME_STMT);
!       if (old_bsi)
! 	*old_bsi = tmp;
!       bsi_next (&tmp);
        return tmp;
      }
  
*************** bsi_commit_first_edge_insert (edge e, tr
*** 3922,3927 ****
--- 3968,3976 ----
    ann->ephi_nodes = NULL_TREE;
    ann->dom_children = (bitmap) NULL;
  
+   if (created_block)
+     *created_block = new_bb;
+ 
    tsi = find_insert_location (src, dest, new_bb, &location);
    parent = parent_stmt (tsi_stmt (tsi));
  
*************** bsi_commit_edge_inserts (int update_anno
*** 4010,4016 ****
  	    SET_PENDING_STMT (e, NULL_TREE);
  	    next_stmt = TREE_CHAIN (stmt);
  	    /* The first insert will create a new basic block if needed.  */
! 	    ret = bsi = bsi_commit_first_edge_insert (e, stmt);
  	    count++;
  	    stmt = next_stmt;
  	    for ( ; stmt; stmt = next_stmt)
--- 4059,4065 ----
  	    SET_PENDING_STMT (e, NULL_TREE);
  	    next_stmt = TREE_CHAIN (stmt);
  	    /* The first insert will create a new basic block if needed.  */
! 	    ret = bsi = bsi_insert_on_edge_immediate (e, stmt, NULL, NULL);
  	    count++;
  	    stmt = next_stmt;
  	    for ( ; stmt; stmt = next_stmt)
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.83
diff -c -p -r1.1.4.83 tree-flow.h
*** tree-flow.h	11 Jun 2003 12:41:21 -0000	1.1.4.83
--- tree-flow.h	16 Jun 2003 17:57:03 -0000
*************** extern void bsi_insert_before	PARAMS ((b
*** 337,342 ****
--- 337,345 ----
  extern void bsi_insert_after	PARAMS ((block_stmt_iterator *, tree, enum bsi_iterator_update));
  extern void bsi_insert_on_edge	PARAMS ((edge, tree));
  extern int bsi_commit_edge_inserts	PARAMS ((int, int *));
+ extern block_stmt_iterator bsi_insert_on_edge_immediate	
+ 		PARAMS ((edge, tree, block_stmt_iterator *, basic_block *));
+ 
  extern void bsi_replace		PARAMS ((block_stmt_iterator, tree));
  
  /* Stmt list insertion routines.  */
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.29
diff -c -p -r1.1.2.29 tree-pretty-print.c
*** tree-pretty-print.c	3 Jun 2003 16:50:52 -0000	1.1.2.29
--- tree-pretty-print.c	16 Jun 2003 17:57:04 -0000
*************** dump_block_info (buffer, bb, spc)
*** 1969,1980 ****
        output_add_string (buffer, ".  PRED:");
        for (e = bb->pred; e; e = e->pred_next)
  	if (e->src)
! 	  output_formatted_scalar (buffer, " %d", e->src->index);
  
        output_add_string (buffer, ".  SUCC:");
        for (e = bb->succ; e; e = e->succ_next)
  	if (e->dest)
! 	  output_formatted_scalar (buffer, " %d", e->dest->index);
  
        output_add_character (buffer, '.');
  
--- 1969,1988 ----
        output_add_string (buffer, ".  PRED:");
        for (e = bb->pred; e; e = e->pred_next)
  	if (e->src)
! 	  {
! 	    output_formatted_scalar (buffer, " %d", e->src->index);
! 	    if (e->flags & EDGE_ABNORMAL)
! 	      output_add_string (buffer, "(ab)");
! 	  }
  
        output_add_string (buffer, ".  SUCC:");
        for (e = bb->succ; e; e = e->succ_next)
  	if (e->dest)
! 	  {
! 	    output_formatted_scalar (buffer, " %d", e->dest->index);
! 	    if (e->flags & EDGE_ABNORMAL)
! 	      output_add_string (buffer, "(ab)");
! 	  }
  
        output_add_character (buffer, '.');
  
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.42
diff -c -p -r1.1.2.42 tree-ssa-dce.c
*** tree-ssa-dce.c	13 Jun 2003 18:14:16 -0000	1.1.2.42
--- tree-ssa-dce.c	16 Jun 2003 17:57:04 -0000
*************** process_worklist (void)
*** 318,329 ****
    basic_block bb;
    tree i, j;
    edge e;
!   sbitmap cond_checked, goto_checked;
  
!   cond_checked = sbitmap_alloc (n_basic_blocks);
!   goto_checked = sbitmap_alloc (n_basic_blocks);
!   sbitmap_zero (cond_checked);
!   sbitmap_zero (goto_checked);
  
    while (VARRAY_ACTIVE_SIZE (worklist) > 0)
      {
--- 318,327 ----
    basic_block bb;
    tree i, j;
    edge e;
!   bitmap cond_checked, goto_checked;
  
!   cond_checked = BITMAP_XMALLOC ();
!   goto_checked = BITMAP_XMALLOC ();
  
    while (VARRAY_ACTIVE_SIZE (worklist) > 0)
      {
*************** process_worklist (void)
*** 342,350 ****
  	 as necessary since it is control flow.  A block's predecessors only
  	 need to be checked once.  */
        bb = bb_for_stmt (i);
!       if (bb && !TEST_BIT (goto_checked, bb->index))
          {
! 	  SET_BIT (goto_checked, bb->index);
  	  for (e = bb->pred; e != NULL; e = e->pred_next)
  	    {
  	      basic_block p = e->src;
--- 340,348 ----
  	 as necessary since it is control flow.  A block's predecessors only
  	 need to be checked once.  */
        bb = bb_for_stmt (i);
!       if (bb && !bitmap_bit_p (goto_checked, bb->index))
          {
! 	  bitmap_set_bit (goto_checked, bb->index);
  	  for (e = bb->pred; e != NULL; e = e->pred_next)
  	    {
  	      basic_block p = e->src;
*************** process_worklist (void)
*** 371,379 ****
  	     This only needs to be done once per block.  */
  
  	  k = bb_for_stmt (i)->index;
! 	  if (!TEST_BIT (cond_checked, k))
  	    {
! 	      SET_BIT (cond_checked, k);
  	      for (e = bb->pred; e; e = e->pred_next)
  		{
  		  basic_block pred, par;
--- 369,377 ----
  	     This only needs to be done once per block.  */
  
  	  k = bb_for_stmt (i)->index;
! 	  if (!bitmap_bit_p (cond_checked, k))
  	    {
! 	      bitmap_set_bit (cond_checked, k);
  	      for (e = bb->pred; e; e = e->pred_next)
  		{
  		  basic_block pred, par;
*************** process_worklist (void)
*** 430,437 ****
  	    }
  	}
      }
!   sbitmap_free (cond_checked);
!   sbitmap_free (goto_checked);
  }
  
  
--- 428,435 ----
  	    }
  	}
      }
!   BITMAP_XFREE (cond_checked);
!   BITMAP_XFREE (goto_checked);
  }
  
  
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.c,v
retrieving revision 1.1.2.7
diff -c -p -r1.1.2.7 tree-ssa-live.c
*** tree-ssa-live.c	11 Jun 2003 12:41:21 -0000	1.1.2.7
--- tree-ssa-live.c	16 Jun 2003 17:57:04 -0000
*************** calculate_live_on_entry (var_map map)
*** 545,550 ****
--- 545,571 ----
        live_worklist (live, stack, i);
      });
  
+ #ifdef ENABLE_CHECKING
+    /* Check for live on entry partitions and report those with a DEF in
+       the program. This will typically mean an optimization has done
+       something wrong.  */
+   for (num=0, i = 0; i < num_var_partitions (map); i++)
+     {
+       if (TEST_BIT (live_entry_blocks (live, i), 0))
+         {
+ 	  var = partition_to_var (map, i);
+ 	  if (!IS_EMPTY_STMT (SSA_NAME_DEF_STMT (var)))
+ 	    {
+ 	      num++;
+ 	      print_generic_expr (stderr, var, TDF_SLIM);
+ 	      fprintf (stderr, " is defined, but is also live on entry.");
+ 	    }
+ 	}
+     }
+   if (num > 0)
+     abort ();
+ #endif
+ 
    return live;
  }
  
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.93
diff -c -p -r1.1.4.93 tree-ssa.c
*** tree-ssa.c	13 Jun 2003 19:00:19 -0000	1.1.4.93
--- tree-ssa.c	16 Jun 2003 17:57:06 -0000
*************** coalesce_ssa_name (var_map map)
*** 1365,1371 ****
  		   a copy in the DEST block instead, and use it in the 
  		   PHI node. Adding a new partition/version at this point
  		   is really a bad idea, so for now, PUNT!.  */
! 		error ("Different root vars across an abnormal edge\n");
  	      }
  
  	    if (x != y)
--- 1365,1380 ----
  		   a copy in the DEST block instead, and use it in the 
  		   PHI node. Adding a new partition/version at this point
  		   is really a bad idea, so for now, PUNT!.  */
! 		fprintf (stderr, "\nDifferent root vars '\n");
! 		print_generic_expr (stderr, 
! 				    root_var (rv, find_root_var (rv, x)),
! 				    TDF_SLIM);
! 		fprintf (stderr, "' and '");
! 		print_generic_expr (stderr, 
! 				    root_var (rv, find_root_var (rv, y)),
! 				    TDF_SLIM);
! 		fprintf (stderr, "' across an abnormal edge\n");
! 		abort ();
  	      }
  
  	    if (x != y)
*************** coalesce_ssa_name (var_map map)
*** 1392,1398 ****
  		    conflict_graph_merge_regs (graph, x, y);
  		  }
  		else
! 		  error ("Vars Conflict across an abnormal edge\n");
  	      }
  	  }
  
--- 1401,1418 ----
  		    conflict_graph_merge_regs (graph, x, y);
  		  }
  		else
! 		  {
! 		    fprintf (stderr, "\n");
! 		    print_generic_expr (stderr, 
! 					partition_to_var (map, x), 
! 					TDF_SLIM);
! 		    fprintf (stderr, " and ");
! 		    print_generic_expr (stderr, 
! 					partition_to_var (map, y), 
! 					TDF_SLIM);
! 		    fprintf (stderr, " conflict across an abnormal edge\n");
! 		    abort ();
! 		  }
  	      }
  	  }
  
*************** rewrite_out_of_ssa (tree fndecl)
*** 1560,1565 ****
--- 1580,1588 ----
  
    tree_ssa_dump_file = dump_begin (TDI_optimized, &tree_ssa_dump_flags);
  
+   if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+     dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
+ 
    map = create_ssa_var_map ();
  
    /* Shrink the map to include only referenced variables.  Exclude variables
*************** rewrite_out_of_ssa (tree fndecl)
*** 1651,1656 ****
--- 1674,1682 ----
  
    /* If any copies were inserted on edges, actually insert them now.  */
    bsi_commit_edge_inserts (0, NULL);
+ 
+   if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+     dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */



More information about the Gcc-patches mailing list