X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fvar-tracking.c;h=fb4a1813218fe7d1e3bed25c16e220eb905de9c4;hb=29f9683a5f2242786773eaa8f066001a39f18c82;hp=38983ec0524b69d817e8d3f185df32193fa94545;hpb=450d042a5291a12fd08589b74c0abf6b63581104;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 38983ec0524..fb4a1813218 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. @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ /* This file contains the variable tracking pass. It computes where variables are located (which registers or where in memory) at each position @@ -102,6 +102,10 @@ #include "alloc-pool.h" #include "fibheap.h" #include "hashtab.h" +#include "regs.h" +#include "expr.h" +#include "timevar.h" +#include "tree-pass.h" /* Type of micro operation. */ enum micro_operation_type @@ -233,6 +237,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 +248,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) @@ -261,16 +268,12 @@ static htab_t changed_variables; /* Shall notes be emitted? */ static bool emit_notes; -/* Fake variable for stack pointer. */ -GTY(()) tree frame_base_decl; - /* Local function prototypes. */ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); static void bb_stack_adjust_offset (basic_block); -static HOST_WIDE_INT prologue_stack_adjust (void); static bool vt_stack_adjustments (void); static rtx adjust_stack_reference (rtx, HOST_WIDE_INT); static hashval_t variable_htab_hash (const void *); @@ -285,6 +288,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 +304,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 *); @@ -324,7 +328,6 @@ static void dump_dataflow_set (dataflow_set *); static void dump_dataflow_sets (void); static void variable_was_changed (variable, htab_t); -static void set_frame_base_location (dataflow_set *, rtx); static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); static int emit_note_insn_var_location (void **, void *); @@ -366,7 +369,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 +383,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 @@ -470,7 +473,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,38 +483,6 @@ bb_stack_adjust_offset (basic_block bb) VTI (bb)->out.stack_adjust = offset; } -/* Compute stack adjustment caused by function prolog. */ - -static HOST_WIDE_INT -prologue_stack_adjust (void) -{ - HOST_WIDE_INT offset = 0; - basic_block bb = ENTRY_BLOCK_PTR->next_bb; - rtx insn; - rtx end; - - if (!BB_END (bb)) - return 0; - - end = NEXT_INSN (BB_END (bb)); - for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) - break; - - if (INSN_P (insn)) - { - HOST_WIDE_INT tmp; - - insn_stack_adjust_offset_pre_post (insn, &tmp, &tmp); - offset += tmp; - } - } - - return offset; -} - /* Compute stack adjustments for all blocks by traversing DFS tree. Return true when the adjustments on all incoming edges are consistent. Heavily borrowed from flow_depth_first_order_compute. */ @@ -519,30 +490,30 @@ prologue_stack_adjust (void) 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 = INCOMING_FRAME_SP_OFFSET; /* 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 +522,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 +536,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--; @@ -578,24 +549,28 @@ vt_stack_adjustments (void) return true; } -/* Adjust stack reference MEM by ADJUSTMENT bytes and return the new rtx. */ +/* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative + to the argument pointer. Return the new rtx. */ static rtx adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) { - rtx adjusted_mem; - rtx tmp; + rtx addr, cfa, tmp; - adjusted_mem = copy_rtx (mem); - XEXP (adjusted_mem, 0) = replace_rtx (XEXP (adjusted_mem, 0), - stack_pointer_rtx, - gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (adjustment))); - tmp = simplify_rtx (XEXP (adjusted_mem, 0)); +#ifdef FRAME_POINTER_CFA_OFFSET + adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl); + cfa = plus_constant (frame_pointer_rtx, adjustment); +#else + adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl); + cfa = plus_constant (arg_pointer_rtx, adjustment); +#endif + + addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa); + tmp = simplify_rtx (addr); if (tmp) - XEXP (adjusted_mem, 0) = tmp; + addr = tmp; - return adjusted_mem; + return replace_equiv_address_nv (mem, addr); } /* The hash function for variable_htab, computes the hash value @@ -629,6 +604,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 +713,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 +743,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 +798,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 +974,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 +1017,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 +1033,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 +1044,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 +1091,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 +1143,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 +1155,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 +1201,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 +1215,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 +1235,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 +1263,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 +1295,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 +1387,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 +1401,28 @@ 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_IS_FROM (realdecl) && DECL_DEBUG_EXPR (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 +1433,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 +1460,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 +1498,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 +1508,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 +1538,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 +1549,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 +1593,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,23 +1605,15 @@ 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; case MO_ADJUST: - { - 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))); - set_frame_base_location (out, base); - } + out->stack_adjust += VTI (bb)->mos[i].u.adjust; break; } } @@ -1590,8 +1638,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 +1651,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 +1674,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 +1688,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; @@ -1690,8 +1736,7 @@ dump_attrs_list (attrs list) for (; list; list = list->next) { print_mem_expr (dump_file, list->decl); - fprintf (dump_file, "+"); - fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset); + fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset); } fprintf (dump_file, "\n"); } @@ -1741,9 +1786,8 @@ dump_dataflow_set (dataflow_set *set) { int i; - fprintf (dump_file, "Stack adjustment: "); - fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust); - fprintf (dump_file, "\n"); + fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n", + set->stack_adjust); for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) { if (set->regs[i]) @@ -1795,6 +1839,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 +1855,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, @@ -1824,33 +1866,6 @@ 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. - */ - -static void -set_frame_base_location (dataflow_set *set, rtx loc) -{ - variable var; - - 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 - - var->var_part[0].loc_chain->loc = loc; - variable_was_changed (var, set->vars); -} - /* Set the part of variable's location in the dataflow set SET. The variable part is specified by variable's declaration DECL and offset OFFSET and the part's location by LOC. */ @@ -1859,7 +1874,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 +1886,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 +1911,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 +1955,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 +2018,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))) { @@ -2048,28 +2098,101 @@ emit_note_insn_var_location (void **varp, void *data) rtx insn = ((emit_note_data *)data)->insn; enum emit_note_where where = ((emit_note_data *)data)->where; rtx note; - int i; + int i, j, n_var_parts; bool complete; HOST_WIDE_INT last_limit; tree type_size_unit; + HOST_WIDE_INT offsets[MAX_VAR_PARTS]; + rtx loc[MAX_VAR_PARTS]; -#ifdef ENABLE_CHECKING - if (!var->decl) - abort (); -#endif + gcc_assert (var->decl); complete = true; last_limit = 0; + n_var_parts = 0; for (i = 0; i < var->n_var_parts; i++) { + enum machine_mode mode, wider_mode; + if (last_limit < var->var_part[i].offset) { complete = false; break; } - last_limit - = (var->var_part[i].offset - + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc))); + else if (last_limit > var->var_part[i].offset) + continue; + offsets[n_var_parts] = var->var_part[i].offset; + loc[n_var_parts] = var->var_part[i].loc_chain->loc; + mode = GET_MODE (loc[n_var_parts]); + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + + /* Attempt to merge adjacent registers or memory. */ + wider_mode = GET_MODE_WIDER_MODE (mode); + for (j = i + 1; j < var->n_var_parts; j++) + if (last_limit <= var->var_part[j].offset) + break; + if (j < var->n_var_parts + && wider_mode != VOIDmode + && GET_CODE (loc[n_var_parts]) + == GET_CODE (var->var_part[j].loc_chain->loc) + && mode == GET_MODE (var->var_part[j].loc_chain->loc) + && last_limit == var->var_part[j].offset) + { + rtx new_loc = NULL; + rtx loc2 = var->var_part[j].loc_chain->loc; + + if (REG_P (loc[n_var_parts]) + && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2 + == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode] + && REGNO (loc[n_var_parts]) + + hard_regno_nregs[REGNO (loc[n_var_parts])][mode] + == REGNO (loc2)) + { + if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) + new_loc = simplify_subreg (wider_mode, loc[n_var_parts], + mode, 0); + else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN) + new_loc = simplify_subreg (wider_mode, loc2, mode, 0); + if (new_loc) + { + if (!REG_P (new_loc) + || REGNO (new_loc) != REGNO (loc[n_var_parts])) + new_loc = NULL; + else + REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); + } + } + else if (MEM_P (loc[n_var_parts]) + && GET_CODE (XEXP (loc2, 0)) == PLUS + && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG + && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT) + { + if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG + && rtx_equal_p (XEXP (loc[n_var_parts], 0), + XEXP (XEXP (loc2, 0), 0)) + && INTVAL (XEXP (XEXP (loc2, 0), 1)) + == GET_MODE_SIZE (mode)) + || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS + && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1)) + == CONST_INT + && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0), + XEXP (XEXP (loc2, 0), 0)) + && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1)) + + GET_MODE_SIZE (mode) + == INTVAL (XEXP (XEXP (loc2, 0), 1)))) + new_loc = adjust_address_nv (loc[n_var_parts], + wider_mode, 0); + } + + if (new_loc) + { + loc[n_var_parts] = new_loc; + mode = wider_mode; + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + i = j; + } + } + ++n_var_parts; } type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl)); if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) @@ -2085,26 +2208,24 @@ emit_note_insn_var_location (void **varp, void *data) NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, NULL_RTX); } - else if (var->n_var_parts == 1) + else if (n_var_parts == 1) { rtx expr_list - = gen_rtx_EXPR_LIST (VOIDmode, - var->var_part[0].loc_chain->loc, - GEN_INT (var->var_part[0].offset)); + = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, expr_list); } - else if (var->n_var_parts) + else if (n_var_parts) { - rtx argp[MAX_VAR_PARTS]; rtx parallel; - for (i = 0; i < var->n_var_parts; i++) - argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc, - GEN_INT (var->var_part[i].offset)); + for (i = 0; i < n_var_parts; i++) + loc[i] + = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); + parallel = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec_v (var->n_var_parts, argp)); + gen_rtvec_v (n_var_parts, loc)); NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, parallel); } @@ -2147,8 +2268,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 +2278,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 +2301,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 +2360,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 +2377,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); @@ -2268,16 +2390,7 @@ emit_notes_in_bb (basic_block bb) break; case MO_ADJUST: - { - 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))); - set_frame_base_location (&set, base); - emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); - } + set.stack_adjust += VTI (bb)->mos[i].u.adjust; break; } } @@ -2293,10 +2406,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 +2436,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 +2445,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 +2463,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 +2471,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,35 +2492,19 @@ vt_add_function_parameters (void) 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); - in = &VTI (ENTRY_BLOCK_PTR)->in; 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 - 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) - { - set_variable_part (in, incoming, parm, offset); set_variable_part (out, incoming, parm, offset); } + else if (MEM_P (incoming)) + set_variable_part (out, incoming, parm, offset); } } @@ -2431,7 +2521,7 @@ vt_initialize (void) FOR_EACH_BB (bb) { rtx insn; - HOST_WIDE_INT pre, post; + HOST_WIDE_INT pre, post = 0; /* Count the number of micro operations. */ VTI (bb)->n_mos = 0; @@ -2450,7 +2540,7 @@ 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++; } } @@ -2500,7 +2590,7 @@ vt_initialize (void) } } - if (GET_CODE (insn) == CALL_INSN) + if (CALL_P (insn)) { micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; @@ -2559,26 +2649,6 @@ vt_initialize (void) changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, NULL); vt_add_function_parameters (); - - if (!frame_pointer_needed) - { - rtx base; - - /* Create fake variable for tracking stack pointer changes. */ - frame_base_decl = make_node (VAR_DECL); - DECL_NAME (frame_base_decl) = get_identifier ("___frame_base_decl"); - TREE_TYPE (frame_base_decl) = char_type_node; - DECL_ARTIFICIAL (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); - set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0); - } - else - { - frame_base_decl = NULL; - } } /* Free the data structures needed for variable tracking. */ @@ -2635,3 +2705,29 @@ variable_tracking_main (void) vt_finalize (); } + +static bool +gate_handle_var_tracking (void) +{ + return (flag_var_tracking); +} + + + +struct tree_opt_pass pass_variable_tracking = +{ + "vartrack", /* name */ + gate_handle_var_tracking, /* gate */ + variable_tracking_main, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_VAR_TRACKING, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'V' /* letter */ +}; +