X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gcc%2Fvar-tracking.c;h=ce1d92027c452d503c33108db2e90b69403ad7f9;hb=7adcbafe45f8001b698967defe682687b52c0007;hp=fdad87459fb7e4fbe7a16ef8a8049a2cb3339f4b;hpb=191816a36b90e5230ae285940f7ad1e225b66487;p=thirdparty%2Fgcc.git diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index fdad87459fb7..ce1d92027c45 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-2016 Free Software Foundation, Inc. + Copyright (C) 2002-2022 Free Software Foundation, Inc. This file is part of GCC. @@ -95,6 +95,7 @@ #include "cfghooks.h" #include "alloc-pool.h" #include "tree-pass.h" +#include "memmodel.h" #include "tm_p.h" #include "insn-config.h" #include "regs.h" @@ -110,13 +111,13 @@ #include "tree-dfa.h" #include "tree-ssa.h" #include "cselib.h" -#include "params.h" #include "tree-pretty-print.h" #include "rtl-iter.h" #include "fibonacci_heap.h" +#include "print-rtl.h" +#include "function-abi.h" typedef fibonacci_heap bb_heap_t; -typedef fibonacci_node bb_heap_node_t; /* var-tracking.c assumes that tree code with the same value as VALUE rtx code has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl. @@ -303,6 +304,9 @@ struct expand_depth int entryvals; }; +/* Type for dependencies actively used when expand FROM into cur_loc. */ +typedef vec deps_vec; + /* This data structure is allocated for one-part variables at the time of emitting notes. */ struct onepart_aux @@ -323,7 +327,7 @@ struct onepart_aux /* The depth of the cur_loc expression. */ expand_depth depth; /* Dependencies actively used when expand FROM into cur_loc. */ - vec deps; + deps_vec deps; }; /* Structure describing one part of variable. */ @@ -389,8 +393,16 @@ struct variable /* Pointer to the BB's information specific to variable tracking pass. */ #define VTI(BB) ((variable_tracking_info *) (BB)->aux) -/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */ -#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0) +/* Return MEM_OFFSET (MEM) as a HOST_WIDE_INT, or 0 if we can't. */ + +static inline HOST_WIDE_INT +int_mem_offset (const_rtx mem) +{ + HOST_WIDE_INT offset; + if (MEM_OFFSET_KNOWN_P (mem) && MEM_OFFSET (mem).is_constant (&offset)) + return offset; + return 0; +} #if CHECKING_P && (GCC_VERSION >= 2007) @@ -424,10 +436,16 @@ struct variable : NULL) #define VAR_LOC_FROM(var) (VAR_LOC_1PAUX (var)->from) #define VAR_LOC_DEPTH(var) (VAR_LOC_1PAUX (var)->depth) -#define VAR_LOC_DEP_VEC(var) (VAR_LOC_1PAUX (var) \ - ? &VAR_LOC_1PAUX (var)->deps \ - : NULL) +#define VAR_LOC_DEP_VEC(var) var_loc_dep_vec (var) +/* Implements the VAR_LOC_DEP_VEC above as a function to work around + a bogus -Wnonnull (PR c/95554). */ + +static inline deps_vec* +var_loc_dep_vec (variable *var) +{ + return VAR_LOC_1PAUX (var) ? &VAR_LOC_1PAUX (var)->deps : NULL; +} typedef unsigned int dvuid; @@ -665,7 +683,6 @@ static bool dataflow_set_different (dataflow_set *, dataflow_set *); static void dataflow_set_destroy (dataflow_set *); static bool track_expr_p (tree, bool); -static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT); static void add_uses_1 (rtx *, void *); static void add_stores (rtx, const_rtx, void *); static bool compute_bb_dataflow (basic_block); @@ -696,7 +713,6 @@ static void delete_variable_part (dataflow_set *, rtx, static void emit_notes_in_bb (basic_block, dataflow_set *); static void vt_emit_notes (void); -static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *); static void vt_add_function_parameters (void); static bool vt_initialize (void); static void vt_finalize (void); @@ -910,19 +926,20 @@ static HOST_WIDE_INT cfa_base_offset; or hard_frame_pointer_rtx. */ static inline rtx -compute_cfa_pointer (HOST_WIDE_INT adjustment) +compute_cfa_pointer (poly_int64 adjustment) { return plus_constant (Pmode, cfa_base_rtx, adjustment + cfa_base_offset); } /* Adjustment for hard_frame_pointer_rtx to cfa base reg, or -1 if the replacement shouldn't be done. */ -static HOST_WIDE_INT hard_frame_pointer_adjustment = -1; +static poly_int64 hard_frame_pointer_adjustment = -1; /* Data for adjust_mems callback. */ -struct adjust_mem_data +class adjust_mem_data { +public: bool store; machine_mode mem_mode; HOST_WIDE_INT stack_adjust; @@ -957,6 +974,24 @@ use_narrower_mode_test (rtx x, const_rtx subreg) case MULT: break; case ASHIFT: + if (GET_MODE (XEXP (x, 1)) != VOIDmode) + { + enum machine_mode mode = GET_MODE (subreg); + rtx op1 = XEXP (x, 1); + enum machine_mode op1_mode = GET_MODE (op1); + if (GET_MODE_PRECISION (as_a (mode)) + < GET_MODE_PRECISION (as_a (op1_mode))) + { + poly_uint64 byte = subreg_lowpart_offset (mode, op1_mode); + if (GET_CODE (op1) == SUBREG || GET_CODE (op1) == CONCAT) + { + if (!simplify_subreg (mode, op1, op1_mode, byte)) + return false; + } + else if (!validate_subreg (mode, op1_mode, op1, byte)) + return false; + } + } iter.substitute (XEXP (x, 0)); break; default: @@ -969,7 +1004,7 @@ use_narrower_mode_test (rtx x, const_rtx subreg) /* Transform X into narrower mode MODE from wider mode WMODE. */ static rtx -use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode) +use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode) { rtx op0, op1; if (CONSTANT_P (x)) @@ -990,7 +1025,8 @@ use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode) /* Ensure shift amount is not wider than mode. */ if (GET_MODE (op1) == VOIDmode) op1 = lowpart_subreg (mode, op1, wmode); - else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1))) + else if (GET_MODE_PRECISION (mode) + < GET_MODE_PRECISION (as_a (GET_MODE (op1)))) op1 = lowpart_subreg (mode, op1, GET_MODE (op1)); return simplify_gen_binary (ASHIFT, mode, op0, op1); default: @@ -1003,10 +1039,12 @@ use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode) static rtx adjust_mems (rtx loc, const_rtx old_rtx, void *data) { - struct adjust_mem_data *amd = (struct adjust_mem_data *) data; + class adjust_mem_data *amd = (class adjust_mem_data *) data; rtx mem, addr = loc, tem; machine_mode mem_mode_save; bool store_save; + scalar_int_mode tem_mode, tem_subreg_mode; + poly_int64 size; switch (GET_CODE (loc)) { case REG: @@ -1020,7 +1058,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data) return compute_cfa_pointer (amd->stack_adjust); else if (loc == hard_frame_pointer_rtx && frame_pointer_needed - && hard_frame_pointer_adjustment != -1 + && maybe_ne (hard_frame_pointer_adjustment, -1) && cfa_base_rtx) return compute_cfa_pointer (hard_frame_pointer_adjustment); gcc_checking_assert (loc != virtual_incoming_args_rtx); @@ -1051,11 +1089,9 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data) return mem; case PRE_INC: case PRE_DEC: - addr = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0), - gen_int_mode (GET_CODE (loc) == PRE_INC - ? GET_MODE_SIZE (amd->mem_mode) - : -GET_MODE_SIZE (amd->mem_mode), - GET_MODE (loc))); + size = GET_MODE_SIZE (amd->mem_mode); + addr = plus_constant (GET_MODE (loc), XEXP (loc, 0), + GET_CODE (loc) == PRE_INC ? size : -size); /* FALLTHRU */ case POST_INC: case POST_DEC: @@ -1063,12 +1099,10 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data) addr = XEXP (loc, 0); gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode); addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data); - tem = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0), - gen_int_mode ((GET_CODE (loc) == PRE_INC - || GET_CODE (loc) == POST_INC) - ? GET_MODE_SIZE (amd->mem_mode) - : -GET_MODE_SIZE (amd->mem_mode), - GET_MODE (loc))); + size = GET_MODE_SIZE (amd->mem_mode); + tem = plus_constant (GET_MODE (loc), XEXP (loc, 0), + (GET_CODE (loc) == PRE_INC + || GET_CODE (loc) == POST_INC) ? size : -size); store_save = amd->store; amd->store = false; tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data); @@ -1115,22 +1149,20 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data) if (tem == NULL_RTX) tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc)); finish_subreg: - if (MAY_HAVE_DEBUG_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS && GET_CODE (tem) == SUBREG && (GET_CODE (SUBREG_REG (tem)) == PLUS || GET_CODE (SUBREG_REG (tem)) == MINUS || GET_CODE (SUBREG_REG (tem)) == MULT || GET_CODE (SUBREG_REG (tem)) == ASHIFT) - && (GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT - || GET_MODE_CLASS (GET_MODE (tem)) == MODE_PARTIAL_INT) - && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT - || GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_PARTIAL_INT) - && GET_MODE_PRECISION (GET_MODE (tem)) - < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (tem))) + && is_a (GET_MODE (tem), &tem_mode) + && is_a (GET_MODE (SUBREG_REG (tem)), + &tem_subreg_mode) + && (GET_MODE_PRECISION (tem_mode) + < GET_MODE_PRECISION (tem_subreg_mode)) && subreg_lowpart_p (tem) && use_narrower_mode_test (SUBREG_REG (tem), tem)) - return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem), - GET_MODE (SUBREG_REG (tem))); + return use_narrower_mode (SUBREG_REG (tem), tem_mode, tem_subreg_mode); return tem; case ASM_OPERANDS: /* Don't do any replacements in second and following @@ -1215,7 +1247,7 @@ adjust_insn (basic_block bb, rtx_insn *insn) amd.stack_adjust = -VTI (bb)->out.stack_adjust; amd.store = true; - note_stores (PATTERN (insn), adjust_mem_stores, &amd); + note_stores (insn, adjust_mem_stores, &amd); amd.store = false; if (GET_CODE (PATTERN (insn)) == PARALLEL @@ -1329,7 +1361,7 @@ dv_onepart_p (decl_or_value dv) { tree decl; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return NOT_ONEPART; if (dv_is_value_p (dv)) @@ -1810,8 +1842,7 @@ vars_copy (variable_table_type *dst, variable_table_type *src) static inline tree var_debug_decl (tree decl) { - if (decl && TREE_CODE (decl) == VAR_DECL - && DECL_HAS_DEBUG_EXPR_P (decl)) + if (decl && VAR_P (decl) && DECL_HAS_DEBUG_EXPR_P (decl)) { tree debugdecl = DECL_DEBUG_EXPR (decl); if (DECL_P (debugdecl)) @@ -1843,6 +1874,32 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized, set_variable_part (set, loc, dv, offset, initialized, set_src, iopt); } +/* Return true if we should track a location that is OFFSET bytes from + a variable. Store the constant offset in *OFFSET_OUT if so. */ + +static bool +track_offset_p (poly_int64 offset, HOST_WIDE_INT *offset_out) +{ + HOST_WIDE_INT const_offset; + if (!offset.is_constant (&const_offset) + || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1)) + return false; + *offset_out = const_offset; + return true; +} + +/* Return the offset of a register that track_offset_p says we + should track. */ + +static HOST_WIDE_INT +get_tracked_reg_offset (rtx loc) +{ + HOST_WIDE_INT offset; + if (!track_offset_p (REG_OFFSET (loc), &offset)) + gcc_unreachable (); + return offset; +} + /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ static void @@ -1850,7 +1907,7 @@ 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); + HOST_WIDE_INT offset = get_tracked_reg_offset (loc); var_reg_decl_set (set, loc, initialized, dv_from_decl (decl), offset, set_src, INSERT); @@ -1896,7 +1953,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify, enum var_init_status initialized, rtx set_src) { tree decl = REG_EXPR (loc); - HOST_WIDE_INT offset = REG_OFFSET (loc); + HOST_WIDE_INT offset = get_tracked_reg_offset (loc); attrs *node, *next; attrs **nextp; @@ -1937,10 +1994,10 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber) attrs **nextp = &set->regs[REGNO (loc)]; attrs *node, *next; - if (clobber) + HOST_WIDE_INT offset; + if (clobber && track_offset_p (REG_OFFSET (loc), &offset)) { tree decl = REG_EXPR (loc); - HOST_WIDE_INT offset = REG_OFFSET (loc); decl = var_debug_decl (decl); @@ -1983,7 +2040,7 @@ static bool negative_power_of_two_p (HOST_WIDE_INT i) { unsigned HOST_WIDE_INT x = -(unsigned HOST_WIDE_INT)i; - return x == (x & -x); + return pow2_or_zerop (x); } /* Strip constant offsets and alignments off of LOC. Return the base @@ -2127,7 +2184,7 @@ get_addr_from_local_cache (dataflow_set *set, rtx const loc) static rtx vt_canonicalize_addr (dataflow_set *set, rtx oloc) { - HOST_WIDE_INT ofst = 0; + poly_int64 ofst = 0, term; machine_mode mode = GET_MODE (oloc); rtx loc = oloc; rtx x; @@ -2136,9 +2193,9 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc) while (retry) { while (GET_CODE (loc) == PLUS - && GET_CODE (XEXP (loc, 1)) == CONST_INT) + && poly_int_rtx_p (XEXP (loc, 1), &term)) { - ofst += INTVAL (XEXP (loc, 1)); + ofst += term; loc = XEXP (loc, 0); } @@ -2163,10 +2220,11 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc) loc = get_addr_from_global_cache (loc); /* Consolidate plus_constants. */ - while (ofst && GET_CODE (loc) == PLUS - && GET_CODE (XEXP (loc, 1)) == CONST_INT) + while (maybe_ne (ofst, 0) + && GET_CODE (loc) == PLUS + && poly_int_rtx_p (XEXP (loc, 1), &term)) { - ofst += INTVAL (XEXP (loc, 1)); + ofst += term; loc = XEXP (loc, 0); } @@ -2182,12 +2240,10 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc) } /* Add OFST back in. */ - if (ofst) + if (maybe_ne (ofst, 0)) { /* Don't build new RTL if we can help it. */ - if (GET_CODE (oloc) == PLUS - && XEXP (oloc, 0) == loc - && INTVAL (XEXP (oloc, 1)) == ofst) + if (strip_offset (oloc, &term) == loc && known_eq (term, ofst)) return oloc; loc = plus_constant (mode, loc, ofst); @@ -2336,7 +2392,7 @@ var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized, rtx set_src) { tree decl = MEM_EXPR (loc); - HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); + HOST_WIDE_INT offset = int_mem_offset (loc); var_mem_decl_set (set, loc, initialized, dv_from_decl (decl), offset, set_src, INSERT); @@ -2354,7 +2410,7 @@ var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify, enum var_init_status initialized, rtx set_src) { tree decl = MEM_EXPR (loc); - HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); + HOST_WIDE_INT offset = int_mem_offset (loc); clobber_overlapping_mems (set, loc); decl = var_debug_decl (decl); @@ -2375,7 +2431,7 @@ static void var_mem_delete (dataflow_set *set, rtx loc, bool clobber) { tree decl = MEM_EXPR (loc); - HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); + HOST_WIDE_INT offset = int_mem_offset (loc); clobber_overlapping_mems (set, loc); decl = var_debug_decl (decl); @@ -2394,7 +2450,6 @@ unsuitable_loc (rtx loc) { case PC: case SCRATCH: - case CC0: case ASM_INPUT: case ASM_OPERANDS: return true; @@ -2555,7 +2610,7 @@ val_reset (dataflow_set *set, decl_or_value dv) { decl_or_value cdv = dv_from_value (cval); - /* Keep the remaining values connected, accummulating links + /* Keep the remaining values connected, accumulating links in the canonical value. */ for (node = var->var_part[0].loc_chain; node; node = node->next) { @@ -3490,6 +3545,12 @@ loc_cmp (rtx x, rtx y) else return 1; + case 'p': + r = compare_sizes_for_sort (SUBREG_BYTE (x), SUBREG_BYTE (y)); + if (r != 0) + return r; + break; + case 'V': case 'E': /* Compare the vector length first. */ @@ -4618,7 +4679,7 @@ find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars) for (node = var->var_part[0].loc_chain; node; node = node->next) if (MEM_P (node->loc) && MEM_EXPR (node->loc) == expr - && INT_MEM_OFFSET (node->loc) == 0) + && int_mem_offset (node->loc) == 0) { where = node; break; @@ -4683,7 +4744,7 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set) /* We want to remove dying MEMs that don't refer to DECL. */ if (GET_CODE (loc->loc) == MEM && (MEM_EXPR (loc->loc) != decl - || INT_MEM_OFFSET (loc->loc) != 0) + || int_mem_offset (loc->loc) != 0) && mem_dies_at_call (loc->loc)) break; /* We want to move here MEMs that do refer to DECL. */ @@ -4727,7 +4788,7 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set) if (GET_CODE (loc->loc) != MEM || (MEM_EXPR (loc->loc) == decl - && INT_MEM_OFFSET (loc->loc) == 0) + && int_mem_offset (loc->loc) == 0) || !mem_dies_at_call (loc->loc)) { if (old_loc != loc->loc && emit_notes) @@ -4846,15 +4907,14 @@ dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn) { unsigned int r; hard_reg_set_iterator hrsi; - HARD_REG_SET invalidated_regs; - get_call_reg_set_usage (call_insn, &invalidated_regs, - regs_invalidated_by_call); + HARD_REG_SET callee_clobbers + = insn_callee_abi (call_insn).full_reg_clobbers (); - EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi) + EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, r, hrsi) var_regno_delete (set, r); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { set->traversed_vars = set->vars; shared_hash_htab (set->vars) @@ -5145,7 +5205,7 @@ track_expr_p (tree expr, bool need_rtl) return DECL_RTL_SET_P (expr); /* If EXPR is not a parameter or a variable do not track it. */ - if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL) + if (!VAR_P (expr) && TREE_CODE (expr) != PARM_DECL) return 0; /* It also must have a name... */ @@ -5161,7 +5221,7 @@ track_expr_p (tree expr, bool need_rtl) don't need to track this expression if the ultimate declaration is ignored. */ realdecl = expr; - if (TREE_CODE (realdecl) == VAR_DECL && DECL_HAS_DEBUG_EXPR_P (realdecl)) + if (VAR_P (realdecl) && DECL_HAS_DEBUG_EXPR_P (realdecl)) { realdecl = DECL_DEBUG_EXPR (realdecl); if (!DECL_P (realdecl)) @@ -5170,20 +5230,20 @@ track_expr_p (tree expr, bool need_rtl) || (TREE_CODE (realdecl) == MEM_REF && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR)) { - HOST_WIDE_INT bitsize, bitpos, maxsize; + HOST_WIDE_INT bitsize, bitpos; bool reverse; tree innerdecl - = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, - &maxsize, &reverse); - if (!DECL_P (innerdecl) + = get_ref_base_and_extent_hwi (realdecl, &bitpos, + &bitsize, &reverse); + if (!innerdecl + || !DECL_P (innerdecl) || DECL_IGNORED_P (innerdecl) /* Do not track declarations for parts of tracked record parameters since we want to track them as a whole. */ || tracked_record_parameter_p (innerdecl) || TREE_STATIC (innerdecl) - || bitsize <= 0 - || bitpos + bitsize > 256 - || bitsize != maxsize) + || bitsize == 0 + || bitpos + bitsize > 256) return 0; else realdecl = expr; @@ -5220,11 +5280,12 @@ track_expr_p (tree expr, bool need_rtl) if (decl_rtl && MEM_P (decl_rtl)) { /* Do not track structures and arrays. */ - if (GET_MODE (decl_rtl) == BLKmode - || AGGREGATE_TYPE_P (TREE_TYPE (realdecl))) + if ((GET_MODE (decl_rtl) == BLKmode + || AGGREGATE_TYPE_P (TREE_TYPE (realdecl))) + && !tracked_record_parameter_p (realdecl)) return 0; if (MEM_SIZE_KNOWN_P (decl_rtl) - && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS) + && maybe_gt (MEM_SIZE (decl_rtl), MAX_VAR_PARTS)) return 0; } @@ -5237,10 +5298,10 @@ track_expr_p (tree expr, bool need_rtl) EXPR+OFFSET. */ static bool -same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) +same_variable_part_p (rtx loc, tree expr, poly_int64 offset) { tree expr2; - HOST_WIDE_INT offset2; + poly_int64 offset2; if (! DECL_P (expr)) return false; @@ -5253,7 +5314,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) else if (MEM_P (loc)) { expr2 = MEM_EXPR (loc); - offset2 = INT_MEM_OFFSET (loc); + offset2 = int_mem_offset (loc); } else return false; @@ -5264,7 +5325,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) expr = var_debug_decl (expr); expr2 = var_debug_decl (expr2); - return (expr == expr2 && offset == offset2); + return (expr == expr2 && known_eq (offset, offset2)); } /* LOC is a REG or MEM that we would like to track if possible. @@ -5278,7 +5339,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) from EXPR in *OFFSET_OUT (if nonnull). */ static bool -track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p, +track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p, machine_mode *mode_out, HOST_WIDE_INT *offset_out) { machine_mode mode; @@ -5294,7 +5355,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p, machine_mode pseudo_mode; pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc)); - if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode)) + if (paradoxical_subreg_p (mode, pseudo_mode)) { offset += byte_lowpart_offset (pseudo_mode, mode); mode = pseudo_mode; @@ -5308,23 +5369,24 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p, because the real and imaginary parts are represented as separate pseudo registers, even if the whole complex value fits into one hard register. */ - if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr)) + if ((paradoxical_subreg_p (mode, DECL_MODE (expr)) || (store_reg_p && !COMPLEX_MODE_P (DECL_MODE (expr)) - && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1)) - && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0) + && hard_regno_nregs (REGNO (loc), DECL_MODE (expr)) == 1)) + && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0)) { mode = DECL_MODE (expr); offset = 0; } - if (offset < 0 || offset >= MAX_VAR_PARTS) + HOST_WIDE_INT const_offset; + if (!track_offset_p (offset, &const_offset)) return false; if (mode_out) *mode_out = mode; if (offset_out) - *offset_out = offset; + *offset_out = const_offset; return true; } @@ -5335,7 +5397,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p, static rtx var_lowpart (machine_mode mode, rtx loc) { - unsigned int offset, reg_offset, regno; + unsigned int regno; if (GET_MODE (loc) == mode) return loc; @@ -5343,12 +5405,12 @@ var_lowpart (machine_mode mode, rtx loc) if (!REG_P (loc) && !MEM_P (loc)) return NULL; - offset = byte_lowpart_offset (mode, GET_MODE (loc)); + poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc)); if (MEM_P (loc)) return adjust_address_nv (loc, mode, offset); - reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc)); + poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc)); regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc), reg_offset, mode); return gen_rtx_REG_offset (loc, mode, regno, offset); @@ -5521,13 +5583,13 @@ use_type (rtx loc, struct count_use_info *cui, machine_mode *modep) return MO_CLOBBER; else if (target_for_debug_bind (var_debug_decl (expr))) return MO_CLOBBER; - else if (track_loc_p (loc, expr, INT_MEM_OFFSET (loc), + else if (track_loc_p (loc, expr, int_mem_offset (loc), false, modep, NULL) /* Multi-part variables shouldn't refer to one-part variable names such as VALUEs (never happens) or DEBUG_EXPRs (only happens in the presence of debug insns). */ - && (!MAY_HAVE_DEBUG_INSNS + && (!MAY_HAVE_DEBUG_BIND_INSNS || !rtx_debug_expr_p (XEXP (loc, 0)))) return MO_USE; else @@ -5598,7 +5660,6 @@ non_suitable_const (const_rtx x) case DEBUG_EXPR: case PC: case SCRATCH: - case CC0: case ASM_INPUT: case ASM_OPERANDS: return true; @@ -5788,7 +5849,7 @@ add_uses_1 (rtx *x, void *cui) compile time for ridiculously complex expressions, although they're seldom useful, and they may often have to be discarded as not representable anyway. */ -#define EXPR_USE_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH)) +#define EXPR_USE_DEPTH (param_max_vartrack_expr_depth) /* Attempt to reverse the EXPR operation in the debug info and record it in the cselib table. Say for reg1 = reg2 + 6 even when reg2 is @@ -5848,7 +5909,7 @@ reverse_op (rtx val, const_rtx expr, rtx_insn *insn) && (GET_CODE (l->loc) != CONST || !references_value_p (l->loc, 0))) return; /* Avoid creating too large locs lists. */ - else if (count == PARAM_VALUE (PARAM_MAX_VARTRACK_REVERSE_OP_SIZE)) + else if (count == param_max_vartrack_reverse_op_size) return; switch (GET_CODE (src)) @@ -5925,7 +5986,9 @@ add_stores (rtx loc, const_rtx expr, void *cuip) mo.type = MO_CLOBBER; mo.u.loc = loc; if (GET_CODE (expr) == SET - && SET_DEST (expr) == loc + && (SET_DEST (expr) == loc + || (GET_CODE (SET_DEST (expr)) == STRICT_LOW_PART + && XEXP (SET_DEST (expr), 0) == loc)) && !unsuitable_loc (SET_SRC (expr)) && find_use_val (loc, mode, cui)) { @@ -6016,7 +6079,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip) rtx xexpr = gen_rtx_SET (loc, src); if (same_variable_part_p (SET_SRC (xexpr), MEM_EXPR (loc), - INT_MEM_OFFSET (loc))) + int_mem_offset (loc))) mo.type = MO_COPY; else mo.type = MO_SET; @@ -6055,10 +6118,25 @@ add_stores (rtx loc, const_rtx expr, void *cuip) } if (loc == stack_pointer_rtx - && hard_frame_pointer_adjustment != -1 + && (maybe_ne (hard_frame_pointer_adjustment, -1) + || (!frame_pointer_needed && !ACCUMULATE_OUTGOING_ARGS)) && preserve) cselib_set_value_sp_based (v); + /* Don't record MO_VAL_SET for VALUEs that can be described using + cfa_base_rtx or cfa_base_rtx + CONST_INT, cselib already knows + all the needed equivalences and they shouldn't change depending + on which register holds that VALUE in some instruction. */ + if (!frame_pointer_needed + && cfa_base_rtx + && cselib_sp_derived_value_p (v) + && loc == stack_pointer_rtx) + { + if (preserve) + preserve_value (v); + return; + } + nloc = replace_expr_with_values (oloc); if (nloc) oloc = nloc; @@ -6235,14 +6313,12 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) && targetm.calls.struct_value_rtx (type, 0) == 0) { tree struct_addr = build_pointer_type (TREE_TYPE (type)); - machine_mode mode = TYPE_MODE (struct_addr); + function_arg_info arg (struct_addr, /*named=*/true); rtx reg; INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl, nargs + 1); - reg = targetm.calls.function_arg (args_so_far, mode, - struct_addr, true); - targetm.calls.function_arg_advance (args_so_far, mode, - struct_addr, true); + reg = targetm.calls.function_arg (args_so_far, arg); + targetm.calls.function_arg_advance (args_so_far, arg); if (reg == NULL_RTX) { for (; link; link = XEXP (link, 1)) @@ -6260,11 +6336,9 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) nargs); if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node) { - machine_mode mode; t = TYPE_ARG_TYPES (type); - mode = TYPE_MODE (TREE_VALUE (t)); - this_arg = targetm.calls.function_arg (args_so_far, mode, - TREE_VALUE (t), true); + function_arg_info arg (TREE_VALUE (t), /*named=*/true); + this_arg = targetm.calls.function_arg (args_so_far, arg); if (this_arg && !REG_P (this_arg)) this_arg = NULL_RTX; else if (this_arg == NULL_RTX) @@ -6300,18 +6374,19 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) else if (REG_P (x)) { cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode); + scalar_int_mode mode; if (val && cselib_preserved_value_p (val)) item = val->val_rtx; - else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT - || GET_MODE_CLASS (GET_MODE (x)) == MODE_PARTIAL_INT) + else if (is_a (GET_MODE (x), &mode)) { - machine_mode mode = GET_MODE (x); - - while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode - && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD) + opt_scalar_int_mode mode_iter; + FOR_EACH_WIDER_MODE (mode_iter, mode) { - rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0); + mode = mode_iter.require (); + if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD) + break; + rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0); if (reg == NULL_RTX || !REG_P (reg)) continue; val = cselib_lookup (reg, mode, 0, VOIDmode); @@ -6330,7 +6405,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) if (!frame_pointer_needed) { - struct adjust_mem_data amd; + class adjust_mem_data amd; amd.mem_mode = VOIDmode; amd.stack_adjust = -VTI (bb)->out.stack_adjust; amd.store = true; @@ -6346,8 +6421,9 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) { /* For non-integer stack argument see also if they weren't initialized by integers. */ - machine_mode imode = int_mode_for_mode (GET_MODE (mem)); - if (imode != GET_MODE (mem) && imode != BLKmode) + scalar_int_mode imode; + if (int_mode_for_mode (GET_MODE (mem)).exists (&imode) + && imode != GET_MODE (mem)) { val = cselib_lookup (adjust_address_nv (mem, imode, 0), imode, 0, VOIDmode); @@ -6370,30 +6446,24 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) } if (t && t != void_list_node) { - tree argtype = TREE_VALUE (t); - machine_mode mode = TYPE_MODE (argtype); rtx reg; - if (pass_by_reference (&args_so_far_v, mode, argtype, true)) - { - argtype = build_pointer_type (argtype); - mode = TYPE_MODE (argtype); - } - reg = targetm.calls.function_arg (args_so_far, mode, - argtype, true); - if (TREE_CODE (argtype) == REFERENCE_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (argtype)) + function_arg_info arg (TREE_VALUE (t), /*named=*/true); + apply_pass_by_reference_rules (&args_so_far_v, arg); + reg = targetm.calls.function_arg (args_so_far, arg); + if (TREE_CODE (arg.type) == REFERENCE_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (arg.type)) && reg && REG_P (reg) - && GET_MODE (reg) == mode - && (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) + && GET_MODE (reg) == arg.mode + && (GET_MODE_CLASS (arg.mode) == MODE_INT + || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT) && REG_P (x) && REGNO (x) == REGNO (reg) - && GET_MODE (x) == mode + && GET_MODE (x) == arg.mode && item) { machine_mode indmode - = TYPE_MODE (TREE_TYPE (argtype)); + = TYPE_MODE (TREE_TYPE (arg.type)); rtx mem = gen_rtx_MEM (indmode, x); cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode); if (val && cselib_preserved_value_p (val)) @@ -6433,8 +6503,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) } } } - targetm.calls.function_arg_advance (args_so_far, mode, - argtype, true); + targetm.calls.function_arg_advance (args_so_far, arg); t = TREE_CHAIN (t); } } @@ -6583,7 +6652,7 @@ add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_sets) insert notes before it without worrying about any notes that MO_USEs might emit after the insn. */ cui.store_p = true; - note_stores (PATTERN (insn), add_stores, &cui); + note_stores (insn, add_stores, &cui); n2 = VTI (bb)->mos.length () - 1; mos = VTI (bb)->mos.address (); @@ -6690,7 +6759,7 @@ compute_bb_dataflow (basic_block bb) dataflow_set_copy (&old_out, out); dataflow_set_copy (out, in); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) local_get_addr_cache = new hash_map; FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo) @@ -6972,7 +7041,7 @@ compute_bb_dataflow (basic_block bb) } } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { delete local_get_addr_cache; local_get_addr_cache = NULL; @@ -7005,61 +7074,75 @@ vt_find_locations (void) int *rc_order; int i; int htabsz = 0; - int htabmax = PARAM_VALUE (PARAM_MAX_VARTRACK_SIZE); + int htabmax = param_max_vartrack_size; bool success = true; + unsigned int n_blocks_processed = 0; timevar_push (TV_VAR_TRACKING_DATAFLOW); /* Compute reverse completion order of depth first search of the CFG so that the data-flow runs faster. */ rc_order = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS); bb_order = XNEWVEC (int, last_basic_block_for_fn (cfun)); - pre_and_rev_post_order_compute (NULL, rc_order, false); - for (i = 0; i < n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS; i++) + auto_bitmap exit_bbs; + bitmap_set_bit (exit_bbs, EXIT_BLOCK); + auto_vec > toplevel_scc_extents; + int n = rev_post_order_and_mark_dfs_back_seme + (cfun, single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), exit_bbs, true, + rc_order, &toplevel_scc_extents); + for (i = 0; i < n; i++) bb_order[rc_order[i]] = i; - free (rc_order); - auto_sbitmap visited (last_basic_block_for_fn (cfun)); in_worklist = sbitmap_alloc (last_basic_block_for_fn (cfun)); in_pending = sbitmap_alloc (last_basic_block_for_fn (cfun)); bitmap_clear (in_worklist); + bitmap_clear (in_pending); + + /* We're performing the dataflow iteration independently over the + toplevel SCCs plus leading non-cyclic entry blocks and separately + over the tail. That ensures best memory locality and the least + number of visited blocks. */ + unsigned extent = 0; + int curr_start = -1; + int curr_end = -1; + do + { + curr_start = curr_end + 1; + if (toplevel_scc_extents.length () <= extent) + curr_end = n - 1; + else + curr_end = toplevel_scc_extents[extent++].second; - FOR_EACH_BB_FN (bb, cfun) - pending->insert (bb_order[bb->index], bb); - bitmap_ones (in_pending); - - while (success && !pending->empty ()) - { - std::swap (worklist, pending); - std::swap (in_worklist, in_pending); - - bitmap_clear (visited); + for (int i = curr_start; i <= curr_end; ++i) + { + pending->insert (i, BASIC_BLOCK_FOR_FN (cfun, rc_order[i])); + bitmap_set_bit (in_pending, rc_order[i]); + } - while (!worklist->empty ()) + while (success && !pending->empty ()) { - bb = worklist->extract_min (); - bitmap_clear_bit (in_worklist, bb->index); - gcc_assert (!bitmap_bit_p (visited, bb->index)); - if (!bitmap_bit_p (visited, bb->index)) + std::swap (worklist, pending); + std::swap (in_worklist, in_pending); + + while (!worklist->empty ()) { bool changed; edge_iterator ei; int oldinsz, oldoutsz; - bitmap_set_bit (visited, bb->index); + bb = worklist->extract_min (); + bitmap_clear_bit (in_worklist, bb->index); if (VTI (bb)->in.vars) { - htabsz - -= shared_hash_htab (VTI (bb)->in.vars)->size () - + shared_hash_htab (VTI (bb)->out.vars)->size (); + htabsz -= (shared_hash_htab (VTI (bb)->in.vars)->size () + + shared_hash_htab (VTI (bb)->out.vars)->size ()); oldinsz = shared_hash_htab (VTI (bb)->in.vars)->elements (); - oldoutsz - = shared_hash_htab (VTI (bb)->out.vars)->elements (); + oldoutsz = shared_hash_htab (VTI (bb)->out.vars)->elements (); } else oldinsz = oldoutsz = 0; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { dataflow_set *in = &VTI (bb)->in, *first_out = NULL; bool first = true, adjust = false; @@ -7115,15 +7198,16 @@ vt_find_locations (void) } changed = compute_bb_dataflow (bb); - htabsz += shared_hash_htab (VTI (bb)->in.vars)->size () - + shared_hash_htab (VTI (bb)->out.vars)->size (); + n_blocks_processed++; + htabsz += (shared_hash_htab (VTI (bb)->in.vars)->size () + + shared_hash_htab (VTI (bb)->out.vars)->size ()); if (htabmax && htabsz > htabmax) { - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) inform (DECL_SOURCE_LOCATION (cfun->decl), "variable tracking size limit exceeded with " - "-fvar-tracking-assignments, retrying without"); + "%<-fvar-tracking-assignments%>, retrying without"); else inform (DECL_SOURCE_LOCATION (cfun->decl), "variable tracking size limit exceeded"); @@ -7138,8 +7222,11 @@ vt_find_locations (void) if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun)) continue; - if (bitmap_bit_p (visited, e->dest->index)) + /* Iterate to an earlier block in RPO in the next + round, iterate to the same block immediately. */ + if (bb_order[e->dest->index] < bb_order[bb->index]) { + gcc_assert (bb_order[e->dest->index] >= curr_start); if (!bitmap_bit_p (in_pending, e->dest->index)) { /* Send E->DEST to next round. */ @@ -7148,9 +7235,11 @@ vt_find_locations (void) e->dest); } } - else if (!bitmap_bit_p (in_worklist, e->dest->index)) + else if (bb_order[e->dest->index] <= curr_end + && !bitmap_bit_p (in_worklist, e->dest->index)) { - /* Add E->DEST to current round. */ + /* Add E->DEST to current round or delay + processing if it is in the next SCC. */ bitmap_set_bit (in_worklist, e->dest->index); worklist->insert (bb_order[e->dest->index], e->dest); @@ -7160,8 +7249,8 @@ vt_find_locations (void) if (dump_file) fprintf (dump_file, - "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n", - bb->index, + "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, " + "tsz %i\n", bb->index, (int)shared_hash_htab (VTI (bb)->in.vars)->size (), oldinsz, (int)shared_hash_htab (VTI (bb)->out.vars)->size (), @@ -7179,11 +7268,16 @@ vt_find_locations (void) } } } + while (curr_end != n - 1); + + statistics_counter_event (cfun, "compute_bb_dataflow times", + n_blocks_processed); - if (success && MAY_HAVE_DEBUG_INSNS) + if (success && MAY_HAVE_DEBUG_BIND_INSNS) FOR_EACH_BB_FN (bb, cfun) gcc_assert (VTI (bb)->flooded); + free (rc_order); free (bb_order); delete worklist; delete pending; @@ -7273,7 +7367,7 @@ dump_var (variable *var) static void dump_vars (variable_table_type *vars) { - if (vars->elements () > 0) + if (!vars->is_empty ()) { fprintf (dump_file, "Variables:\n"); vars->traverse (NULL); @@ -8002,8 +8096,9 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, /* Structure for passing some other parameters to function vt_expand_loc_callback. */ -struct expand_loc_callback_data +class expand_loc_callback_data { +public: /* The variables and values active at this point. */ variable_table_type *vars; @@ -8049,7 +8144,7 @@ loc_exp_dep_alloc (variable *var, int count) return; allocsize = offsetof (struct onepart_aux, deps) - + vec::embedded_size (count); + + deps_vec::embedded_size (count); if (VAR_LOC_1PAUX (var)) { @@ -8269,8 +8364,8 @@ static inline rtx vt_expand_var_loc_chain (variable *var, bitmap regs, void *data, bool *pendrecp) { - struct expand_loc_callback_data *elcd - = (struct expand_loc_callback_data *) data; + class expand_loc_callback_data *elcd + = (class expand_loc_callback_data *) data; location_chain *loc, *next; rtx result = NULL; int first_child, result_first_child, last_child; @@ -8408,8 +8503,8 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth ATTRIBUTE_UNUSED, void *data) { - struct expand_loc_callback_data *elcd - = (struct expand_loc_callback_data *) data; + class expand_loc_callback_data *elcd + = (class expand_loc_callback_data *) data; decl_or_value dv; variable *var; rtx result, subreg; @@ -8432,7 +8527,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, /* Invalid SUBREGs are ok in debug info. ??? We could try alternate expansions for the VALUE as well. */ - if (!result) + if (!result && GET_MODE (subreg) != VOIDmode) result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x)); return result; @@ -8566,10 +8661,10 @@ resolve_expansions_pending_recursion (vec *pending) static rtx vt_expand_loc (rtx loc, variable_table_type *vars) { - struct expand_loc_callback_data data; + class expand_loc_callback_data data; rtx result; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return loc; INIT_ELCD (data, vars); @@ -8588,7 +8683,7 @@ vt_expand_loc (rtx loc, variable_table_type *vars) static rtx vt_expand_1pvar (variable *var, variable_table_type *vars) { - struct expand_loc_callback_data data; + class expand_loc_callback_data data; rtx loc; gcc_checking_assert (var->onepart && var->n_var_parts == 1); @@ -8624,7 +8719,6 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) bool complete; enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED; HOST_WIDE_INT last_limit; - tree type_size_unit; HOST_WIDE_INT offsets[MAX_VAR_PARTS]; rtx loc[MAX_VAR_PARTS]; tree decl; @@ -8646,7 +8740,7 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) { machine_mode mode, wider_mode; rtx loc2; - HOST_WIDE_INT offset; + HOST_WIDE_INT offset, size, wider_size; if (i == 0 && var->onepart) { @@ -8701,15 +8795,22 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) mode = GET_MODE (var->var_part[i].cur_loc); if (mode == VOIDmode && var->onepart) mode = DECL_MODE (decl); - last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + /* We ony track subparts of constant-sized objects, since at present + there's no representation for polynomial pieces. */ + if (!GET_MODE_SIZE (mode).is_constant (&size)) + { + complete = false; + continue; + } + last_limit = offsets[n_var_parts] + size; /* 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_PART_OFFSET (var, j)) break; if (j < var->n_var_parts - && wider_mode != VOIDmode + && GET_MODE_WIDER_MODE (mode).exists (&wider_mode) + && GET_MODE_SIZE (wider_mode).is_constant (&wider_size) && var->var_part[j].cur_loc && mode == GET_MODE (var->var_part[j].cur_loc) && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts])) @@ -8718,10 +8819,11 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2)) { rtx new_loc = NULL; + poly_int64 offset2; 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] + && hard_regno_nregs (REGNO (loc[n_var_parts]), mode) * 2 + == hard_regno_nregs (REGNO (loc[n_var_parts]), wider_mode) && end_hard_regno (mode, REGNO (loc[n_var_parts])) == REGNO (loc2)) { @@ -8742,20 +8844,13 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) else if (MEM_P (loc[n_var_parts]) && GET_CODE (XEXP (loc2, 0)) == PLUS && REG_P (XEXP (XEXP (loc2, 0), 0)) - && CONST_INT_P (XEXP (XEXP (loc2, 0), 1))) + && poly_int_rtx_p (XEXP (XEXP (loc2, 0), 1), &offset2)) { - if ((REG_P (XEXP (loc[n_var_parts], 0)) - && 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 - && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1)) - && 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)))) + poly_int64 end1 = size; + rtx base1 = strip_offset_and_add (XEXP (loc[n_var_parts], 0), + &end1); + if (rtx_equal_p (base1, XEXP (XEXP (loc2, 0), 0)) + && known_eq (end1, offset2)) new_loc = adjust_address_nv (loc[n_var_parts], wider_mode, 0); } @@ -8764,14 +8859,15 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) { loc[n_var_parts] = new_loc; mode = wider_mode; - last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + last_limit = offsets[n_var_parts] + wider_size; i = j; } } ++n_var_parts; } - type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl)); - if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) + poly_uint64 type_size_unit + = tree_to_poly_uint64 (TYPE_SIZE_UNIT (TREE_TYPE (decl))); + if (maybe_lt (poly_uint64 (last_limit), type_size_unit)) complete = false; if (! flag_var_tracking_uninit) @@ -8816,14 +8912,12 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) /* Make sure that the call related notes come first. */ while (NEXT_INSN (insn) && NOTE_P (insn) - && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION - && NOTE_DURING_CALL_P (insn)) - || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION)) + && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION + && NOTE_DURING_CALL_P (insn)) insn = NEXT_INSN (insn); if (NOTE_P (insn) - && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION - && NOTE_DURING_CALL_P (insn)) - || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION)) + && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION + && NOTE_DURING_CALL_P (insn)) note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); else note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); @@ -9002,10 +9096,10 @@ emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where, emit_note_data data; variable_table_type *htab = shared_hash_htab (vars); - if (!changed_variables->elements ()) + if (changed_variables->is_empty ()) return; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) process_changed_values (htab); data.insn = insn; @@ -9166,7 +9260,6 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars); { rtx arguments = mo->u.loc, *p = &arguments; - rtx_note *note; while (*p) { XEXP (XEXP (*p, 0), 1) @@ -9174,7 +9267,11 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) shared_hash_htab (set->vars)); /* If expansion is successful, keep it in the list. */ if (XEXP (XEXP (*p, 0), 1)) - p = &XEXP (*p, 1); + { + XEXP (XEXP (*p, 0), 1) + = copy_rtx_if_shared (XEXP (XEXP (*p, 0), 1)); + p = &XEXP (*p, 1); + } /* Otherwise, if the following item is data_value for it, drop it too too. */ else if (XEXP (*p, 1) @@ -9190,8 +9287,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) else *p = XEXP (*p, 1); } - note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn); - NOTE_VAR_LOCATION (note) = arguments; + add_reg_note (insn, REG_CALL_ARG_LOCATION, arguments); } break; @@ -9478,7 +9574,7 @@ vt_emit_notes (void) basic_block bb; dataflow_set cur; - gcc_assert (!changed_variables->elements ()); + gcc_assert (changed_variables->is_empty ()); /* Free memory occupied by the out hash tables, as they aren't used anymore. */ @@ -9489,10 +9585,8 @@ vt_emit_notes (void) delete_variable_part). */ emit_notes = true; - if (MAY_HAVE_DEBUG_INSNS) - { - dropped_values = new variable_table_type (cselib_get_next_uid () * 2); - } + if (MAY_HAVE_DEBUG_BIND_INSNS) + dropped_values = new variable_table_type (cselib_get_next_uid () * 2); dataflow_set_init (&cur); @@ -9502,13 +9596,13 @@ vt_emit_notes (void) subsequent basic blocks. */ emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) local_get_addr_cache = new hash_map; /* Emit the notes for the changes in the basic block itself. */ emit_notes_in_bb (bb, &cur); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) delete local_get_addr_cache; local_get_addr_cache = NULL; @@ -9524,7 +9618,7 @@ vt_emit_notes (void) dataflow_set_destroy (&cur); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) delete dropped_values; dropped_values = NULL; @@ -9535,7 +9629,7 @@ vt_emit_notes (void) assign declaration to *DECLP and offset to *OFFSETP, and return true. */ static bool -vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) +vt_get_decl_and_offset (rtx rtl, tree *declp, poly_int64 *offsetp) { if (REG_P (rtl)) { @@ -9561,8 +9655,10 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) decl = REG_EXPR (reg); if (REG_EXPR (reg) != decl) break; - if (REG_OFFSET (reg) < offset) - offset = REG_OFFSET (reg); + HOST_WIDE_INT this_offset; + if (!track_offset_p (REG_OFFSET (reg), &this_offset)) + break; + offset = MIN (offset, this_offset); } if (i == len) @@ -9577,7 +9673,7 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) if (MEM_ATTRS (rtl)) { *declp = MEM_EXPR (rtl); - *offsetp = INT_MEM_OFFSET (rtl); + *offsetp = int_mem_offset (rtl); return true; } } @@ -9606,9 +9702,10 @@ vt_add_function_parameter (tree parm) rtx incoming = DECL_INCOMING_RTL (parm); tree decl; machine_mode mode; - HOST_WIDE_INT offset; + poly_int64 offset; dataflow_set *out; decl_or_value dv; + bool incoming_ok = true; if (TREE_CODE (parm) != PARM_DECL) return; @@ -9623,20 +9720,17 @@ vt_add_function_parameter (tree parm) rewrite the incoming location of parameters passed on the stack into MEMs based on the argument pointer, so that incoming doesn't depend on a pseudo. */ + poly_int64 incoming_offset = 0; if (MEM_P (incoming) - && (XEXP (incoming, 0) == crtl->args.internal_arg_pointer - || (GET_CODE (XEXP (incoming, 0)) == PLUS - && XEXP (XEXP (incoming, 0), 0) - == crtl->args.internal_arg_pointer - && CONST_INT_P (XEXP (XEXP (incoming, 0), 1))))) + && (strip_offset (XEXP (incoming, 0), &incoming_offset) + == crtl->args.internal_arg_pointer)) { HOST_WIDE_INT off = -FIRST_PARM_OFFSET (current_function_decl); - if (GET_CODE (XEXP (incoming, 0)) == PLUS) - off += INTVAL (XEXP (XEXP (incoming, 0), 1)); incoming = replace_equiv_address_nv (incoming, plus_constant (Pmode, - arg_pointer_rtx, off)); + arg_pointer_rtx, + off + incoming_offset)); } #ifdef HAVE_window_save @@ -9699,6 +9793,7 @@ vt_add_function_parameter (tree parm) if (!vt_get_decl_and_offset (incoming, &decl, &offset)) { + incoming_ok = false; if (MEM_P (incoming)) { /* This means argument is passed by invisible reference. */ @@ -9729,7 +9824,8 @@ vt_add_function_parameter (tree parm) offset = 0; } - if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) + HOST_WIDE_INT const_offset; + if (!track_loc_p (incoming, parm, offset, false, &mode, &const_offset)) return; out = &VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out; @@ -9750,7 +9846,7 @@ vt_add_function_parameter (tree parm) arguments passed by invisible reference aren't dealt with above: incoming-rtl will have Pmode rather than the expected mode for the type. */ - if (offset) + if (const_offset) return; lowpart = var_lowpart (mode, incoming); @@ -9765,7 +9861,7 @@ vt_add_function_parameter (tree parm) if (val) { preserve_value (val); - set_variable_part (out, val->val_rtx, dv, offset, + set_variable_part (out, val->val_rtx, dv, const_offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); dv = dv_from_value (val->val_rtx); } @@ -9786,9 +9882,9 @@ vt_add_function_parameter (tree parm) { incoming = var_lowpart (mode, incoming); gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); - attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, + attrs_list_insert (&out->regs[REGNO (incoming)], dv, const_offset, incoming); - set_variable_part (out, incoming, dv, offset, + set_variable_part (out, incoming, dv, const_offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); if (dv_is_value_p (dv)) { @@ -9816,20 +9912,26 @@ vt_add_function_parameter (tree parm) { int i; + /* The following code relies on vt_get_decl_and_offset returning true for + incoming, which might not be always the case. */ + if (!incoming_ok) + return; for (i = 0; i < XVECLEN (incoming, 0); i++) { rtx reg = XEXP (XVECEXP (incoming, 0, i), 0); - offset = REG_OFFSET (reg); + /* vt_get_decl_and_offset has already checked that the offset + is a valid variable part. */ + const_offset = get_tracked_reg_offset (reg); gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER); - attrs_list_insert (&out->regs[REGNO (reg)], dv, offset, reg); - set_variable_part (out, reg, dv, offset, + attrs_list_insert (&out->regs[REGNO (reg)], dv, const_offset, reg); + set_variable_part (out, reg, dv, const_offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); } } else if (MEM_P (incoming)) { incoming = var_lowpart (mode, incoming); - set_variable_part (out, incoming, dv, offset, + set_variable_part (out, incoming, dv, const_offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); } } @@ -9843,8 +9945,7 @@ vt_add_function_parameters (void) for (parm = DECL_ARGUMENTS (current_function_decl); parm; parm = DECL_CHAIN (parm)) - if (!POINTER_BOUNDS_P (parm)) - vt_add_function_parameter (parm); + vt_add_function_parameter (parm); if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl))) { @@ -9884,7 +9985,7 @@ vt_init_cfa_base (void) cfa_base_rtx = NULL_RTX; return; } - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return; /* Tell alias analysis that cfa_base_rtx should share @@ -9900,6 +10001,35 @@ vt_init_cfa_base (void) cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx)); } +/* Reemit INSN, a MARKER_DEBUG_INSN, as a note. */ + +static rtx_insn * +reemit_marker_as_note (rtx_insn *insn) +{ + gcc_checking_assert (DEBUG_MARKER_INSN_P (insn)); + + enum insn_note kind = INSN_DEBUG_MARKER_KIND (insn); + + switch (kind) + { + case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: + { + rtx_insn *note = NULL; + if (cfun->debug_nonbind_markers) + { + note = emit_note_before (kind, insn); + NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn); + } + delete_insn (insn); + return note; + } + + default: + gcc_unreachable (); + } +} + /* Allocate and initialize the data structures for variable tracking and parse the RTL to get the micro operations. */ @@ -9907,7 +10037,7 @@ static bool vt_initialize (void) { basic_block bb; - HOST_WIDE_INT fp_cfa_offset = -1; + poly_int64 fp_cfa_offset = -1; alloc_aux_for_blocks (sizeof (variable_tracking_info)); @@ -9926,7 +10056,7 @@ vt_initialize (void) VTI (bb)->permp = NULL; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS); scratch_regs = BITMAP_ALLOC (NULL); @@ -9939,7 +10069,7 @@ vt_initialize (void) global_get_addr_cache = NULL; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { rtx reg, expr; int ofst; @@ -9960,19 +10090,25 @@ vt_initialize (void) preserve_value (val); if (reg != hard_frame_pointer_rtx && fixed_regs[REGNO (reg)]) cselib_preserve_cfa_base_value (val, REGNO (reg)); - expr = plus_constant (GET_MODE (stack_pointer_rtx), - stack_pointer_rtx, -ofst); - cselib_add_permanent_equiv (val, expr, get_insns ()); - if (ofst) { - val = cselib_lookup_from_insn (stack_pointer_rtx, - GET_MODE (stack_pointer_rtx), 1, - VOIDmode, get_insns ()); - preserve_value (val); + cselib_val *valsp + = cselib_lookup_from_insn (stack_pointer_rtx, + GET_MODE (stack_pointer_rtx), 1, + VOIDmode, get_insns ()); + preserve_value (valsp); expr = plus_constant (GET_MODE (reg), reg, ofst); - cselib_add_permanent_equiv (val, expr, get_insns ()); + /* This cselib_add_permanent_equiv call needs to be done before + the other cselib_add_permanent_equiv a few lines later, + because after that one is done, cselib_lookup on this expr + will due to the cselib SP_DERIVED_VALUE_P optimizations + return valsp and so no permanent equivalency will be added. */ + cselib_add_permanent_equiv (valsp, expr, get_insns ()); } + + expr = plus_constant (GET_MODE (stack_pointer_rtx), + stack_pointer_rtx, -ofst); + cselib_add_permanent_equiv (val, expr, get_insns ()); } /* In order to factor out the adjustments made to the stack pointer or to @@ -10022,7 +10158,7 @@ vt_initialize (void) { if (GET_CODE (elim) == PLUS) { - fp_cfa_offset -= INTVAL (XEXP (elim, 1)); + fp_cfa_offset -= rtx_to_poly_int64 (XEXP (elim, 1)); elim = XEXP (elim, 0); } if (elim != hard_frame_pointer_rtx) @@ -10063,13 +10199,13 @@ vt_initialize (void) vt_add_function_parameters (); + bool record_sp_value = false; FOR_EACH_BB_FN (bb, cfun) { rtx_insn *insn; - HOST_WIDE_INT pre, post = 0; basic_block first_bb, last_bb; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_record_sets_hook = add_with_sets; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -10077,6 +10213,15 @@ vt_initialize (void) cselib_get_next_uid ()); } + if (MAY_HAVE_DEBUG_BIND_INSNS + && cfa_base_rtx + && !frame_pointer_needed + && record_sp_value) + cselib_record_sp_cfa_base_equiv (-cfa_base_offset + - VTI (bb)->in.stack_adjust, + BB_HEAD (bb)); + record_sp_value = true; + first_bb = bb; for (;;) { @@ -10096,11 +10241,14 @@ vt_initialize (void) { HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust; VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust; - for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); - insn = NEXT_INSN (insn)) + + rtx_insn *next; + FOR_BB_INSNS_SAFE (bb, insn, next) { if (INSN_P (insn)) { + HOST_WIDE_INT pre = 0, post = 0; + if (!frame_pointer_needed) { insn_stack_adjust_offset_pre_post (insn, &pre, &post); @@ -10114,20 +10262,32 @@ vt_initialize (void) log_op_type (PATTERN (insn), bb, insn, MO_ADJUST, dump_file); VTI (bb)->mos.safe_push (mo); - VTI (bb)->out.stack_adjust += pre; } } cselib_hook_called = false; adjust_insn (bb, insn); - if (MAY_HAVE_DEBUG_INSNS) + + if (pre) + VTI (bb)->out.stack_adjust += pre; + + if (DEBUG_MARKER_INSN_P (insn)) + { + reemit_marker_as_note (insn); + continue; + } + + if (MAY_HAVE_DEBUG_BIND_INSNS) { if (CALL_P (insn)) prepare_call_arguments (bb, insn); cselib_process_insn (insn); if (dump_file && (dump_flags & TDF_DETAILS)) { - print_rtl_single (dump_file, insn); + if (dump_flags & TDF_SLIM) + dump_insn_slim (dump_file, insn); + else + print_rtl_single (dump_file, insn); dump_cselib_table (dump_file); } } @@ -10135,7 +10295,7 @@ vt_initialize (void) add_with_sets (insn, 0, 0); cancel_changes (0); - if (!frame_pointer_needed && post) + if (post) { micro_operation mo; mo.type = MO_ADJUST; @@ -10148,14 +10308,14 @@ vt_initialize (void) VTI (bb)->out.stack_adjust += post; } - if (fp_cfa_offset != -1 - && hard_frame_pointer_adjustment == -1 + if (maybe_ne (fp_cfa_offset, -1) + && known_eq (hard_frame_pointer_adjustment, -1) && fp_setter_insn (insn)) { vt_init_cfa_base (); hard_frame_pointer_adjustment = fp_cfa_offset; /* Disassociate sp from fp now. */ - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_val *v; cselib_invalidate_rtx (stack_pointer_rtx); @@ -10175,7 +10335,7 @@ vt_initialize (void) bb = last_bb; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_preserve_only_values (); cselib_reset_table (cselib_get_next_uid ()); @@ -10195,10 +10355,40 @@ vt_initialize (void) static int debug_label_num = 1; -/* Get rid of all debug insns from the insn stream. */ +/* Remove from the insn stream a single debug insn used for + variable tracking at assignments. */ -static void -delete_debug_insns (void) +static inline void +delete_vta_debug_insn (rtx_insn *insn) +{ + if (DEBUG_MARKER_INSN_P (insn)) + { + reemit_marker_as_note (insn); + return; + } + + tree decl = INSN_VAR_LOCATION_DECL (insn); + if (TREE_CODE (decl) == LABEL_DECL + && DECL_NAME (decl) + && !DECL_RTL_SET_P (decl)) + { + PUT_CODE (insn, NOTE); + NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL; + NOTE_DELETED_LABEL_NAME (insn) + = IDENTIFIER_POINTER (DECL_NAME (decl)); + SET_DECL_RTL (decl, insn); + CODE_LABEL_NUMBER (insn) = debug_label_num++; + } + else + delete_insn (insn); +} + +/* Remove from the insn stream all debug insns used for variable + tracking at assignments. USE_CFG should be false if the cfg is no + longer usable. */ + +void +delete_vta_debug_insns (bool use_cfg) { basic_block bb; rtx_insn *insn, *next; @@ -10206,27 +10396,20 @@ delete_debug_insns (void) if (!MAY_HAVE_DEBUG_INSNS) return; - FOR_EACH_BB_FN (bb, cfun) - { - FOR_BB_INSNS_SAFE (bb, insn, next) + if (use_cfg) + FOR_EACH_BB_FN (bb, cfun) + { + FOR_BB_INSNS_SAFE (bb, insn, next) + if (DEBUG_INSN_P (insn)) + delete_vta_debug_insn (insn); + } + else + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); if (DEBUG_INSN_P (insn)) - { - tree decl = INSN_VAR_LOCATION_DECL (insn); - if (TREE_CODE (decl) == LABEL_DECL - && DECL_NAME (decl) - && !DECL_RTL_SET_P (decl)) - { - PUT_CODE (insn, NOTE); - NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL; - NOTE_DELETED_LABEL_NAME (insn) - = IDENTIFIER_POINTER (DECL_NAME (decl)); - SET_DECL_RTL (decl, insn); - CODE_LABEL_NUMBER (insn) = debug_label_num++; - } - else - delete_insn (insn); - } - } + delete_vta_debug_insn (insn); + } } /* Run a fast, BB-local only version of var tracking, to take care of @@ -10239,7 +10422,7 @@ static void vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED) { /* ??? Just skip it all for now. */ - delete_debug_insns (); + delete_vta_debug_insns (true); } /* Free the data structures needed for variable tracking. */ @@ -10274,7 +10457,7 @@ vt_finalize (void) location_chain_pool.release (); shared_hash_pool.release (); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { if (global_get_addr_cache) delete global_get_addr_cache; @@ -10304,23 +10487,28 @@ variable_tracking_main_1 (void) { bool success; - if (flag_var_tracking_assignments < 0 + /* We won't be called as a separate pass if flag_var_tracking is not + set, but final may call us to turn debug markers into notes. */ + if ((!flag_var_tracking && MAY_HAVE_DEBUG_INSNS) + || flag_var_tracking_assignments < 0 /* Var-tracking right now assumes the IR doesn't contain any pseudos at this point. */ || targetm.no_register_allocation) { - delete_debug_insns (); + delete_vta_debug_insns (true); return 0; } - if (n_basic_blocks_for_fn (cfun) > 500 && - n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20) + if (!flag_var_tracking) + return 0; + + if (n_basic_blocks_for_fn (cfun) > 500 + && n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20) { vt_debug_insns_local (true); return 0; } - mark_dfs_back_edges (); if (!vt_initialize ()) { vt_finalize (); @@ -10334,7 +10522,7 @@ variable_tracking_main_1 (void) { vt_finalize (); - delete_debug_insns (); + delete_vta_debug_insns (true); /* This is later restored by our caller. */ flag_var_tracking_assignments = 0;