X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fvar-tracking.c;h=a6a9c15d79e122b1d66b91fb9154b36529ae9f2d;hb=576aff9d272cd8ebec2b93b10dcf5eae125e9667;hp=7a1653d3ca436ff1ad3812079fad9763d50d3b22;hpb=5923a5e78781a98a9fbb1acaa222864c23cc26ef;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 7a1653d3ca4..a6a9c15d79e 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -1,5 +1,5 @@ /* 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. @@ -112,7 +112,7 @@ enum micro_operation_type MO_SET, /* Set location. */ MO_CLOBBER, /* Clobber location. */ MO_CALL, /* Call insn. */ - MO_ADJUST /* Adjust stack pointer. */ + MO_ADJUST /* Adjust stack pointer. */ }; /* Where shall the note be emitted? BEFORE or AFTER the instruction. */ @@ -233,6 +233,9 @@ typedef struct variable_def /* The declaration of the variable. */ tree decl; + /* Reference count. */ + int refcount; + /* Number of variable parts. */ int n_var_parts; @@ -241,7 +244,7 @@ typedef struct variable_def } *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) @@ -264,6 +267,9 @@ static bool emit_notes; /* Fake variable for stack pointer. */ 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 *, HOST_WIDE_INT *); @@ -285,6 +291,7 @@ static void attrs_list_copy (attrs *, attrs); static void attrs_list_union (attrs *, attrs); static void vars_clear (htab_t); +static variable unshare_variable (dataflow_set *set, variable var); static int vars_copy_1 (void **, void *); static void vars_copy (htab_t, htab_t); static void var_reg_delete_and_set (dataflow_set *, rtx); @@ -300,7 +307,7 @@ static int variable_union_info_cmp_pos (const void *, const void *); 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 *); @@ -366,7 +373,7 @@ stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre, 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); @@ -380,9 +387,9 @@ stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre, { 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 @@ -455,7 +462,7 @@ insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre, } } -/* Compute stack adjustnment in basic block BB. */ +/* Compute stack adjustment in basic block BB. */ static void bb_stack_adjust_offset (basic_block bb) @@ -470,7 +477,7 @@ bb_stack_adjust_offset (basic_block bb) 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); @@ -480,7 +487,7 @@ bb_stack_adjust_offset (basic_block bb) 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) @@ -496,7 +503,7 @@ 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; @@ -519,30 +526,30 @@ prologue_stack_adjust (void) static bool vt_stack_adjustments (void) { - edge *stack; + edge_iterator *stack; int sp; - /* Initialize enttry block. */ + /* 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) @@ -551,10 +558,10 @@ vt_stack_adjustments (void) 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 { @@ -565,9 +572,9 @@ vt_stack_adjustments (void) 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--; @@ -586,6 +593,9 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) 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, @@ -629,6 +639,12 @@ variable_htab_free (void *elem) variable var = (variable) elem; location_chain node, next; + gcc_assert (var->refcount > 0); + + var->refcount--; + if (var->refcount > 0) + return; + for (i = 0; i < var->n_var_parts; i++) { for (node = var->var_part[i].loc_chain; node; node = next) @@ -732,31 +748,29 @@ vars_clear (htab_t vars) htab_empty (vars); } -/* Copy one variable from *SLOT to hash table DATA. */ +/* Return a copy of a variable VAR and insert it to dataflow set SET. */ -static int -vars_copy_1 (void **slot, void *data) +static variable +unshare_variable (dataflow_set *set, variable var) { - htab_t dst = (htab_t) data; - variable src, *dstp, var; + void **slot; + variable new_var; int i; - src = *(variable *) slot; - dstp = (variable *) htab_find_slot_with_hash (dst, src->decl, - VARIABLE_HASH_VAL (src->decl), - INSERT); - var = pool_alloc (var_pool); - var->decl = src->decl; - var->n_var_parts = src->n_var_parts; - *dstp = (void *) var; + new_var = pool_alloc (var_pool); + new_var->decl = var->decl; + new_var->refcount = 1; + var->refcount--; + new_var->n_var_parts = var->n_var_parts; for (i = 0; i < var->n_var_parts; i++) { - location_chain last, node; + location_chain node; + location_chain *nextp; - var->var_part[i].offset = src->var_part[i].offset; - last = NULL; - for (node = src->var_part[i].loc_chain; node; node = node->next) + new_var->var_part[i].offset = var->var_part[i].offset; + nextp = &new_var->var_part[i].loc_chain; + for (node = var->var_part[i].loc_chain; node; node = node->next) { location_chain new_lc; @@ -764,21 +778,42 @@ vars_copy_1 (void **slot, void *data) new_lc->next = NULL; new_lc->loc = node->loc; - if (last) - last->next = new_lc; - else - var->var_part[i].loc_chain = new_lc; - last = new_lc; + *nextp = new_lc; + nextp = &new_lc->next; } /* We are at the basic block boundary when copying variable description so set the CUR_LOC to be the first element of the chain. */ - if (var->var_part[i].loc_chain) - var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc; + if (new_var->var_part[i].loc_chain) + new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc; else - var->var_part[i].cur_loc = NULL; + new_var->var_part[i].cur_loc = NULL; } + slot = htab_find_slot_with_hash (set->vars, new_var->decl, + VARIABLE_HASH_VAL (new_var->decl), + INSERT); + *slot = new_var; + return new_var; +} + +/* Add a variable from *SLOT to hash table DATA and increase its reference + count. */ + +static int +vars_copy_1 (void **slot, void *data) +{ + htab_t dst = (htab_t) data; + variable src, *dstp; + + src = *(variable *) slot; + src->refcount++; + + dstp = (variable *) htab_find_slot_with_hash (dst, src->decl, + VARIABLE_HASH_VAL (src->decl), + INSERT); + *dstp = src; + /* Continue traversing the hash table. */ return 1; } @@ -798,33 +833,29 @@ vars_copy (htab_t dst, htab_t src) static void var_reg_delete_and_set (dataflow_set *set, rtx loc) { - attrs *reg = &set->regs[REGNO (loc)]; tree decl = REG_EXPR (loc); HOST_WIDE_INT offset = REG_OFFSET (loc); - attrs node, prev, next; + attrs node, next; + attrs *nextp; - prev = NULL; - for (node = *reg; node; node = next) + nextp = &set->regs[REGNO (loc)]; + for (node = *nextp; node; node = next) { next = node->next; if (node->decl != decl || node->offset != offset) { delete_variable_part (set, node->loc, node->decl, node->offset); - - if (prev) - prev->next = next; - else - *reg = next; pool_free (attrs_pool, node); + *nextp = next; } else { node->loc = loc; - prev = node; + nextp = &node->next; } } - if (*reg == NULL) - attrs_list_insert (reg, decl, offset, loc); + if (set->regs[REGNO (loc)] == NULL) + attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); set_variable_part (set, loc, decl, offset); } @@ -978,17 +1009,34 @@ variable_union (void **slot, void *data) INSERT); if (!*dstp) { - *dstp = dst = pool_alloc (var_pool); - dst->decl = src->decl; - dst->n_var_parts = 0; + src->refcount++; + + /* If CUR_LOC of some variable part is not the first element of + the location chain we are going to change it so we have to make + 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) + { + gcc_assert (src->var_part[k].cur_loc); + if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) + break; + } + } + if (k < src->n_var_parts) + unshare_variable (set, src); + else + *dstp = src; + + /* Continue traversing the hash table. */ + return 1; } 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; @@ -1004,16 +1052,15 @@ variable_union (void **slot, void *data) else j++; } - if (i < src->n_var_parts) - k += src->n_var_parts - i; - if (j < dst->n_var_parts) - k += dst->n_var_parts - j; -#ifdef ENABLE_CHECKING + k += src->n_var_parts - i; + k += dst->n_var_parts - j; + /* 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); i = src->n_var_parts - 1; j = dst->n_var_parts - 1; @@ -1021,7 +1068,7 @@ variable_union (void **slot, void *data) for (k--; k >= 0; k--) { - location_chain node; + location_chain node, node2; if (i >= 0 && j >= 0 && src->var_part[i].offset == dst->var_part[j].offset) @@ -1032,7 +1079,26 @@ variable_union (void **slot, void *data) int dst_l, src_l; int ii, jj, n; struct variable_union_info *vui; - + + /* If DST is shared compare the location chains. + If they are different we will modify the chain in DST with + high probability so make a copy of DST. */ + if (dst->refcount > 1) + { + for (node = src->var_part[i].loc_chain, + node2 = dst->var_part[j].loc_chain; node && node2; + node = node->next, node2 = node2->next) + { + if (!((REG_P (node2->loc) + && REG_P (node->loc) + && REGNO (node2->loc) == REGNO (node->loc)) + || rtx_equal_p (node2->loc, node->loc))) + break; + } + if (node || node2) + dst = unshare_variable (set, dst); + } + src_l = 0; for (node = src->var_part[i].loc_chain; node; node = node->next) src_l++; @@ -1060,8 +1126,8 @@ variable_union (void **slot, void *data) /* 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)) { @@ -1112,9 +1178,10 @@ variable_union (void **slot, void *data) && src->var_part[i].offset > dst->var_part[j].offset) || j < 0) { - location_chain last = NULL; + location_chain *nextp; /* Copy the chain from SRC. */ + nextp = &dst->var_part[k].loc_chain; for (node = src->var_part[i].loc_chain; node; node = node->next) { location_chain new_lc; @@ -1123,11 +1190,8 @@ variable_union (void **slot, void *data) new_lc->next = NULL; new_lc->loc = node->loc; - if (last) - last->next = new_lc; - else - dst->var_part[k].loc_chain = new_lc; - last = new_lc; + *nextp = new_lc; + nextp = &new_lc->next; } dst->var_part[k].offset = src->var_part[i].offset; @@ -1172,7 +1236,7 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2) { 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; @@ -1186,15 +1250,19 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2) 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 == var2) + return false; + if (var1->n_var_parts != var2->n_var_parts) return true; @@ -1202,6 +1270,16 @@ variable_different_p (variable var1, variable var2) { 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])) @@ -1220,21 +1298,21 @@ dataflow_set_different_1 (void **slot, void *data) variable var1, var2; var1 = *(variable *) slot; - var2 = (variable) htab_find_with_hash (htab, var1->decl, - VARIABLE_HASH_VAL (var1->decl)); + var2 = htab_find_with_hash (htab, var1->decl, + VARIABLE_HASH_VAL (var1->decl)); if (!var2) { dataflow_set_different_value = true; - /* Stop traversing the hash table. */ + /* Stop traversing the hash table. */ return 0; } - if (variable_different_p (var1, var2)) + if (variable_different_p (var1, var2, false)) { dataflow_set_different_value = true; - /* Stop traversing the hash table. */ + /* Stop traversing the hash table. */ return 0; } @@ -1252,22 +1330,19 @@ dataflow_set_different_2 (void **slot, void *data) variable var1, var2; var1 = *(variable *) slot; - var2 = (variable) htab_find_with_hash (htab, var1->decl, - VARIABLE_HASH_VAL (var1->decl)); + var2 = htab_find_with_hash (htab, var1->decl, + VARIABLE_HASH_VAL (var1->decl)); if (!var2) { dataflow_set_different_value = true; - /* Stop traversing the hash table. */ + /* Stop traversing the hash table. */ 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; @@ -1347,6 +1422,7 @@ static bool 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) @@ -1360,10 +1436,29 @@ track_expr_p (tree expr) 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 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) @@ -1374,13 +1469,13 @@ track_expr_p (tree expr) 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) @@ -1401,19 +1496,16 @@ count_uses (rtx *loc, void *insn) { 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; @@ -1442,7 +1534,7 @@ count_stores (rtx loc, rtx expr ATTRIBUTE_UNUSED, void *insn) 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++; @@ -1452,7 +1544,7 @@ add_uses (rtx *loc, void *insn) 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))) { @@ -1482,7 +1574,7 @@ add_uses_1 (rtx *x, void *insn) 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++; @@ -1493,7 +1585,7 @@ add_stores (rtx loc, rtx expr, void *insn) 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))) { @@ -1537,9 +1629,9 @@ compute_bb_dataflow (basic_block bb) { 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; @@ -1549,9 +1641,9 @@ compute_bb_dataflow (basic_block bb) { 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; @@ -1561,9 +1653,8 @@ compute_bb_dataflow (basic_block bb) 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; @@ -1590,8 +1681,8 @@ vt_find_locations (void) /* Compute reverse completion order of depth first search of the CFG so that the data-flow runs faster. */ - rc_order = (int *) xmalloc (n_basic_blocks * sizeof (int)); - bb_order = (int *) xmalloc (last_basic_block * sizeof (int)); + rc_order = xmalloc (n_basic_blocks * sizeof (int)); + bb_order = xmalloc (last_basic_block * sizeof (int)); flow_depth_first_order_compute (NULL, rc_order); for (i = 0; i < n_basic_blocks; i++) bb_order[rc_order[i]] = i; @@ -1603,13 +1694,10 @@ vt_find_locations (void) 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)) { @@ -1629,12 +1717,13 @@ vt_find_locations (void) 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); } @@ -1642,7 +1731,7 @@ vt_find_locations (void) 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; @@ -1689,11 +1778,11 @@ dump_attrs_list (attrs list) { for (; list; list = list->next) { - print_mem_expr (rtl_dump_file, list->decl); - fprintf (rtl_dump_file, "+"); - fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset); + print_mem_expr (dump_file, list->decl); + fprintf (dump_file, "+"); + fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset); } - fprintf (rtl_dump_file, "\n"); + fprintf (dump_file, "\n"); } /* Print the information about variable *SLOT to dump file. */ @@ -1705,16 +1794,16 @@ dump_variable (void **slot, void *data ATTRIBUTE_UNUSED) int i; location_chain node; - fprintf (rtl_dump_file, " name: %s\n", + fprintf (dump_file, " name: %s\n", IDENTIFIER_POINTER (DECL_NAME (var->decl))); for (i = 0; i < var->n_var_parts; i++) { - fprintf (rtl_dump_file, " offset %ld\n", + fprintf (dump_file, " offset %ld\n", (long) var->var_part[i].offset); for (node = var->var_part[i].loc_chain; node; node = node->next) { - fprintf (rtl_dump_file, " "); - print_rtl_single (rtl_dump_file, node->loc); + fprintf (dump_file, " "); + print_rtl_single (dump_file, node->loc); } } @@ -1729,7 +1818,7 @@ dump_vars (htab_t vars) { if (htab_elements (vars) > 0) { - fprintf (rtl_dump_file, "Variables:\n"); + fprintf (dump_file, "Variables:\n"); htab_traverse (vars, dump_variable, NULL); } } @@ -1741,19 +1830,19 @@ dump_dataflow_set (dataflow_set *set) { int i; - fprintf (rtl_dump_file, "Stack adjustment: "); - fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust); - fprintf (rtl_dump_file, "\n"); + fprintf (dump_file, "Stack adjustment: "); + fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust); + fprintf (dump_file, "\n"); for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) { if (set->regs[i]) { - fprintf (rtl_dump_file, "Reg %d:", i); + fprintf (dump_file, "Reg %d:", i); dump_attrs_list (set->regs[i]); } } dump_vars (set->vars); - fprintf (rtl_dump_file, "\n"); + fprintf (dump_file, "\n"); } /* Print the IN and OUT sets for each basic block to dump file. */ @@ -1765,10 +1854,10 @@ dump_dataflow_sets (void) FOR_EACH_BB (bb) { - fprintf (rtl_dump_file, "\nBasic block %d:\n", bb->index); - fprintf (rtl_dump_file, "IN:\n"); + fprintf (dump_file, "\nBasic block %d:\n", bb->index); + fprintf (dump_file, "IN:\n"); dump_dataflow_set (&VTI (bb)->in); - fprintf (rtl_dump_file, "OUT:\n"); + fprintf (dump_file, "OUT:\n"); dump_dataflow_set (&VTI (bb)->out); } } @@ -1795,6 +1884,7 @@ variable_was_changed (variable var, htab_t htab) empty_var = pool_alloc (var_pool); empty_var->decl = var->decl; + empty_var->refcount = 1; empty_var->n_var_parts = 0; *slot = empty_var; @@ -1810,10 +1900,7 @@ variable_was_changed (variable var, htab_t htab) } 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, @@ -1825,9 +1912,8 @@ variable_was_changed (variable var, htab_t htab) } /* 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) @@ -1836,18 +1922,17 @@ 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) + var = unshare_variable (set, var); var->var_part[0].loc_chain->loc = loc; + var->var_part[0].cur_loc = loc; variable_was_changed (var, set->vars); } @@ -1859,7 +1944,8 @@ static void set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) { int pos, low, high; - location_chain node, prev, next; + location_chain node, next; + location_chain *nextp; variable var; void **slot; @@ -1870,6 +1956,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) /* Create new variable information. */ var = pool_alloc (var_pool); var->decl = decl; + var->refcount = 1; var->n_var_parts = 1; var->var_part[0].offset = offset; var->var_part[0].loc_chain = NULL; @@ -1894,16 +1981,37 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) } pos = low; - if (pos == var->n_var_parts || var->var_part[pos].offset != offset) + if (pos < var->n_var_parts && var->var_part[pos].offset == offset) + { + node = var->var_part[pos].loc_chain; + + if (node + && ((REG_P (node->loc) && REG_P (loc) + && REGNO (node->loc) == REGNO (loc)) + || rtx_equal_p (node->loc, loc))) + { + /* LOC is in the beginning of the chain so we have nothing + to do. */ + return; + } + else + { + /* We have to make a copy of a shared variable. */ + if (var->refcount > 1) + var = unshare_variable (set, var); + } + } + else { - /* We have not find the location part, new one will be created. */ + /* We have not found the location part, new one will be created. */ + + /* We have to make a copy of the shared variable. */ + 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. */ @@ -1917,24 +2025,21 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) } } - /* Delete the location from list. */ - prev = NULL; + /* Delete the location from the list. */ + nextp = &var->var_part[pos].loc_chain; 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)) { - if (prev) - prev->next = next; - else - var->var_part[pos].loc_chain = next; pool_free (loc_chain_pool, node); + *nextp = next; break; } else - prev = node; + nextp = &node->next; } /* Add the location to the beginning. */ @@ -1983,35 +2088,50 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl, if (pos < var->n_var_parts && var->var_part[pos].offset == offset) { - location_chain node, prev, next; + location_chain node, next; + location_chain *nextp; bool changed; + if (var->refcount > 1) + { + /* If the variable contains the location part we have to + make a copy of the variable. */ + for (node = var->var_part[pos].loc_chain; node; + node = node->next) + { + if ((REG_P (node->loc) && REG_P (loc) + && REGNO (node->loc) == REGNO (loc)) + || rtx_equal_p (node->loc, loc)) + { + var = unshare_variable (set, var); + break; + } + } + } + /* Delete the location part. */ - prev = NULL; - for (node = var->var_part[pos].loc_chain; node; node = next) + nextp = &var->var_part[pos].loc_chain; + 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)) { - if (prev) - prev->next = next; - else - var->var_part[pos].loc_chain = next; pool_free (loc_chain_pool, node); + *nextp = next; break; } else - prev = node; + nextp = &node->next; } /* If we have deleted the location which was last emitted 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))) { @@ -2053,10 +2173,7 @@ emit_note_insn_var_location (void **varp, void *data) 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; @@ -2147,8 +2264,8 @@ emit_notes_for_differences_1 (void **slot, void *data) variable old_var, new_var; old_var = *(variable *) slot; - new_var = (variable) htab_find_with_hash (new_vars, old_var->decl, - VARIABLE_HASH_VAL (old_var->decl)); + new_var = htab_find_with_hash (new_vars, old_var->decl, + VARIABLE_HASH_VAL (old_var->decl)); if (!new_var) { @@ -2157,10 +2274,11 @@ emit_notes_for_differences_1 (void **slot, void *data) empty_var = pool_alloc (var_pool); empty_var->decl = old_var->decl; + empty_var->refcount = 1; 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); } @@ -2179,8 +2297,8 @@ emit_notes_for_differences_2 (void **slot, void *data) variable old_var, new_var; new_var = *(variable *) slot; - old_var = (variable) htab_find_with_hash (old_vars, new_var->decl, - VARIABLE_HASH_VAL (new_var->decl)); + old_var = htab_find_with_hash (old_vars, new_var->decl, + VARIABLE_HASH_VAL (new_var->decl)); if (!old_var) { /* Variable has appeared. */ @@ -2238,7 +2356,7 @@ emit_notes_in_bb (basic_block bb) { 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); @@ -2255,7 +2373,7 @@ emit_notes_in_bb (basic_block bb) { 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); @@ -2272,9 +2390,8 @@ emit_notes_in_bb (basic_block bb) 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); } @@ -2293,10 +2410,7 @@ vt_emit_notes (void) 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). */ @@ -2326,7 +2440,7 @@ vt_emit_notes (void) 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)) { @@ -2335,7 +2449,7 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) return true; } } - else if (GET_CODE (rtl) == MEM) + else if (MEM_P (rtl)) { if (MEM_ATTRS (rtl)) { @@ -2353,11 +2467,7 @@ static void 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)) { @@ -2365,7 +2475,7 @@ vt_add_function_parameters (void) rtx incoming = DECL_INCOMING_RTL (parm); tree decl; HOST_WIDE_INT offset; - dataflow_set *in, *out; + dataflow_set *out; if (TREE_CODE (parm) != PARM_DECL) continue; @@ -2386,29 +2496,20 @@ vt_add_function_parameters (void) if (!decl) continue; - if (parm != decl) - abort (); + 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); - in = &VTI (ENTRY_BLOCK_PTR)->in; out = &VTI (ENTRY_BLOCK_PTR)->out; - if (GET_CODE (incoming) == REG) + if (REG_P (incoming)) { - if (REGNO (incoming) >= FIRST_PSEUDO_REGISTER) - abort (); - attrs_list_insert (&in->regs[REGNO (incoming)], - parm, offset, incoming); + gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); attrs_list_insert (&out->regs[REGNO (incoming)], parm, offset, incoming); - set_variable_part (in, incoming, parm, offset); set_variable_part (out, incoming, parm, offset); } - else if (GET_CODE (incoming) == MEM) + else if (MEM_P (incoming)) { - set_variable_part (in, incoming, parm, offset); set_variable_part (out, incoming, parm, offset); } } @@ -2446,12 +2547,12 @@ vt_initialize (void) } 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++; } } - /* Add the nicro-operations to the array. */ + /* Add the micro-operations to the array. */ VTI (bb)->mos = xmalloc (VTI (bb)->n_mos * sizeof (struct micro_operation_def)); VTI (bb)->n_mos = 0; @@ -2496,7 +2597,7 @@ vt_initialize (void) } } - if (GET_CODE (insn) == CALL_INSN) + if (CALL_P (insn)) { micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; @@ -2565,10 +2666,12 @@ vt_initialize (void) 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); - set_variable_part (&VTI (ENTRY_BLOCK_PTR)->in, base, frame_base_decl, 0); + 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 @@ -2623,10 +2726,10 @@ variable_tracking_main (void) vt_find_locations (); vt_emit_notes (); - if (rtl_dump_file) + if (dump_file) { dump_dataflow_sets (); - dump_flow_info (rtl_dump_file); + dump_flow_info (dump_file); } vt_finalize ();