diff options
Diffstat (limited to 'gcc/var-tracking.c')
-rw-r--r-- | gcc/var-tracking.c | 245 |
1 files changed, 205 insertions, 40 deletions
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 97986b66886..13a9dd20e86 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -112,6 +112,9 @@ enum micro_operation_type MO_USE, /* Use location (REG or MEM). */ MO_USE_NO_VAR,/* Use location which is not associated with a variable or the variable is not trackable. */ + MO_LOC_MAIN, /* Use location from the debug insn. */ + MO_LOC_USE, /* The location appears in a debug insn, but it's not + the location of the debug insn's decl. */ MO_SET, /* Set location. */ MO_COPY, /* Copy the same portion of a variable from one location to another. */ @@ -836,14 +839,12 @@ var_debug_decl (tree decl) return decl; } -/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ +/* Set the register LOC to contain DECL, OFFSET. */ static void -var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized, - rtx set_src) +var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized, + tree decl, HOST_WIDE_INT offset, rtx set_src) { - tree decl = REG_EXPR (loc); - HOST_WIDE_INT offset = REG_OFFSET (loc); attrs node; decl = var_debug_decl (decl); @@ -856,6 +857,18 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized, set_variable_part (set, loc, decl, offset, initialized, set_src); } +/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ + +static void +var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized, + rtx set_src) +{ + tree decl = REG_EXPR (loc); + HOST_WIDE_INT offset = REG_OFFSET (loc); + + var_reg_decl_set (set, loc, initialized, decl, offset, set_src); +} + static int get_init_value (dataflow_set *set, rtx loc, tree decl) { @@ -975,6 +988,17 @@ var_regno_delete (dataflow_set *set, int regno) *reg = NULL; } +/* Set the location of DECL, OFFSET as the MEM LOC. */ + +static void +var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized, + tree decl, HOST_WIDE_INT offset, rtx set_src) +{ + decl = var_debug_decl (decl); + + set_variable_part (set, loc, decl, offset, initialized, set_src); +} + /* Set the location part of variable MEM_EXPR (LOC) in dataflow set SET to LOC. Adjust the address first if it is stack pointer based. */ @@ -986,9 +1010,7 @@ var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized, tree decl = MEM_EXPR (loc); HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; - decl = var_debug_decl (decl); - - set_variable_part (set, loc, decl, offset, initialized, set_src); + var_mem_decl_set (set, loc, initialized, decl, offset, set_src); } /* Delete and set the location part of variable MEM_EXPR (LOC) in @@ -1672,27 +1694,72 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) return (expr == expr2 && offset == offset2); } +/* Determine what kind of micro operation to choose for a USE. Return + MO_CLOBBER if no micro operation is to be generated. */ -/* Count uses (register and memory references) LOC which will be tracked. - INSN is instruction which the LOC is part of. */ - -static int -count_uses (rtx *loc, void *insn) +static enum micro_operation_type +use_type (rtx *loc, rtx insn) { - basic_block bb = BLOCK_FOR_INSN ((rtx) insn); + tree expr; + + if (DEBUG_INSN_P (insn)) + { + if (!VAR_LOC_UNKNOWN_P (*loc) && !REG_P (*loc) && !MEM_P (*loc)) + return MO_CLOBBER; - if (REG_P (*loc)) + expr = INSN_VAR_LOCATION_DECL (insn); + + if (!track_expr_p (expr)) + return MO_CLOBBER; + + if (&INSN_VAR_LOCATION_LOC (insn) == loc) + return MO_LOC_MAIN; + else + return MO_LOC_USE; + } + else if (REG_P (*loc)) { gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER); - VTI (bb)->n_mos++; + + expr = REG_EXPR (*loc); + + if (!expr) + return MO_USE_NO_VAR; + else if (var_debug_value_for_decl (expr)) + return MO_CLOBBER; + else if (track_expr_p (expr)) + return MO_USE; + else + return MO_USE_NO_VAR; } - else if (MEM_P (*loc) - && MEM_EXPR (*loc) - && track_expr_p (MEM_EXPR (*loc))) + else if (MEM_P (*loc)) { - VTI (bb)->n_mos++; + expr = MEM_EXPR (*loc); + + if (!expr) + return MO_CLOBBER; + else if (var_debug_value_for_decl (expr)) + return MO_CLOBBER; + else if (track_expr_p (expr)) + return MO_USE; + else + return MO_CLOBBER; } + return MO_CLOBBER; +} + +/* Count uses (register and memory references) LOC which will be tracked. + INSN is instruction which the LOC is part of. */ + +static int +count_uses (rtx *loc, void *data) +{ + rtx insn = (rtx) data; + + if (use_type (loc, insn) != MO_CLOBBER) + VTI (BLOCK_FOR_INSN (insn))->n_mos++; + return 0; } @@ -1717,28 +1784,19 @@ count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *insn) to VTI (bb)->mos. INSN is instruction which the LOC is part of. */ static int -add_uses (rtx *loc, void *insn) +add_uses (rtx *loc, void *data) { - if (REG_P (*loc)) - { - basic_block bb = BLOCK_FOR_INSN ((rtx) insn); - micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; + rtx insn = (rtx)data; + enum micro_operation_type type = use_type (loc, insn); - mo->type = ((REG_EXPR (*loc) && track_expr_p (REG_EXPR (*loc))) - ? MO_USE : MO_USE_NO_VAR); - mo->u.loc = *loc; - mo->insn = (rtx) insn; - } - else if (MEM_P (*loc) - && MEM_EXPR (*loc) - && track_expr_p (MEM_EXPR (*loc))) + if (type != MO_CLOBBER) { - basic_block bb = BLOCK_FOR_INSN ((rtx) insn); + basic_block bb = BLOCK_FOR_INSN (insn); micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; - mo->type = MO_USE; + mo->type = type; mo->u.loc = *loc; - mo->insn = (rtx) insn; + mo->insn = insn; } return 0; @@ -1759,6 +1817,9 @@ add_uses_1 (rtx *x, void *insn) static void add_stores (rtx loc, const_rtx expr, void *insn) { + if (use_type (&loc, (rtx) insn) == MO_CLOBBER) + return; + if (REG_P (loc)) { basic_block bb = BLOCK_FOR_INSN ((rtx) insn); @@ -1944,6 +2005,32 @@ compute_bb_dataflow (basic_block bb) } break; + case MO_LOC_MAIN: + { + rtx loc = VTI (bb)->mos[i].u.loc; + rtx insn = VTI (bb)->mos[i].insn; + + if (VAR_LOC_UNKNOWN_P (loc)) + clobber_variable_part (out, NULL_RTX, + INSN_VAR_LOCATION_DECL (insn), 0, + NULL_RTX); + else if (REG_P (loc)) + var_reg_decl_set (out, loc, VAR_INIT_STATUS_INITIALIZED, + INSN_VAR_LOCATION_DECL (insn), 0, NULL_RTX); + else if (MEM_P (loc)) + var_mem_decl_set (out, loc, VAR_INIT_STATUS_INITIALIZED, + INSN_VAR_LOCATION_DECL (insn), 0, NULL_RTX); + } + break; + + case MO_LOC_USE: + { + /* ??? Note that this reg or mem is part of the value of + decl such that, when it's set, we know the variable + no longer holds its value. */ + } + break; + case MO_SET: { rtx loc = VTI (bb)->mos[i].u.loc; @@ -2867,8 +2954,8 @@ emit_notes_in_bb (basic_block bb) case MO_USE: { rtx loc = VTI (bb)->mos[i].u.loc; - enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED; + if (! flag_var_tracking_uninit) status = VAR_INIT_STATUS_INITIALIZED; if (GET_CODE (loc) == REG) @@ -2880,6 +2967,42 @@ emit_notes_in_bb (basic_block bb) } break; + case MO_LOC_MAIN: + { + rtx loc = VTI (bb)->mos[i].u.loc; + rtx insn = VTI (bb)->mos[i].insn, next; + + if (VAR_LOC_UNKNOWN_P (loc)) + clobber_variable_part (&set, NULL_RTX, + INSN_VAR_LOCATION_DECL (insn), 0, + NULL_RTX); + else if (REG_P (loc)) + var_reg_decl_set (&set, loc, VAR_INIT_STATUS_INITIALIZED, + INSN_VAR_LOCATION_DECL (insn), 0, NULL_RTX); + else if (MEM_P (loc)) + var_mem_decl_set (&set, loc, VAR_INIT_STATUS_INITIALIZED, + INSN_VAR_LOCATION_DECL (insn), 0, NULL_RTX); + + for (next = NEXT_INSN (insn); + next && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (next); + next = NEXT_INSN (next)) + if (DEBUG_INSN_P (next)) + insn = next; + else if (!NOTE_P (next)) + break; + + emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); + } + break; + + case MO_LOC_USE: + { + /* ??? Note that this reg or mem is part of the value of + decl such that, when it's set, we know the variable + no longer holds its value. */ + } + break; + case MO_SET: { rtx loc = VTI (bb)->mos[i].u.loc; @@ -3087,6 +3210,7 @@ vt_initialize (void) { rtx insn; HOST_WIDE_INT pre, post = 0; + int count; /* Count the number of micro operations. */ VTI (bb)->n_mos = 0; @@ -3110,6 +3234,8 @@ vt_initialize (void) } } + count = VTI (bb)->n_mos; + /* Add the micro-operations to the array. */ VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos); VTI (bb)->n_mos = 0; @@ -3137,12 +3263,13 @@ vt_initialize (void) note_uses (&PATTERN (insn), add_uses_1, insn); n2 = VTI (bb)->n_mos - 1; - /* Order the MO_USEs to be before MO_USE_NO_VARs. */ + /* Order the MO_USEs to be before MO_USE_NO_VARs, + MO_LOC_MAIN and MO_LOC_USE. */ while (n1 < n2) { while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE) n1++; - while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR) + while (n1 < n2 && VTI (bb)->mos[n2].type != MO_USE) n2--; if (n1 < n2) { @@ -3197,6 +3324,7 @@ vt_initialize (void) } } } + gcc_assert (count == VTI (bb)->n_mos); } /* Init the IN and OUT sets. */ @@ -3219,6 +3347,38 @@ vt_initialize (void) vt_add_function_parameters (); } +/* Get rid of all debug insns from the insn stream. */ + +static void +delete_debug_insns (void) +{ + basic_block bb; + rtx insn, next; + + if (!MAY_HAVE_DEBUG_INSNS) + return; + + FOR_EACH_BB (bb) + { + FOR_BB_INSNS_SAFE (bb, insn, next) + if (DEBUG_INSN_P (insn)) + delete_insn (insn); + } +} + +/* Run a fast, BB-local only version of var tracking, to take care of + information that we don't do global analysis on, such that not all + information is lost. If SKIPPED holds, we're skipping the global + pass entirely, so we should try to use information it would have + handled as well.. */ + +static void +vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED) +{ + /* ??? Just skip it all for now. */ + delete_debug_insns (); +} + /* Free the data structures needed for variable tracking. */ static void @@ -3249,7 +3409,10 @@ unsigned int variable_tracking_main (void) { if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20) - return 0; + { + vt_debug_insns_local (true); + return 0; + } mark_dfs_back_edges (); vt_initialize (); @@ -3258,6 +3421,7 @@ variable_tracking_main (void) if (!vt_stack_adjustments ()) { vt_finalize (); + vt_debug_insns_local (true); return 0; } } @@ -3272,6 +3436,7 @@ variable_tracking_main (void) } vt_finalize (); + vt_debug_insns_local (false); return 0; } |