This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[debuglocus] PHI source locations
- From: Andrew MacLeod <amacleod at redhat dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 23 Mar 2009 09:43:22 -0400
- Subject: [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))