X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fvar-tracking.c;h=fb4a1813218fe7d1e3bed25c16e220eb905de9c4;hb=29f9683a5f2242786773eaa8f066001a39f18c82;hp=28c0c6fbdbaad2b31bd8bf6865c47546af669978;hpb=d887990506aaf31a4aaab2a59570a18d88278a74;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 28c0c6fbdba..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 @@ -244,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) @@ -264,16 +268,12 @@ static htab_t changed_variables; /* Shall notes be emitted? */ static bool emit_notes; -/* Fake variable for stack pointer. */ -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 *); @@ -328,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 *); @@ -370,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); @@ -384,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 @@ -474,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); @@ -484,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. */ @@ -523,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) @@ -555,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 { @@ -569,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--; @@ -582,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 @@ -633,10 +604,7 @@ variable_htab_free (void *elem) 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) @@ -1013,22 +981,14 @@ variable_union (void **slot, void *data) 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); @@ -1041,10 +1001,7 @@ variable_union (void **slot, void *data) 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; @@ -1062,12 +1019,10 @@ variable_union (void **slot, void *data) } 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); @@ -1099,8 +1054,8 @@ variable_union (void **slot, void *data) 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; @@ -1136,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)) { @@ -1246,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; @@ -1282,8 +1237,8 @@ variable_different_p (variable var1, variable var2, return true; if (compare_current_location) { - if (!((GET_CODE (var1->var_part[i].cur_loc) == REG - && GET_CODE (var2->var_part[i].cur_loc) == REG + 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, @@ -1350,12 +1305,9 @@ dataflow_set_different_2 (void **slot, void *data) return 0; } -#ifdef ENABLE_CHECKING /* If both variables are defined they have been already checked for equivalence. */ - if (variable_different_p (var1, var2, false)) - abort (); -#endif + gcc_assert (!variable_different_p (var1, var2, false)); /* Continue traversing the hash table. */ return 1; @@ -1435,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) @@ -1448,14 +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 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) @@ -1466,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) @@ -1493,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; @@ -1534,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++; @@ -1544,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))) { @@ -1574,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++; @@ -1585,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))) { @@ -1629,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; @@ -1641,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; } } @@ -1695,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)) { @@ -1721,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); } @@ -1734,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; @@ -1782,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"); } @@ -1833,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]) @@ -1903,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, @@ -1917,38 +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 - - /* 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); -} - /* 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. */ @@ -1999,7 +1916,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) 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))) { @@ -2022,12 +1939,9 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) 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. */ @@ -2046,7 +1960,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) 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)) { @@ -2115,7 +2029,7 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl, 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)) { @@ -2130,7 +2044,7 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl, 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)) { @@ -2146,8 +2060,8 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl, 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))) { @@ -2184,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)) @@ -2221,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); } @@ -2375,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); @@ -2392,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); @@ -2405,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; } } @@ -2430,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). */ @@ -2463,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)) { @@ -2472,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)) { @@ -2490,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)) { @@ -2523,30 +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); 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) - { - set_variable_part (out, incoming, parm, offset); - } + else if (MEM_P (incoming)) + set_variable_part (out, incoming, parm, offset); } } @@ -2563,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; @@ -2582,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++; } } @@ -2632,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++; @@ -2691,25 +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)->out, base, frame_base_decl, 0); - } - else - { - frame_base_decl = NULL; - } } /* Free the data structures needed for variable tracking. */ @@ -2766,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 */ +}; +