This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[debuglocus] PHI source locations


This is the first patch on the debuglocus branch.

It enhances PHI nodes to carry around a source location field which allows out-of-ssa to properly replace the locus field when copies are issued. Previously, we lost a *lot* of locus information here. The cost is an extra word (the source locus field) in each phi argument.

debuglocus requires this change in order to retain the locus field throughout all optimizations, but its probably something that should have been considered at the very beginning.

Before the patch, a simple program like:

void
f2(int a, int b) {
 int x;

 if (a)
   x = b;
 else
   x = 10;
 func(x);
}

would produce lineno info (after optimization and outofssa) like:


<bb 2>: [a.c : 7] if (a != 0) goto <bb 3>; else goto <bb 4>;

<bb 3>:
 x = b;
 goto <bb 5>;

<bb 4>:
 x = 10;

<bb 5>:
 [a.c : 11] func (x); [tail call]
 [a.c : 12] return;

THe information associated with the copies in block 3 and 4 have been lost. With the patch, we get:

<bb 2>:
 [a.c : 7] if (a != 0)
   goto <bb 3>;
 else
   goto <bb 4>;

<bb 3>:
 [a.c : 8] x = b;
 goto <bb 5>;

<bb 4>:
 [a.c : 10] x = 10;

<bb 5>:
 [a.c : 11] func (x); [tail call]
 [a.c : 12] return;

}

Bootstrapped and no regressions on x86_64-unknown-linux-gnu. checked into the debuglocus branch.
Andrew



2009-03-19  Andrew Macleod  <amacleod@redhat.com>

	* tree-into-ssa.c (rewrite_add_phi_arguments): Initialize arg locations.
	* tree.h (struct phi_arg_d): Add location field.
	* tree-phinodes.c (make_phi_node): Initialize phi arg locations.
	* gimple-pretty-print.c (dump_gimple_phi): Dump lineno's.
	* tree-flow-inline.h (gimple_phi_arg_location,
	gimple_phi_arg_set_location, gimple_phi_arg_has_location): New.
	* cfgexpand.c (gimple_assign_rhs_to_tree): Copy location to new expr.
	* tree-ssa-ter.c (dump_replaceable_exprs): Dump expr lineno's.
	(struct _elim_graph): Add location to the copy and edge lists.
	(insert_copy_on_edge): Add location to copy statement.
	(new_elim_graph): Initialize location lists.
	(clear_elim_graph): Clear edge location list.
	(delete_elim_graph): Free location lists.
	(elim_graph_add_edge, elim_graph_remove_succ_edge,
	FOR_EACH_ELIM_GRAPH_SUCC, FOR_EACH_ELIM_GRAPH_PRED, eliminate_build,
	elim_forward, elim_unvisited_predecessor, elim_backward, 
	elim_create): Add location support in elimination graph.
	(eliminate_phi): Add locations to copies generated.
	(insert_backedge_copies): Add locations to copies generated.


Index: tree-into-ssa.c
===================================================================
*** tree-into-ssa.c	(revision 144935)
--- tree-into-ssa.c	(working copy)
*************** rewrite_add_phi_arguments (struct dom_wa
*** 1385,1393 ****
--- 1385,1406 ----
  	   gsi_next (&gsi))
  	{
  	  tree currdef;
+ 	  gimple stmt;
+ 
  	  phi = gsi_stmt (gsi);
  	  currdef = get_reaching_def (SSA_NAME_VAR (gimple_phi_result (phi)));
  	  add_phi_arg (phi, currdef, e);
+ 
+ 	  /* If there is a source location, add it to the phi argument.  */
+ 	  stmt = SSA_NAME_DEF_STMT (currdef);
+ 	  if (gimple_has_location (stmt))
+ 	    {
+ 	      use_operand_p use = PHI_ARG_DEF_PTR_FROM_EDGE(phi, e);
+ 	      int index = PHI_ARG_INDEX_FROM_USE (use);
+ 	      source_location locus = gimple_location (stmt);
+ 
+ 	      gimple_phi_arg_set_location (phi, index, locus);
+ 	    }
  	}
      }
  }
Index: tree.h
===================================================================
*** tree.h	(revision 144935)
--- tree.h	(working copy)
*************** struct phi_arg_d GTY(())
*** 1930,1935 ****
--- 1930,1936 ----
       pointer arithmetic with it.  See phi_arg_index_from_use.  */
    struct ssa_use_operand_d imm_use;
    tree def;
+   location_t locus;
  };
  
  
Index: tree-phinodes.c
===================================================================
*** tree-phinodes.c	(revision 144935)
--- tree-phinodes.c	(working copy)
*************** make_phi_node (tree var, int len)
*** 231,236 ****
--- 231,238 ----
    for (i = 0; i < capacity; i++)
      {
        use_operand_p  imm;
+ 
+       gimple_phi_arg_set_location (phi, i, UNKNOWN_LOCATION);
        imm = gimple_phi_arg_imm_use_ptr (phi, i);
        imm->use = gimple_phi_arg_def_ptr (phi, i);
        imm->prev = NULL;
*************** resize_phi_node (gimple *phi, size_t len
*** 299,304 ****
--- 301,308 ----
    for (i = gimple_phi_num_args (new_phi); i < len; i++)
      {
        use_operand_p imm;
+ 
+       gimple_phi_arg_set_location (new_phi, i, UNKNOWN_LOCATION);
        imm = gimple_phi_arg_imm_use_ptr (new_phi, i);
        imm->use = gimple_phi_arg_def_ptr (new_phi, i);
        imm->prev = NULL;
Index: gimple-pretty-print.c
===================================================================
*** gimple-pretty-print.c	(revision 144935)
--- gimple-pretty-print.c	(working copy)
*************** dump_gimple_phi (pretty_printer *buffer,
*** 1182,1187 ****
--- 1182,1201 ----
        pp_character (buffer, '(');
        pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
        pp_character (buffer, ')');
+       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
+         {
+ 	  expanded_location xloc;
+ 
+ 	  xloc = expand_location (gimple_phi_arg_location (phi, i));
+ 	  pp_character (buffer, '[');
+ 	  if (xloc.file)
+ 	    {
+ 	      pp_string (buffer, xloc.file);
+ 	      pp_string (buffer, " : ");
+ 	    }
+ 	  pp_decimal_int (buffer, xloc.line);
+ 	  pp_string (buffer, "] ");
+ 	}
        if (i < gimple_phi_num_args (phi) - 1)
  	pp_string (buffer, ", ");
      }
Index: tree-flow-inline.h
===================================================================
*** tree-flow-inline.h	(revision 144935)
--- tree-flow-inline.h	(working copy)
*************** gimple_phi_arg_edge (gimple gs, size_t i
*** 526,531 ****
--- 526,556 ----
    return EDGE_PRED (gimple_bb (gs), i);
  }
  
+ /* Return the source location of gimple argument I of phi node GS.  */
+ 
+ static inline source_location
+ gimple_phi_arg_location (gimple gs, size_t i)
+ {
+   return gimple_phi_arg (gs, i)->locus;
+ }
+ 
+ /* Set the source location of gimple argument I of phi node GS to LOC.  */
+ 
+ static inline void
+ gimple_phi_arg_set_location (gimple gs, size_t i, source_location loc)
+ {
+   gimple_phi_arg (gs, i)->locus = loc;
+ }
+ 
+ /* Return TRUE if argument I of phi node GS has a location record.  */
+ 
+ static inline bool
+ gimple_phi_arg_has_location (gimple gs, size_t i)
+ {
+   return gimple_phi_arg_location (gs, i) != UNKNOWN_LOCATION;
+ }
+ 
+ 
  /* Return the PHI nodes for basic block BB, or NULL if there are no
     PHI nodes.  */
  static inline gimple_seq
Index: cfgexpand.c
===================================================================
*** cfgexpand.c	(revision 144935)
--- cfgexpand.c	(working copy)
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 69,74 ****
--- 69,77 ----
    else
      gcc_unreachable ();
  
+   if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t))
+     SET_EXPR_LOCATION (t, gimple_location (stmt));
+ 
    return t;
  }
  
Index: tree-ssa-ter.c
===================================================================
*** tree-ssa-ter.c	(revision 144935)
--- tree-ssa-ter.c	(working copy)
*************** dump_replaceable_exprs (FILE *f, gimple 
*** 688,693 ****
--- 688,704 ----
  	var = ssa_name (x);
  	print_generic_expr (f, var, TDF_SLIM);
  	fprintf (f, " replace with --> ");
+ 	if ((dump_flags & TDF_LINENO) && gimple_has_location (expr[x]))
+ 	  {
+ 	    expanded_location xlc = expand_location (gimple_location (expr[x]));
+ 	    fprintf (f, "[");
+ 	    if (xlc.file)
+ 	      {
+ 		fprintf (f, "%s", xlc.file);
+ 		fprintf (f, " :");
+ 	      }
+ 	    fprintf (f, "%d]", xlc.line);
+ 	  }
  	print_gimple_stmt (f, expr[x], 0, TDF_SLIM);
  	fprintf (f, "\n");
        }
Index: tree-outof-ssa.c
===================================================================
*** tree-outof-ssa.c	(revision 144935)
--- tree-outof-ssa.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 35,40 ****
--- 35,43 ----
  #include "toplev.h"
  
  
+ DEF_VEC_I(source_location);
+ DEF_VEC_ALLOC_I(source_location,heap);
+ 
  /* Used to hold all the components required to do SSA PHI elimination.
     The node and pred/succ list is a simple linear list of nodes and
     edges represented as pairs of nodes.
*************** typedef struct _elim_graph {
*** 66,71 ****
--- 69,77 ----
    /*  The predecessor and successor edge list.  */
    VEC(int,heap) *edge_list;
  
+   /* Source locus on each edge */
+   VEC(source_location,heap) *edge_locus;
+ 
    /* Visited vector.  */
    sbitmap visited;
  
*************** typedef struct _elim_graph {
*** 80,85 ****
--- 86,94 ----
  
    /* List of constant copies to emit.  These are pushed on in pairs.  */
    VEC(tree,heap) *const_copies;
+ 
+   /* Source locations for any constant copies.  */
+   VEC(source_location,heap) *copy_locus;
  } *elim_graph;
  
  
*************** create_temp (tree t)
*** 139,150 ****
     variable DEST on edge E.  */
  
  static void
! insert_copy_on_edge (edge e, tree dest, tree src)
  {
    gimple copy;
  
    copy = gimple_build_assign (dest, src);
    set_is_used (dest);
  
    if (TREE_CODE (src) == ADDR_EXPR)
      src = TREE_OPERAND (src, 0);
--- 148,160 ----
     variable DEST on edge E.  */
  
  static void
! insert_copy_on_edge (edge e, tree dest, tree src, source_location locus)
  {
    gimple copy;
  
    copy = gimple_build_assign (dest, src);
    set_is_used (dest);
+   gimple_set_location (copy, locus);
  
    if (TREE_CODE (src) == ADDR_EXPR)
      src = TREE_OPERAND (src, 0);
*************** new_elim_graph (int size)
*** 175,181 ****
--- 185,193 ----
  
    g->nodes = VEC_alloc (tree, heap, 30);
    g->const_copies = VEC_alloc (tree, heap, 20);
+   g->copy_locus = VEC_alloc (source_location, heap, 10);
    g->edge_list = VEC_alloc (int, heap, 20);
+   g->edge_locus = VEC_alloc (source_location, heap, 10);
    g->stack = VEC_alloc (int, heap, 30);
    
    g->visited = sbitmap_alloc (size);
*************** clear_elim_graph (elim_graph g)
*** 191,196 ****
--- 203,209 ----
  {
    VEC_truncate (tree, g->nodes, 0);
    VEC_truncate (int, g->edge_list, 0);
+   VEC_truncate (source_location, g->edge_locus, 0);
  }
  
  
*************** delete_elim_graph (elim_graph g)
*** 204,209 ****
--- 217,224 ----
    VEC_free (int, heap, g->edge_list);
    VEC_free (tree, heap, g->const_copies);
    VEC_free (tree, heap, g->nodes);
+   VEC_free (source_location, heap, g->copy_locus);
+   VEC_free (source_location, heap, g->edge_locus);
    free (g);
  }
  
*************** elim_graph_add_node (elim_graph g, tree 
*** 235,244 ****
  /* Add the edge PRED->SUCC to graph G.  */
  
  static inline void
! elim_graph_add_edge (elim_graph g, int pred, int succ)
  {
    VEC_safe_push (int, heap, g->edge_list, pred);
    VEC_safe_push (int, heap, g->edge_list, succ);
  }
  
  
--- 250,260 ----
  /* Add the edge PRED->SUCC to graph G.  */
  
  static inline void
! elim_graph_add_edge (elim_graph g, int pred, int succ, source_location locus)
  {
    VEC_safe_push (int, heap, g->edge_list, pred);
    VEC_safe_push (int, heap, g->edge_list, succ);
+   VEC_safe_push (source_location, heap, g->edge_locus, locus);
  }
  
  
*************** elim_graph_add_edge (elim_graph g, int p
*** 246,252 ****
     return the successor node.  -1 is returned if there is no such edge.  */
  
  static inline int
! elim_graph_remove_succ_edge (elim_graph g, int node)
  {
    int y;
    unsigned x;
--- 262,268 ----
     return the successor node.  -1 is returned if there is no such edge.  */
  
  static inline int
! elim_graph_remove_succ_edge (elim_graph g, int node, source_location *locus)
  {
    int y;
    unsigned x;
*************** elim_graph_remove_succ_edge (elim_graph 
*** 256,263 ****
--- 272,282 ----
          VEC_replace (int, g->edge_list, x, -1);
  	y = VEC_index (int, g->edge_list, x + 1);
  	VEC_replace (int, g->edge_list, x + 1, -1);
+ 	*locus = VEC_index (source_location, g->edge_locus, x / 2);
+ 	VEC_replace (source_location, g->edge_locus, x / 2, UNKNOWN_LOCATION);
  	return y;
        }
+   *locus = UNKNOWN_LOCATION;
    return -1;
  }
  
*************** elim_graph_remove_succ_edge (elim_graph 
*** 266,272 ****
     edge list.  VAR will hold the partition number found.  CODE is the
     code fragment executed for every node found.  */
  
! #define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, CODE)		\
  do {									\
    unsigned x_;								\
    int y_;								\
--- 285,291 ----
     edge list.  VAR will hold the partition number found.  CODE is the
     code fragment executed for every node found.  */
  
! #define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, LOCUS, CODE)		\
  do {									\
    unsigned x_;								\
    int y_;								\
*************** do {									\
*** 276,281 ****
--- 295,301 ----
        if (y_ != (NODE))							\
          continue;							\
        (VAR) = VEC_index (int, (GRAPH)->edge_list, x_ + 1);		\
+       (LOCUS) = VEC_index (source_location, (GRAPH)->edge_locus, x_ / 2); \
        CODE;								\
      }									\
  } while (0)
*************** do {									\
*** 285,291 ****
     GRAPH.  VAR will hold the partition number found.  CODE is the
     code fragment executed for every node found.  */
  
! #define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, CODE)		\
  do {									\
    unsigned x_;								\
    int y_;								\
--- 305,311 ----
     GRAPH.  VAR will hold the partition number found.  CODE is the
     code fragment executed for every node found.  */
  
! #define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, LOCUS, CODE)		\
  do {									\
    unsigned x_;								\
    int y_;								\
*************** do {									\
*** 295,300 ****
--- 315,321 ----
        if (y_ != (NODE))							\
          continue;							\
        (VAR) = VEC_index (int, (GRAPH)->edge_list, x_);			\
+       (LOCUS) = VEC_index (source_location, (GRAPH)->edge_locus, x_ / 2); \
        CODE;								\
      }									\
  } while (0)
*************** eliminate_build (elim_graph g, basic_blo
*** 324,329 ****
--- 345,351 ----
    for (gsi = gsi_start_phis (B); !gsi_end_p (gsi); gsi_next (&gsi))
      {
        gimple phi = gsi_stmt (gsi);
+       source_location locus;
  
        T0 = var_to_partition_to_var (g->map, gimple_phi_result (phi));
        
*************** eliminate_build (elim_graph g, basic_blo
*** 332,337 ****
--- 354,360 ----
  	continue;
  
        Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
+       locus = gimple_phi_arg_location (phi, g->e->dest_idx);
  
        /* If this argument is a constant, or a SSA_NAME which is being
  	 left in SSA form, just queue a copy to be emitted on this
*************** eliminate_build (elim_graph g, basic_blo
*** 344,349 ****
--- 367,373 ----
  	     on this edge.  */
  	  VEC_safe_push (tree, heap, g->const_copies, T0);
  	  VEC_safe_push (tree, heap, g->const_copies, Ti);
+ 	  VEC_safe_push (source_location, heap, g->copy_locus, locus);
  	}
        else
          {
*************** eliminate_build (elim_graph g, basic_blo
*** 354,360 ****
  	      eliminate_name (g, Ti);
  	      p0 = var_to_partition (g->map, T0);
  	      pi = var_to_partition (g->map, Ti);
! 	      elim_graph_add_edge (g, p0, pi);
  	    }
  	}
      }
--- 378,384 ----
  	      eliminate_name (g, Ti);
  	      p0 = var_to_partition (g->map, T0);
  	      pi = var_to_partition (g->map, Ti);
! 	      elim_graph_add_edge (g, p0, pi, locus);
  	    }
  	}
      }
*************** static void 
*** 367,374 ****
  elim_forward (elim_graph g, int T)
  {
    int S;
    SET_BIT (g->visited, T);
!   FOR_EACH_ELIM_GRAPH_SUCC (g, T, S,
      {
        if (!TEST_BIT (g->visited, S))
          elim_forward (g, S);
--- 391,400 ----
  elim_forward (elim_graph g, int T)
  {
    int S;
+   source_location locus;
+ 
    SET_BIT (g->visited, T);
!   FOR_EACH_ELIM_GRAPH_SUCC (g, T, S, locus,
      {
        if (!TEST_BIT (g->visited, S))
          elim_forward (g, S);
*************** static int
*** 383,389 ****
  elim_unvisited_predecessor (elim_graph g, int T)
  {
    int P;
!   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, 
      {
        if (!TEST_BIT (g->visited, P))
          return 1;
--- 409,417 ----
  elim_unvisited_predecessor (elim_graph g, int T)
  {
    int P;
!   source_location locus;
! 
!   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
      {
        if (!TEST_BIT (g->visited, P))
          return 1;
*************** static void
*** 397,411 ****
  elim_backward (elim_graph g, int T)
  {
    int P;
    SET_BIT (g->visited, T);
!   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, 
      {
        if (!TEST_BIT (g->visited, P))
          {
  	  elim_backward (g, P);
  	  insert_copy_on_edge (g->e, 
  			       partition_to_var (g->map, P), 
! 			       partition_to_var (g->map, T));
  	}
      });
  }
--- 425,442 ----
  elim_backward (elim_graph g, int T)
  {
    int P;
+   source_location locus;
+ 
    SET_BIT (g->visited, T);
!   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
      {
        if (!TEST_BIT (g->visited, P))
          {
  	  elim_backward (g, P);
  	  insert_copy_on_edge (g->e, 
  			       partition_to_var (g->map, P), 
! 			       partition_to_var (g->map, T),
! 			       locus);
  	}
      });
  }
*************** elim_create (elim_graph g, int T)
*** 418,446 ****
  {
    tree U;
    int P, S;
  
    if (elim_unvisited_predecessor (g, T))
      {
        U = create_temp (partition_to_var (g->map, T));
!       insert_copy_on_edge (g->e, U, partition_to_var (g->map, T));
!       FOR_EACH_ELIM_GRAPH_PRED (g, T, P, 
  	{
  	  if (!TEST_BIT (g->visited, P))
  	    {
  	      elim_backward (g, P);
! 	      insert_copy_on_edge (g->e, partition_to_var (g->map, P), U);
  	    }
  	});
      }
    else
      {
!       S = elim_graph_remove_succ_edge (g, T);
        if (S != -1)
  	{
  	  SET_BIT (g->visited, T);
  	  insert_copy_on_edge (g->e, 
  			       partition_to_var (g->map, T), 
! 			       partition_to_var (g->map, S));
  	}
      }
    
--- 449,485 ----
  {
    tree U;
    int P, S;
+   source_location locus;
  
    if (elim_unvisited_predecessor (g, T))
      {
        U = create_temp (partition_to_var (g->map, T));
!       insert_copy_on_edge (g->e, 
! 			   U, 
! 			   partition_to_var (g->map, T), 
! 			   UNKNOWN_LOCATION);
!       FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
  	{
  	  if (!TEST_BIT (g->visited, P))
  	    {
  	      elim_backward (g, P);
! 	      insert_copy_on_edge (g->e, 
! 				   partition_to_var (g->map, P), 
! 				   U,
! 				   locus);
  	    }
  	});
      }
    else
      {
!       S = elim_graph_remove_succ_edge (g, T, &locus);
        if (S != -1)
  	{
  	  SET_BIT (g->visited, T);
  	  insert_copy_on_edge (g->e, 
  			       partition_to_var (g->map, T), 
! 			       partition_to_var (g->map, S),
! 			       locus);
  	}
      }
    
*************** eliminate_phi (edge e, elim_graph g)
*** 456,461 ****
--- 495,501 ----
    basic_block B = e->dest;
  
    gcc_assert (VEC_length (tree, g->const_copies) == 0);
+   gcc_assert (VEC_length (source_location, g->copy_locus) == 0);
  
    /* Abnormal edges already have everything coalesced.  */
    if (e->flags & EDGE_ABNORMAL)
*************** eliminate_phi (edge e, elim_graph g)
*** 492,500 ****
    while (VEC_length (tree, g->const_copies) > 0)
      {
        tree src, dest;
        src = VEC_pop (tree, g->const_copies);
        dest = VEC_pop (tree, g->const_copies);
!       insert_copy_on_edge (e, dest, src);
      }
  }
  
--- 532,543 ----
    while (VEC_length (tree, g->const_copies) > 0)
      {
        tree src, dest;
+       source_location locus;
+ 
        src = VEC_pop (tree, g->const_copies);
        dest = VEC_pop (tree, g->const_copies);
!       locus = VEC_pop (source_location, g->copy_locus);
!       insert_copy_on_edge (e, dest, src, locus);
      }
  }
  
*************** insert_backedge_copies (void)
*** 1468,1473 ****
--- 1511,1521 ----
  		  name = make_ssa_name (result_var, stmt);
  		  gimple_assign_set_lhs (stmt, name);
  
+ 		  /* copy location if present.  */
+ 		  if (gimple_phi_arg_has_location (phi, i))
+ 		    gimple_set_location (stmt, 
+ 					 gimple_phi_arg_location (phi, i));
+ 
  		  /* Insert the new statement into the block and update
  		     the PHI node.  */
  		  if (last && stmt_ends_bb_p (last))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]