/* Variable tracking routines for the GNU compiler.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
} *variable;
/* Hash function for DECL for VARIABLE_HTAB. */
-#define VARIABLE_HASH_VAL(decl) ((size_t) (decl))
+#define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
/* Pointer to the BB's information specific to variable tracking pass. */
#define VTI(BB) ((variable_tracking_info) (BB)->aux)
static bool emit_notes;
/* Fake variable for stack pointer. */
-GTY(()) tree frame_base_decl;
+tree frame_base_decl;
+
+/* Stack adjust caused by function prologue. */
+static HOST_WIDE_INT frame_stack_adjust;
/* Local function prototypes. */
static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
static int variable_union (void **, void *);
static void dataflow_set_union (dataflow_set *, dataflow_set *);
static bool variable_part_different_p (variable_part *, variable_part *);
-static bool variable_different_p (variable, variable);
+static bool variable_different_p (variable, variable, bool);
static int dataflow_set_different_1 (void **, void *);
static int dataflow_set_different_2 (void **, void *);
static bool dataflow_set_different (dataflow_set *, dataflow_set *);
else
*post -= INTVAL (XEXP (src, 1));
}
- else if (GET_CODE (dest) == MEM)
+ else if (MEM_P (dest))
{
/* (set (mem (pre_dec (reg sp))) (foo)) */
src = XEXP (dest, 0);
{
rtx val = XEXP (XEXP (src, 1), 1);
/* We handle only adjustments by constant amount. */
- if (GET_CODE (XEXP (src, 1)) != PLUS ||
- GET_CODE (val) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
+ GET_CODE (val) == CONST_INT);
+
if (code == PRE_MODIFY)
*pre -= INTVAL (val);
else
offset += VTI (bb)->mos[i].u.adjust;
else if (VTI (bb)->mos[i].type != MO_CALL)
{
- if (GET_CODE (VTI (bb)->mos[i].u.loc) == MEM)
+ if (MEM_P (VTI (bb)->mos[i].u.loc))
{
VTI (bb)->mos[i].u.loc
= adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
VTI (bb)->out.stack_adjust = offset;
}
-/* Compute stack adjustment caused by function prolog. */
+/* Compute stack adjustment caused by function prologue. */
static HOST_WIDE_INT
prologue_stack_adjust (void)
end = NEXT_INSN (BB_END (bb));
for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn))
{
- if (GET_CODE (insn) == NOTE
+ if (NOTE_P (insn)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
break;
static bool
vt_stack_adjustments (void)
{
- edge *stack;
+ edge_iterator *stack;
int sp;
/* Initialize entry block. */
VTI (ENTRY_BLOCK_PTR)->visited = true;
- VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = 0;
+ VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = frame_stack_adjust;
/* Allocate stack for back-tracking up CFG. */
- stack = xmalloc ((n_basic_blocks + 1) * sizeof (edge));
+ stack = xmalloc ((n_basic_blocks + 1) * sizeof (edge_iterator));
sp = 0;
/* Push the first edge on to the stack. */
- stack[sp++] = ENTRY_BLOCK_PTR->succ;
+ stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
while (sp)
{
- edge e;
+ edge_iterator ei;
basic_block src;
basic_block dest;
/* Look at the edge on the top of the stack. */
- e = stack[sp - 1];
- src = e->src;
- dest = e->dest;
+ ei = stack[sp - 1];
+ src = ei_edge (ei)->src;
+ dest = ei_edge (ei)->dest;
/* Check if the edge destination has been visited yet. */
if (!VTI (dest)->visited)
VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
bb_stack_adjust_offset (dest);
- if (dest->succ)
+ if (EDGE_COUNT (dest->succs) > 0)
/* Since the DEST node has been visited for the first
time, check its successors. */
- stack[sp++] = dest->succ;
+ stack[sp++] = ei_start (dest->succs);
}
else
{
return false;
}
- if (e->succ_next)
+ if (! ei_one_before_end_p (ei))
/* Go to the next edge. */
- stack[sp - 1] = e->succ_next;
+ ei_next (&stack[sp - 1]);
else
/* Return to previous level if there are no more edges. */
sp--;
rtx adjusted_mem;
rtx tmp;
+ if (adjustment == 0)
+ return mem;
+
adjusted_mem = copy_rtx (mem);
XEXP (adjusted_mem, 0) = replace_rtx (XEXP (adjusted_mem, 0),
stack_pointer_rtx,
variable var = (variable) elem;
location_chain node, next;
-#ifdef ENABLE_CHECKING
- if (var->refcount <= 0)
- abort ();
-#endif
+ gcc_assert (var->refcount > 0);
var->refcount--;
if (var->refcount > 0)
a copy of the variable. */
for (k = 0; k < src->n_var_parts; k++)
{
+ gcc_assert (!src->var_part[k].loc_chain
+ == !src->var_part[k].cur_loc);
if (src->var_part[k].loc_chain)
{
-#ifdef ENABLE_CHECKING
- if (src->var_part[k].cur_loc == NULL)
- abort ();
-#endif
+ gcc_assert (src->var_part[k].cur_loc);
if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
break;
}
-#ifdef ENABLE_CHECKING
- else
- {
- if (src->var_part[k].cur_loc != NULL)
- abort ();
- }
-#endif
}
if (k < src->n_var_parts)
unshare_variable (set, src);
else
dst = *dstp;
-#ifdef ENABLE_CHECKING
- if (src->n_var_parts == 0)
- abort ();
-#endif
+ gcc_assert (src->n_var_parts);
/* Count the number of location parts, result is K. */
for (i = 0, j = 0, k = 0;
}
k += src->n_var_parts - i;
k += dst->n_var_parts - j;
-#ifdef ENABLE_CHECKING
+
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
- if (k > MAX_VAR_PARTS)
- abort ();
-#endif
+ gcc_assert (k <= MAX_VAR_PARTS);
if (dst->refcount > 1 && dst->n_var_parts != k)
dst = unshare_variable (set, dst);
node2 = dst->var_part[j].loc_chain; node && node2;
node = node->next, node2 = node2->next)
{
- if (!((GET_CODE (node2->loc) == REG
- && GET_CODE (node->loc) == REG
+ if (!((REG_P (node2->loc)
+ && REG_P (node->loc)
&& REGNO (node2->loc) == REGNO (node->loc))
|| rtx_equal_p (node2->loc, node->loc)))
break;
/* Find location from NODE. */
for (jj = 0; jj < dst_l; jj++)
{
- if ((GET_CODE (vui[jj].lc->loc) == REG
- && GET_CODE (node->loc) == REG
+ if ((REG_P (vui[jj].lc->loc)
+ && REG_P (node->loc)
&& REGNO (vui[jj].lc->loc) == REGNO (node->loc))
|| rtx_equal_p (vui[jj].lc->loc, node->loc))
{
{
location_chain lc1, lc2;
- if (!((GET_CODE (vp1->cur_loc) == REG
- && GET_CODE (vp2->cur_loc) == REG
- && REGNO (vp1->cur_loc) == REGNO (vp2->cur_loc))
- || rtx_equal_p (vp1->cur_loc, vp2->cur_loc)))
- return true;
-
for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
{
for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
{
- if (GET_CODE (lc1->loc) == REG && GET_CODE (lc2->loc) == REG)
+ if (REG_P (lc1->loc) && REG_P (lc2->loc))
{
if (REGNO (lc1->loc) == REGNO (lc2->loc))
break;
return false;
}
-/* Return true if variables VAR1 and VAR2 are different (only the first
- location in the list of locations is checked for each offset,
- i.e. when true is returned a note should be emitted). */
+/* Return true if variables VAR1 and VAR2 are different.
+ If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
+ variable part. */
static bool
-variable_different_p (variable var1, variable var2)
+variable_different_p (variable var1, variable var2,
+ bool compare_current_location)
{
int i;
{
if (var1->var_part[i].offset != var2->var_part[i].offset)
return true;
+ if (compare_current_location)
+ {
+ if (!((REG_P (var1->var_part[i].cur_loc)
+ && REG_P (var2->var_part[i].cur_loc)
+ && (REGNO (var1->var_part[i].cur_loc)
+ == REGNO (var2->var_part[i].cur_loc)))
+ || rtx_equal_p (var1->var_part[i].cur_loc,
+ var2->var_part[i].cur_loc)))
+ return true;
+ }
if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
return true;
if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
return 0;
}
- if (variable_different_p (var1, var2))
+ if (variable_different_p (var1, var2, false))
{
dataflow_set_different_value = true;
return 0;
}
-#ifdef ENABLE_CHECKING
/* If both variables are defined they have been already checked for
equivalence. */
- if (variable_different_p (var1, var2))
- abort ();
-#endif
+ gcc_assert (!variable_different_p (var1, var2, false));
/* Continue traversing the hash table. */
return 1;
track_expr_p (tree expr)
{
rtx decl_rtl;
+ tree realdecl;
/* If EXPR is not a parameter or a variable do not track it. */
if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
decl_rtl = DECL_RTL_IF_SET (expr);
if (!decl_rtl)
return 0;
+
+ /* If this expression is really a debug alias of some other declaration, we
+ don't need to track this expression if the ultimate declaration is
+ ignored. */
+ realdecl = expr;
+ if (DECL_DEBUG_EXPR (realdecl)
+ && DECL_DEBUG_EXPR_IS_FROM (realdecl))
+ {
+ realdecl = DECL_DEBUG_EXPR (realdecl);
+ /* ??? We don't yet know how to emit DW_OP_piece for variable
+ that has been SRA'ed. */
+ if (!DECL_P (realdecl))
+ return 0;
+ }
- /* Do not track EXPR if it should be ignored for debugging purposes. */
- if (DECL_IGNORED_P (expr))
+ /* Do not track EXPR if REALDECL it should be ignored for debugging
+ purposes. */
+ if (DECL_IGNORED_P (realdecl))
return 0;
/* Do not track global variables until we are able to emit correct location
list for them. */
- if (TREE_STATIC (expr))
+ if (TREE_STATIC (realdecl))
return 0;
/* When the EXPR is a DECL for alias of some variable (see example)
extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
char **_dl_argv;
*/
- if (GET_CODE (decl_rtl) == MEM
+ if (MEM_P (decl_rtl)
&& contains_symbol_ref (XEXP (decl_rtl, 0)))
return 0;
/* If RTX is a memory it should not be very large (because it would be
an array or struct). */
- if (GET_CODE (decl_rtl) == MEM)
+ if (MEM_P (decl_rtl))
{
/* Do not track structures and arrays. */
if (GET_MODE (decl_rtl) == BLKmode)
{
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
- if (GET_CODE (*loc) == REG)
+ if (REG_P (*loc))
{
-#ifdef ENABLE_CHECKING
- if (REGNO (*loc) >= FIRST_PSEUDO_REGISTER)
- abort ();
-#endif
- VTI (bb)->n_mos++;
+ gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
+ VTI (bb)->n_mos++;
}
- else if (GET_CODE (*loc) == MEM
+ else if (MEM_P (*loc)
&& MEM_EXPR (*loc)
&& track_expr_p (MEM_EXPR (*loc)))
{
- VTI (bb)->n_mos++;
+ VTI (bb)->n_mos++;
}
return 0;
static int
add_uses (rtx *loc, void *insn)
{
- if (GET_CODE (*loc) == REG)
+ if (REG_P (*loc))
{
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
mo->u.loc = *loc;
mo->insn = (rtx) insn;
}
- else if (GET_CODE (*loc) == MEM
+ else if (MEM_P (*loc)
&& MEM_EXPR (*loc)
&& track_expr_p (MEM_EXPR (*loc)))
{
static void
add_stores (rtx loc, rtx expr, void *insn)
{
- if (GET_CODE (loc) == REG)
+ if (REG_P (loc))
{
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
mo->u.loc = loc;
mo->insn = (rtx) insn;
}
- else if (GET_CODE (loc) == MEM
+ else if (MEM_P (loc)
&& MEM_EXPR (loc)
&& track_expr_p (MEM_EXPR (loc)))
{
{
rtx loc = VTI (bb)->mos[i].u.loc;
- if (GET_CODE (loc) == REG)
+ if (REG_P (loc))
var_reg_delete_and_set (out, loc);
- else if (GET_CODE (loc) == MEM)
+ else if (MEM_P (loc))
var_mem_delete_and_set (out, loc);
}
break;
{
rtx loc = VTI (bb)->mos[i].u.loc;
- if (GET_CODE (loc) == REG)
+ if (REG_P (loc))
var_reg_delete (out, loc);
- else if (GET_CODE (loc) == MEM)
+ else if (MEM_P (loc))
var_mem_delete (out, loc);
}
break;
rtx base;
out->stack_adjust += VTI (bb)->mos[i].u.adjust;
- base = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (out->stack_adjust)));
+ base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+ out->stack_adjust));
set_frame_base_location (out, base);
}
break;
in_worklist = sbitmap_alloc (last_basic_block);
in_pending = sbitmap_alloc (last_basic_block);
sbitmap_zero (in_worklist);
- sbitmap_zero (in_pending);
FOR_EACH_BB (bb)
- {
- fibheap_insert (pending, bb_order[bb->index], bb);
- SET_BIT (in_pending, bb->index);
- }
+ fibheap_insert (pending, bb_order[bb->index], bb);
+ sbitmap_ones (in_pending);
while (!fibheap_empty (pending))
{
if (!TEST_BIT (visited, bb->index))
{
bool changed;
+ edge_iterator ei;
SET_BIT (visited, bb->index);
/* Calculate the IN set as union of predecessor OUT sets. */
dataflow_set_clear (&VTI (bb)->in);
- for (e = bb->pred; e; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, bb->preds)
{
dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
}
changed = compute_bb_dataflow (bb);
if (changed)
{
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
}
else
{
-#ifdef ENABLE_CHECKING
- if (!htab)
- abort ();
-#endif
+ gcc_assert (htab);
if (var->n_var_parts == 0)
{
void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
}
/* Set the location of frame_base_decl to LOC in dataflow set SET. This
- function expects that
- frame_base_decl has already one location for offset 0 in the variable table.
- */
+ function expects that frame_base_decl has already one location for offset 0
+ in the variable table. */
static void
set_frame_base_location (dataflow_set *set, rtx loc)
var = htab_find_with_hash (set->vars, frame_base_decl,
VARIABLE_HASH_VAL (frame_base_decl));
-#ifdef ENABLE_CHECKING
- if (!var)
- abort ();
- if (var->n_var_parts != 1)
- abort ();
- if (var->var_part[0].offset != 0)
- abort ();
- if (!var->var_part[0].loc_chain)
- abort ();
-#endif
+ gcc_assert (var);
+ gcc_assert (var->n_var_parts == 1);
+ gcc_assert (!var->var_part[0].offset);
+ gcc_assert (var->var_part[0].loc_chain);
/* If frame_base_decl is shared unshare it first. */
if (var->refcount > 1)
node = var->var_part[pos].loc_chain;
if (node
- && ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+ && ((REG_P (node->loc) && REG_P (loc)
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc)))
{
if (var->refcount > 1)
var = unshare_variable (set, var);
-#ifdef ENABLE_CHECKING
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
- if (var->n_var_parts >= MAX_VAR_PARTS)
- abort ();
-#endif
+ gcc_assert (var->n_var_parts < MAX_VAR_PARTS);
/* We have to move the elements of array starting at index low to the
next position. */
for (node = var->var_part[pos].loc_chain; node; node = next)
{
next = node->next;
- if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+ if ((REG_P (node->loc) && REG_P (loc)
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc))
{
for (node = var->var_part[pos].loc_chain; node;
node = node->next)
{
- if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+ if ((REG_P (node->loc) && REG_P (loc)
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc))
{
for (node = *nextp; node; node = next)
{
next = node->next;
- if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+ if ((REG_P (node->loc) && REG_P (loc)
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc))
{
we have to emit new location so add the variable to set
of changed variables. */
if (var->var_part[pos].cur_loc
- && ((GET_CODE (loc) == REG
- && GET_CODE (var->var_part[pos].cur_loc) == REG
+ && ((REG_P (loc)
+ && REG_P (var->var_part[pos].cur_loc)
&& REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
|| rtx_equal_p (loc, var->var_part[pos].cur_loc)))
{
HOST_WIDE_INT last_limit;
tree type_size_unit;
-#ifdef ENABLE_CHECKING
- if (!var->decl)
- abort ();
-#endif
+ gcc_assert (var->decl);
complete = true;
last_limit = 0;
empty_var->n_var_parts = 0;
variable_was_changed (empty_var, NULL);
}
- else if (variable_different_p (old_var, new_var))
+ else if (variable_different_p (old_var, new_var, true))
{
variable_was_changed (new_var, NULL);
}
{
rtx loc = VTI (bb)->mos[i].u.loc;
- if (GET_CODE (loc) == REG)
+ if (REG_P (loc))
var_reg_delete_and_set (&set, loc);
else
var_mem_delete_and_set (&set, loc);
{
rtx loc = VTI (bb)->mos[i].u.loc;
- if (GET_CODE (loc) == REG)
+ if (REG_P (loc))
var_reg_delete (&set, loc);
else
var_mem_delete (&set, loc);
rtx base;
set.stack_adjust += VTI (bb)->mos[i].u.adjust;
- base = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (set.stack_adjust)));
+ base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+ set.stack_adjust));
set_frame_base_location (&set, base);
emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
}
dataflow_set *last_out;
dataflow_set empty;
-#ifdef ENABLE_CHECKING
- if (htab_elements (changed_variables))
- abort ();
-#endif
+ gcc_assert (!htab_elements (changed_variables));
/* Enable emitting notes by functions (mainly by set_variable_part and
delete_variable_part). */
static bool
vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
{
- if (GET_CODE (rtl) == REG)
+ if (REG_P (rtl))
{
if (REG_ATTRS (rtl))
{
return true;
}
}
- else if (GET_CODE (rtl) == MEM)
+ else if (MEM_P (rtl))
{
if (MEM_ATTRS (rtl))
{
vt_add_function_parameters (void)
{
tree parm;
- HOST_WIDE_INT stack_adjust = 0;
- if (!frame_pointer_needed)
- stack_adjust = prologue_stack_adjust ();
-
for (parm = DECL_ARGUMENTS (current_function_decl);
parm; parm = TREE_CHAIN (parm))
{
if (!decl)
continue;
-#ifdef ENABLE_CHECKING
- if (parm != decl)
- abort ();
-#endif
+ gcc_assert (parm == decl);
incoming = eliminate_regs (incoming, 0, NULL_RTX);
- if (!frame_pointer_needed && GET_CODE (incoming) == MEM)
- incoming = adjust_stack_reference (incoming, -stack_adjust);
out = &VTI (ENTRY_BLOCK_PTR)->out;
- if (GET_CODE (incoming) == REG)
+ if (REG_P (incoming))
{
-#ifdef ENABLE_CHECKING
- if (REGNO (incoming) >= FIRST_PSEUDO_REGISTER)
- abort ();
-#endif
+ gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
attrs_list_insert (&out->regs[REGNO (incoming)],
parm, offset, incoming);
set_variable_part (out, incoming, parm, offset);
}
- else if (GET_CODE (incoming) == MEM)
+ else if (MEM_P (incoming))
{
set_variable_part (out, incoming, parm, offset);
}
}
note_uses (&PATTERN (insn), count_uses_1, insn);
note_stores (PATTERN (insn), count_stores, insn);
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
VTI (bb)->n_mos++;
}
}
}
}
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
{
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
DECL_NAME (frame_base_decl) = get_identifier ("___frame_base_decl");
TREE_TYPE (frame_base_decl) = char_type_node;
DECL_ARTIFICIAL (frame_base_decl) = 1;
+ DECL_IGNORED_P (frame_base_decl) = 1;
/* Set its initial "location". */
- base = gen_rtx_MEM (Pmode, stack_pointer_rtx);
+ frame_stack_adjust = -prologue_stack_adjust ();
+ base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+ frame_stack_adjust));
set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0);
}
else