|
|
6fdc0f |
2006-12-08 Jakub Jelinek <jakub@redhat.com>
|
|
|
6fdc0f |
|
|
|
6fdc0f |
* g++.dg/debug/vartrack1.C: New test.
|
|
|
6fdc0f |
|
|
|
6fdc0f |
2006-09-11 Alexandre Oliva <aoliva@redhat.com>
|
|
|
6fdc0f |
|
|
|
6fdc0f |
PR target/28672
|
|
|
6fdc0f |
* var-tracking.c (dump_dataflow_set): Start dumping at
|
|
|
6fdc0f |
register zero.
|
|
|
6fdc0f |
(clobber_variable_part): Kill only the variable part in
|
|
|
6fdc0f |
registers holding it, leaving other variables alone.
|
|
|
6fdc0f |
|
|
|
6fdc0f |
2006-08-09 Alexandre Oliva <aoliva@redhat.com>
|
|
|
6fdc0f |
|
|
|
6fdc0f |
* var-tracking.c (enum micro_operation_type): Add MO_COPY.
|
|
|
6fdc0f |
(var_debug_decl): New function.
|
|
|
6fdc0f |
(var_reg_set): Follow debug decl link. Add location even if
|
|
|
6fdc0f |
reg is already known to hold some other variable.
|
|
|
6fdc0f |
(var_mem_set): Follow debug decl link.
|
|
|
6fdc0f |
(var_reg_delete_and_set, var_mem_delete_and_set): Follow debug
|
|
|
6fdc0f |
decl link. Delete other known locations of the variable part
|
|
|
6fdc0f |
if requested.
|
|
|
6fdc0f |
(var_reg_delete, var_mem_delete): Delete other known locations
|
|
|
6fdc0f |
of the variable part if requested.
|
|
|
6fdc0f |
(same_variable_part_p): New function.
|
|
|
6fdc0f |
(add_stores): Select MO_COPY when appropriate.
|
|
|
6fdc0f |
(vt_initialize): Handle it.
|
|
|
6fdc0f |
(compute_bb_dataflow, emit_notes_in_bb): Likewise. Delete
|
|
|
6fdc0f |
known locations for MO_SET and MO_CLOBBER.
|
|
|
6fdc0f |
(find_variable_location_part): New function.
|
|
|
6fdc0f |
(set_variable_part, delete_variable_part): Use it.
|
|
|
6fdc0f |
(clobber_variable_part): New function.
|
|
|
6fdc0f |
|
|
|
6fdc0f |
--- gcc/var-tracking.c.orig 2006-12-08 02:14:36.000000000 -0200
|
|
|
6fdc0f |
+++ gcc/var-tracking.c 2006-12-08 02:14:51.000000000 -0200
|
|
|
6fdc0f |
@@ -112,6 +112,8 @@ enum micro_operation_type
|
|
|
6fdc0f |
MO_USE_NO_VAR,/* Use location which is not associated with a variable
|
|
|
6fdc0f |
or the variable is not trackable. */
|
|
|
6fdc0f |
MO_SET, /* Set location. */
|
|
|
6fdc0f |
+ MO_COPY, /* Copy the same portion of a variable from one
|
|
|
6fdc0f |
+ loation to another. */
|
|
|
6fdc0f |
MO_CLOBBER, /* Clobber location. */
|
|
|
6fdc0f |
MO_CALL, /* Call insn. */
|
|
|
6fdc0f |
MO_ADJUST /* Adjust stack pointer. */
|
|
|
6fdc0f |
@@ -293,13 +295,14 @@ static void vars_clear (htab_t);
|
|
|
6fdc0f |
static variable unshare_variable (dataflow_set *set, variable var);
|
|
|
6fdc0f |
static int vars_copy_1 (void **, void *);
|
|
|
6fdc0f |
static void vars_copy (htab_t, htab_t);
|
|
|
6fdc0f |
+static tree var_debug_decl (tree);
|
|
|
6fdc0f |
static void var_reg_set (dataflow_set *, rtx);
|
|
|
6fdc0f |
-static void var_reg_delete_and_set (dataflow_set *, rtx);
|
|
|
6fdc0f |
-static void var_reg_delete (dataflow_set *, rtx);
|
|
|
6fdc0f |
+static void var_reg_delete_and_set (dataflow_set *, rtx, bool);
|
|
|
6fdc0f |
+static void var_reg_delete (dataflow_set *, rtx, bool);
|
|
|
6fdc0f |
static void var_regno_delete (dataflow_set *, int);
|
|
|
6fdc0f |
static void var_mem_set (dataflow_set *, rtx);
|
|
|
6fdc0f |
-static void var_mem_delete_and_set (dataflow_set *, rtx);
|
|
|
6fdc0f |
-static void var_mem_delete (dataflow_set *, rtx);
|
|
|
6fdc0f |
+static void var_mem_delete_and_set (dataflow_set *, rtx, bool);
|
|
|
6fdc0f |
+static void var_mem_delete (dataflow_set *, rtx, bool);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void dataflow_set_init (dataflow_set *, int);
|
|
|
6fdc0f |
static void dataflow_set_clear (dataflow_set *);
|
|
|
6fdc0f |
@@ -316,6 +319,7 @@ static void dataflow_set_destroy (datafl
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static bool contains_symbol_ref (rtx);
|
|
|
6fdc0f |
static bool track_expr_p (tree);
|
|
|
6fdc0f |
+static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
|
|
|
6fdc0f |
static int count_uses (rtx *, void *);
|
|
|
6fdc0f |
static void count_uses_1 (rtx *, void *);
|
|
|
6fdc0f |
static void count_stores (rtx, rtx, void *);
|
|
|
6fdc0f |
@@ -333,6 +337,7 @@ static void dump_dataflow_sets (void);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void variable_was_changed (variable, htab_t);
|
|
|
6fdc0f |
static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
|
|
6fdc0f |
+static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
|
|
6fdc0f |
static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
|
|
6fdc0f |
static int emit_note_insn_var_location (void **, void *);
|
|
|
6fdc0f |
static void emit_notes_for_changes (rtx, enum emit_note_where);
|
|
|
6fdc0f |
@@ -794,6 +799,14 @@ vars_copy (htab_t dst, htab_t src)
|
|
|
6fdc0f |
htab_traverse (src, vars_copy_1, dst);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+/* Map a decl to its main debug decl. */
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+static inline tree
|
|
|
6fdc0f |
+var_debug_decl (tree decl)
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ return decl;
|
|
|
6fdc0f |
+}
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
@@ -801,23 +814,35 @@ var_reg_set (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
tree decl = REG_EXPR (loc);
|
|
|
6fdc0f |
HOST_WIDE_INT offset = REG_OFFSET (loc);
|
|
|
6fdc0f |
+ attrs node;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- if (set->regs[REGNO (loc)] == NULL)
|
|
|
6fdc0f |
+ for (node = set->regs[REGNO (loc)]; node; node = node->next)
|
|
|
6fdc0f |
+ if (node->decl == decl && node->offset == offset)
|
|
|
6fdc0f |
+ break;
|
|
|
6fdc0f |
+ if (!node)
|
|
|
6fdc0f |
attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
|
|
|
6fdc0f |
set_variable_part (set, loc, decl, offset);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
-/* Delete current content of register LOC in dataflow set SET
|
|
|
6fdc0f |
- and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
|
|
|
6fdc0f |
+/* Delete current content of register LOC in dataflow set SET and set
|
|
|
6fdc0f |
+ the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
|
|
|
6fdc0f |
+ MODIFY is true, any other live copies of the same variable part are
|
|
|
6fdc0f |
+ also deleted from the dataflow set, otherwise the variable part is
|
|
|
6fdc0f |
+ assumed to be copied from another location holding the same
|
|
|
6fdc0f |
+ part. */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
-var_reg_delete_and_set (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
+var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
tree decl = REG_EXPR (loc);
|
|
|
6fdc0f |
HOST_WIDE_INT offset = REG_OFFSET (loc);
|
|
|
6fdc0f |
attrs node, next;
|
|
|
6fdc0f |
attrs *nextp;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
nextp = &set->regs[REGNO (loc)];
|
|
|
6fdc0f |
for (node = *nextp; node; node = next)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
@@ -834,17 +859,31 @@ var_reg_delete_and_set (dataflow_set *se
|
|
|
6fdc0f |
nextp = &node->next;
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
+ if (modify)
|
|
|
6fdc0f |
+ clobber_variable_part (set, loc, decl, offset);
|
|
|
6fdc0f |
var_reg_set (set, loc);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
-/* Delete current content of register LOC in dataflow set SET. */
|
|
|
6fdc0f |
+/* Delete current content of register LOC in dataflow set SET. If
|
|
|
6fdc0f |
+ CLOBBER is true, also delete any other live copies of the same
|
|
|
6fdc0f |
+ variable part. */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
-var_reg_delete (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
+var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
attrs *reg = &set->regs[REGNO (loc)];
|
|
|
6fdc0f |
attrs node, next;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+ if (clobber)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ tree decl = REG_EXPR (loc);
|
|
|
6fdc0f |
+ HOST_WIDE_INT offset = REG_OFFSET (loc);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ clobber_variable_part (set, NULL, decl, offset);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
for (node = *reg; node; node = next)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
next = node->next;
|
|
|
6fdc0f |
@@ -881,28 +920,44 @@ var_mem_set (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
tree decl = MEM_EXPR (loc);
|
|
|
6fdc0f |
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
set_variable_part (set, loc, decl, offset);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
-/* Delete and set the location part of variable MEM_EXPR (LOC)
|
|
|
6fdc0f |
- in dataflow set SET to LOC.
|
|
|
6fdc0f |
+/* Delete and set the location part of variable MEM_EXPR (LOC) in
|
|
|
6fdc0f |
+ dataflow set SET to LOC. If MODIFY is true, any other live copies
|
|
|
6fdc0f |
+ of the same variable part are also deleted from the dataflow set,
|
|
|
6fdc0f |
+ otherwise the variable part is assumed to be copied from another
|
|
|
6fdc0f |
+ location holding the same part.
|
|
|
6fdc0f |
Adjust the address first if it is stack pointer based. */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
-var_mem_delete_and_set (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
+var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
+ tree decl = MEM_EXPR (loc);
|
|
|
6fdc0f |
+ HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (modify)
|
|
|
6fdc0f |
+ clobber_variable_part (set, NULL, decl, offset);
|
|
|
6fdc0f |
var_mem_set (set, loc);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
-/* Delete the location part LOC from dataflow set SET.
|
|
|
6fdc0f |
+/* Delete the location part LOC from dataflow set SET. If CLOBBER is
|
|
|
6fdc0f |
+ true, also delete any other live copies of the same variable part.
|
|
|
6fdc0f |
Adjust the address first if it is stack pointer based. */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
-var_mem_delete (dataflow_set *set, rtx loc)
|
|
|
6fdc0f |
+var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
tree decl = MEM_EXPR (loc);
|
|
|
6fdc0f |
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+ decl = var_debug_decl (decl);
|
|
|
6fdc0f |
+ if (clobber)
|
|
|
6fdc0f |
+ clobber_variable_part (set, NULL, decl, offset);
|
|
|
6fdc0f |
delete_variable_part (set, loc, decl, offset);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
@@ -1476,6 +1531,41 @@ track_expr_p (tree expr)
|
|
|
6fdc0f |
return 1;
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+/* Determine whether a given LOC refers to the same variable part as
|
|
|
6fdc0f |
+ EXPR+OFFSET. */
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+static bool
|
|
|
6fdc0f |
+same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ tree expr2;
|
|
|
6fdc0f |
+ HOST_WIDE_INT offset2;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (! DECL_P (expr))
|
|
|
6fdc0f |
+ return false;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ expr2 = REG_EXPR (loc);
|
|
|
6fdc0f |
+ offset2 = REG_OFFSET (loc);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ else if (GET_CODE (loc) == MEM)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ expr2 = MEM_EXPR (loc);
|
|
|
6fdc0f |
+ offset2 = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ return false;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (! expr2 || ! DECL_P (expr2))
|
|
|
6fdc0f |
+ return false;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ expr = var_debug_decl (expr);
|
|
|
6fdc0f |
+ expr2 = var_debug_decl (expr2);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ return (expr == expr2 && offset == offset2);
|
|
|
6fdc0f |
+}
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
/* Count uses (register and memory references) LOC which will be tracked.
|
|
|
6fdc0f |
INSN is instruction which the LOC is part of. */
|
|
|
6fdc0f |
|
|
|
6fdc0f |
@@ -1570,9 +1660,18 @@ add_stores (rtx loc, rtx expr, void *ins
|
|
|
6fdc0f |
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
|
|
|
6fdc0f |
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- mo->type = ((GET_CODE (expr) != CLOBBER && REG_EXPR (loc)
|
|
|
6fdc0f |
- && track_expr_p (REG_EXPR (loc)))
|
|
|
6fdc0f |
- ? MO_SET : MO_CLOBBER);
|
|
|
6fdc0f |
+ if (GET_CODE (expr) == CLOBBER
|
|
|
6fdc0f |
+ || ! REG_EXPR (loc)
|
|
|
6fdc0f |
+ || ! track_expr_p (REG_EXPR (loc)))
|
|
|
6fdc0f |
+ mo->type = MO_CLOBBER;
|
|
|
6fdc0f |
+ else if (GET_CODE (expr) == SET
|
|
|
6fdc0f |
+ && SET_DEST (expr) == loc
|
|
|
6fdc0f |
+ && same_variable_part_p (SET_SRC (expr),
|
|
|
6fdc0f |
+ REG_EXPR (loc),
|
|
|
6fdc0f |
+ REG_OFFSET (loc)))
|
|
|
6fdc0f |
+ mo->type = MO_COPY;
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ mo->type = MO_SET;
|
|
|
6fdc0f |
mo->u.loc = loc;
|
|
|
6fdc0f |
mo->insn = NEXT_INSN ((rtx) insn);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
@@ -1583,7 +1682,17 @@ add_stores (rtx loc, rtx expr, void *ins
|
|
|
6fdc0f |
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
|
|
|
6fdc0f |
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- mo->type = GET_CODE (expr) == CLOBBER ? MO_CLOBBER : MO_SET;
|
|
|
6fdc0f |
+ if (GET_CODE (expr) == CLOBBER)
|
|
|
6fdc0f |
+ mo->type = MO_CLOBBER;
|
|
|
6fdc0f |
+ else if (GET_CODE (expr) == SET
|
|
|
6fdc0f |
+ && SET_DEST (expr) == loc
|
|
|
6fdc0f |
+ && same_variable_part_p (SET_SRC (expr),
|
|
|
6fdc0f |
+ MEM_EXPR (loc),
|
|
|
6fdc0f |
+ MEM_OFFSET (loc)
|
|
|
6fdc0f |
+ ? INTVAL (MEM_OFFSET (loc)) : 0))
|
|
|
6fdc0f |
+ mo->type = MO_COPY;
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ mo->type = MO_SET;
|
|
|
6fdc0f |
mo->u.loc = loc;
|
|
|
6fdc0f |
mo->insn = NEXT_INSN ((rtx) insn);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
@@ -1631,21 +1740,42 @@ compute_bb_dataflow (basic_block bb)
|
|
|
6fdc0f |
rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
- var_reg_delete_and_set (out, loc);
|
|
|
6fdc0f |
+ var_reg_delete_and_set (out, loc, true);
|
|
|
6fdc0f |
else if (GET_CODE (loc) == MEM)
|
|
|
6fdc0f |
- var_mem_delete_and_set (out, loc);
|
|
|
6fdc0f |
+ var_mem_delete_and_set (out, loc, true);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ break;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ case MO_COPY:
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
+ var_reg_delete_and_set (out, loc, false);
|
|
|
6fdc0f |
+ else if (GET_CODE (loc) == MEM)
|
|
|
6fdc0f |
+ var_mem_delete_and_set (out, loc, false);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
break;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
case MO_USE_NO_VAR:
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
+ var_reg_delete (out, loc, false);
|
|
|
6fdc0f |
+ else if (GET_CODE (loc) == MEM)
|
|
|
6fdc0f |
+ var_mem_delete (out, loc, false);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ break;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
case MO_CLOBBER:
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
- var_reg_delete (out, loc);
|
|
|
6fdc0f |
+ var_reg_delete (out, loc, true);
|
|
|
6fdc0f |
else if (GET_CODE (loc) == MEM)
|
|
|
6fdc0f |
- var_mem_delete (out, loc);
|
|
|
6fdc0f |
+ var_mem_delete (out, loc, true);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
break;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
@@ -1824,7 +1954,7 @@ dump_dataflow_set (dataflow_set *set)
|
|
|
6fdc0f |
|
|
|
6fdc0f |
fprintf (rtl_dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
|
|
|
6fdc0f |
set->stack_adjust);
|
|
|
6fdc0f |
- for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
|
|
|
6fdc0f |
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
if (set->regs[i])
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
@@ -1905,6 +2035,39 @@ variable_was_changed (variable var, htab
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+/* Look for the index in VAR->var_part corresponding to OFFSET.
|
|
|
6fdc0f |
+ Return -1 if not found. If INSERTION_POINT is non-NULL, the
|
|
|
6fdc0f |
+ referenced int will be set to the index that the part has or should
|
|
|
6fdc0f |
+ have, if it should be inserted. */
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+static inline int
|
|
|
6fdc0f |
+find_variable_location_part (variable var, HOST_WIDE_INT offset,
|
|
|
6fdc0f |
+ int *insertion_point)
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ int pos, low, high;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ /* Find the location part. */
|
|
|
6fdc0f |
+ low = 0;
|
|
|
6fdc0f |
+ high = var->n_var_parts;
|
|
|
6fdc0f |
+ while (low != high)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ pos = (low + high) / 2;
|
|
|
6fdc0f |
+ if (var->var_part[pos].offset < offset)
|
|
|
6fdc0f |
+ low = pos + 1;
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ high = pos;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ pos = low;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (insertion_point)
|
|
|
6fdc0f |
+ *insertion_point = pos;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
|
|
|
6fdc0f |
+ return pos;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ return -1;
|
|
|
6fdc0f |
+}
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
/* Set the part of variable's location in the dataflow set SET. The variable
|
|
|
6fdc0f |
part is specified by variable's declaration DECL and offset OFFSET and the
|
|
|
6fdc0f |
part's location by LOC. */
|
|
|
6fdc0f |
@@ -1912,7 +2075,7 @@ variable_was_changed (variable var, htab
|
|
|
6fdc0f |
static void
|
|
|
6fdc0f |
set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
- int pos, low, high;
|
|
|
6fdc0f |
+ int pos;
|
|
|
6fdc0f |
location_chain node, next;
|
|
|
6fdc0f |
location_chain *nextp;
|
|
|
6fdc0f |
variable var;
|
|
|
6fdc0f |
@@ -1935,22 +2098,13 @@ set_variable_part (dataflow_set *set, rt
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
else
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
+ int inspos = 0;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
var = (variable) *slot;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- /* Find the location part. */
|
|
|
6fdc0f |
- low = 0;
|
|
|
6fdc0f |
- high = var->n_var_parts;
|
|
|
6fdc0f |
- while (low != high)
|
|
|
6fdc0f |
- {
|
|
|
6fdc0f |
- pos = (low + high) / 2;
|
|
|
6fdc0f |
- if (var->var_part[pos].offset < offset)
|
|
|
6fdc0f |
- low = pos + 1;
|
|
|
6fdc0f |
- else
|
|
|
6fdc0f |
- high = pos;
|
|
|
6fdc0f |
- }
|
|
|
6fdc0f |
- pos = low;
|
|
|
6fdc0f |
+ pos = find_variable_location_part (var, offset, &inspos);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
|
|
|
6fdc0f |
+ if (pos >= 0)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
node = var->var_part[pos].loc_chain;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
@@ -1985,10 +2139,10 @@ set_variable_part (dataflow_set *set, rt
|
|
|
6fdc0f |
abort ();
|
|
|
6fdc0f |
#endif
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- /* We have to move the elements of array starting at index low to the
|
|
|
6fdc0f |
- next position. */
|
|
|
6fdc0f |
- for (high = var->n_var_parts; high > low; high--)
|
|
|
6fdc0f |
- var->var_part[high] = var->var_part[high - 1];
|
|
|
6fdc0f |
+ /* We have to move the elements of array starting at index
|
|
|
6fdc0f |
+ inspos to the next position. */
|
|
|
6fdc0f |
+ for (pos = var->n_var_parts; pos > inspos; pos--)
|
|
|
6fdc0f |
+ var->var_part[pos] = var->var_part[pos - 1];
|
|
|
6fdc0f |
|
|
|
6fdc0f |
var->n_var_parts++;
|
|
|
6fdc0f |
var->var_part[pos].offset = offset;
|
|
|
6fdc0f |
@@ -2028,6 +2182,67 @@ set_variable_part (dataflow_set *set, rt
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
|
|
|
6fdc0f |
+/* Remove all recorded register locations for the given variable part
|
|
|
6fdc0f |
+ from dataflow set SET, except for those that are identical to loc.
|
|
|
6fdc0f |
+ The variable part is specified by variable's declaration DECL and
|
|
|
6fdc0f |
+ offset OFFSET. */
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+static void
|
|
|
6fdc0f |
+clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
|
|
|
6fdc0f |
+ HOST_WIDE_INT offset)
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ void **slot;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (! decl || ! DECL_P (decl))
|
|
|
6fdc0f |
+ return;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
|
|
|
6fdc0f |
+ NO_INSERT);
|
|
|
6fdc0f |
+ if (slot)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ variable var = (variable) *slot;
|
|
|
6fdc0f |
+ int pos = find_variable_location_part (var, offset, NULL);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (pos >= 0)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ location_chain node, next;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ /* Remove the register locations from the dataflow set. */
|
|
|
6fdc0f |
+ next = var->var_part[pos].loc_chain;
|
|
|
6fdc0f |
+ for (node = next; node; node = next)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ next = node->next;
|
|
|
6fdc0f |
+ if (node->loc != loc)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ if (REG_P (node->loc))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ attrs anode, anext;
|
|
|
6fdc0f |
+ attrs *anextp;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ /* Remove the variable part from the register's
|
|
|
6fdc0f |
+ list, but preserve any other variable parts
|
|
|
6fdc0f |
+ that might be regarded as live in that same
|
|
|
6fdc0f |
+ register. */
|
|
|
6fdc0f |
+ anextp = &set->regs[REGNO (node->loc)];
|
|
|
6fdc0f |
+ for (anode = *anextp; anode; anode = anext)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ anext = anode->next;
|
|
|
6fdc0f |
+ if (anode->decl == decl
|
|
|
6fdc0f |
+ && anode->offset == offset)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ pool_free (attrs_pool, anode);
|
|
|
6fdc0f |
+ *anextp = anext;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ delete_variable_part (set, node->loc, decl, offset);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+}
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
/* Delete the part of variable's location from dataflow set SET. The variable
|
|
|
6fdc0f |
part is specified by variable's declaration DECL and offset OFFSET and the
|
|
|
6fdc0f |
part's location by LOC. */
|
|
|
6fdc0f |
@@ -2036,7 +2251,6 @@ static void
|
|
|
6fdc0f |
delete_variable_part (dataflow_set *set, rtx loc, tree decl,
|
|
|
6fdc0f |
HOST_WIDE_INT offset)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
- int pos, low, high;
|
|
|
6fdc0f |
void **slot;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
|
|
|
6fdc0f |
@@ -2044,21 +2258,9 @@ delete_variable_part (dataflow_set *set,
|
|
|
6fdc0f |
if (slot)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
variable var = (variable) *slot;
|
|
|
6fdc0f |
+ int pos = find_variable_location_part (var, offset, NULL);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- /* Find the location part. */
|
|
|
6fdc0f |
- low = 0;
|
|
|
6fdc0f |
- high = var->n_var_parts;
|
|
|
6fdc0f |
- while (low != high)
|
|
|
6fdc0f |
- {
|
|
|
6fdc0f |
- pos = (low + high) / 2;
|
|
|
6fdc0f |
- if (var->var_part[pos].offset < offset)
|
|
|
6fdc0f |
- low = pos + 1;
|
|
|
6fdc0f |
- else
|
|
|
6fdc0f |
- high = pos;
|
|
|
6fdc0f |
- }
|
|
|
6fdc0f |
- pos = low;
|
|
|
6fdc0f |
-
|
|
|
6fdc0f |
- if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
|
|
|
6fdc0f |
+ if (pos >= 0)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
location_chain node, next;
|
|
|
6fdc0f |
location_chain *nextp;
|
|
|
6fdc0f |
@@ -2124,7 +2326,7 @@ delete_variable_part (dataflow_set *set,
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
if (changed)
|
|
|
6fdc0f |
- variable_was_changed (var, set->vars);
|
|
|
6fdc0f |
+ variable_was_changed (var, set->vars);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
@@ -2418,28 +2620,50 @@ emit_notes_in_bb (basic_block bb)
|
|
|
6fdc0f |
rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
- var_reg_delete_and_set (&set, loc);
|
|
|
6fdc0f |
+ var_reg_delete_and_set (&set, loc, true);
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ var_mem_delete_and_set (&set, loc, true);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ break;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ case MO_COPY:
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
+ var_reg_delete_and_set (&set, loc, false);
|
|
|
6fdc0f |
else
|
|
|
6fdc0f |
- var_mem_delete_and_set (&set, loc);
|
|
|
6fdc0f |
+ var_mem_delete_and_set (&set, loc, false);
|
|
|
6fdc0f |
|
|
|
6fdc0f |
emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
break;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
case MO_USE_NO_VAR:
|
|
|
6fdc0f |
- case MO_CLOBBER:
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
- var_reg_delete (&set, loc);
|
|
|
6fdc0f |
+ var_reg_delete (&set, loc, false);
|
|
|
6fdc0f |
else
|
|
|
6fdc0f |
- var_mem_delete (&set, loc);
|
|
|
6fdc0f |
+ var_mem_delete (&set, loc, false);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ break;
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ case MO_CLOBBER:
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ rtx loc = VTI (bb)->mos[i].u.loc;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
- if (VTI (bb)->mos[i].type == MO_USE_NO_VAR)
|
|
|
6fdc0f |
- emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
|
|
|
6fdc0f |
+ if (GET_CODE (loc) == REG)
|
|
|
6fdc0f |
+ var_reg_delete (&set, loc, true);
|
|
|
6fdc0f |
else
|
|
|
6fdc0f |
- emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
|
|
6fdc0f |
+ var_mem_delete (&set, loc, true);
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
|
|
6fdc0f |
}
|
|
|
6fdc0f |
break;
|
|
|
6fdc0f |
|
|
|
6fdc0f |
@@ -2673,7 +2897,8 @@ vt_initialize (void)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
|
|
|
6fdc0f |
n1++;
|
|
|
6fdc0f |
- while (n1 < n2 && VTI (bb)->mos[n2].type == MO_SET)
|
|
|
6fdc0f |
+ while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET
|
|
|
6fdc0f |
+ || VTI (bb)->mos[n2].type == MO_COPY))
|
|
|
6fdc0f |
n2--;
|
|
|
6fdc0f |
if (n1 < n2)
|
|
|
6fdc0f |
{
|
|
|
6fdc0f |
--- gcc/testsuite/g++.dg/debug/vartrack1.C 2004-06-24 14:04:38.000000000 -0400
|
|
|
6fdc0f |
+++ gcc/testsuite/g++.dg/debug/vartrack1.C 2006-12-08 05:29:41.000000000 -0500
|
|
|
6fdc0f |
@@ -0,0 +1,99 @@
|
|
|
6fdc0f |
+// This testcase used to hang the compiler in vt_find_locations.
|
|
|
6fdc0f |
+// { dg-do compile }
|
|
|
6fdc0f |
+// { dg-options "-O2 -g" }
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+struct S
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ int a;
|
|
|
6fdc0f |
+ S *b, *c, *d;
|
|
|
6fdc0f |
+};
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+struct T
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ void f1 (S *x);
|
|
|
6fdc0f |
+ void f2 (S *x);
|
|
|
6fdc0f |
+ void f3 (S *x, S *y);
|
|
|
6fdc0f |
+ S *e;
|
|
|
6fdc0f |
+};
|
|
|
6fdc0f |
+
|
|
|
6fdc0f |
+void
|
|
|
6fdc0f |
+T::f3 (S *x, S *y)
|
|
|
6fdc0f |
+{
|
|
|
6fdc0f |
+ while (x != this->e && (!x || x->a == 1))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ if (x == y->c)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ S *w = y->d;
|
|
|
6fdc0f |
+ if (w && w->a == 0)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = 1;
|
|
|
6fdc0f |
+ y->a = 0;
|
|
|
6fdc0f |
+ f2 (y);
|
|
|
6fdc0f |
+ w = y->d;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ if (w && (!w->c || w->c->a == 1) && (!w->d || w->d->a == 1))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = 0;
|
|
|
6fdc0f |
+ x = y;
|
|
|
6fdc0f |
+ y = x->b;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ if (w && (!w->d || w->d->a == 1))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ if (w->c)
|
|
|
6fdc0f |
+ w->c->a = 1;
|
|
|
6fdc0f |
+ w->a = 0;
|
|
|
6fdc0f |
+ f1 (w);
|
|
|
6fdc0f |
+ w = y->d;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ if (w)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = y->a;
|
|
|
6fdc0f |
+ if (w->d)
|
|
|
6fdc0f |
+ w->d->a = 1;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ y->a = 1;
|
|
|
6fdc0f |
+ f2 (y);
|
|
|
6fdc0f |
+ x = e;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ S *w = y->c;
|
|
|
6fdc0f |
+ if (w && w->a == 0)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = 1;
|
|
|
6fdc0f |
+ y->a = 0;
|
|
|
6fdc0f |
+ f1 (y);
|
|
|
6fdc0f |
+ w = y->c;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ if (w && (!w->c || w->c->a == 1) && (!w->d || w->d->a == 1))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = 0;
|
|
|
6fdc0f |
+ x = y;
|
|
|
6fdc0f |
+ y = x->b;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ else
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ if (w && (!w->c || w->c->a == 1))
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = 0;
|
|
|
6fdc0f |
+ if (w->d)
|
|
|
6fdc0f |
+ w->d->a = 1;
|
|
|
6fdc0f |
+ f2 (w);
|
|
|
6fdc0f |
+ w = y->c;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ if (w)
|
|
|
6fdc0f |
+ {
|
|
|
6fdc0f |
+ w->a = y->a;
|
|
|
6fdc0f |
+ if (w->c)
|
|
|
6fdc0f |
+ w->c->a = 1;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ y->a = 1;
|
|
|
6fdc0f |
+ f1 (y);
|
|
|
6fdc0f |
+ x = e;
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+ }
|
|
|
6fdc0f |
+}
|