Mercurial > hg > CbC > CbC_gcc
diff gcc/var-tracking.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/var-tracking.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/var-tracking.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* Variable tracking routines for the GNU compiler. - Copyright (C) 2002-2017 Free Software Foundation, Inc. + Copyright (C) 2002-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -115,6 +115,7 @@ #include "tree-pretty-print.h" #include "rtl-iter.h" #include "fibonacci_heap.h" +#include "print-rtl.h" typedef fibonacci_heap <long, basic_block_def> bb_heap_t; typedef fibonacci_node <long, basic_block_def> bb_heap_node_t; @@ -390,8 +391,16 @@ /* 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) @@ -666,7 +675,6 @@ 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); @@ -697,7 +705,6 @@ 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); @@ -911,14 +918,14 @@ 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. */ @@ -958,6 +965,24 @@ 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 <scalar_int_mode> (mode)) + < GET_MODE_PRECISION (as_a <scalar_int_mode> (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: @@ -1010,6 +1035,7 @@ 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: @@ -1023,7 +1049,7 @@ 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); @@ -1054,11 +1080,9 @@ 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: @@ -1066,12 +1090,10 @@ 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); @@ -1118,7 +1140,7 @@ 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 @@ -1330,7 +1352,7 @@ { tree decl; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return NOT_ONEPART; if (dv_is_value_p (dv)) @@ -1843,6 +1865,32 @@ 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 +1898,7 @@ 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 +1944,7 @@ 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 +1985,10 @@ 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); @@ -2127,7 +2175,7 @@ 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 +2184,9 @@ while (retry) { while (GET_CODE (loc) == PLUS - && GET_CODE (XEXP (loc, 1)) == CONST_INT) - { - ofst += INTVAL (XEXP (loc, 1)); + && poly_int_rtx_p (XEXP (loc, 1), &term)) + { + ofst += term; loc = XEXP (loc, 0); } @@ -2163,10 +2211,11 @@ 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 +2231,10 @@ } /* 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 +2383,7 @@ 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 +2401,7 @@ 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 +2422,7 @@ 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); @@ -3490,6 +3537,12 @@ 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 +4671,7 @@ 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 +4736,7 @@ /* 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 +4780,7 @@ 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) @@ -4854,7 +4907,7 @@ EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 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) @@ -5170,20 +5223,20 @@ || (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; @@ -5225,7 +5278,7 @@ && !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; } @@ -5238,10 +5291,10 @@ 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; @@ -5254,7 +5307,7 @@ else if (MEM_P (loc)) { expr2 = MEM_EXPR (loc); - offset2 = INT_MEM_OFFSET (loc); + offset2 = int_mem_offset (loc); } else return false; @@ -5265,7 +5318,7 @@ 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. @@ -5279,7 +5332,7 @@ 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; @@ -5313,19 +5366,20 @@ || (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) + && 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; } @@ -5336,7 +5390,7 @@ 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; @@ -5344,12 +5398,12 @@ 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); @@ -5522,13 +5576,13 @@ 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 @@ -5926,7 +5980,9 @@ 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)) { @@ -6017,7 +6073,7 @@ 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; @@ -6056,7 +6112,7 @@ } if (loc == stack_pointer_rtx - && hard_frame_pointer_adjustment != -1 + && maybe_ne (hard_frame_pointer_adjustment, -1) && preserve) cselib_set_value_sp_based (v); @@ -6693,7 +6749,7 @@ 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<rtx, rtx>; FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo) @@ -6975,7 +7031,7 @@ } } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { delete local_get_addr_cache; local_get_addr_cache = NULL; @@ -7062,7 +7118,7 @@ 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; @@ -7123,7 +7179,7 @@ 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"); @@ -7183,7 +7239,7 @@ } } - if (success && MAY_HAVE_DEBUG_INSNS) + if (success && MAY_HAVE_DEBUG_BIND_INSNS) FOR_EACH_BB_FN (bb, cfun) gcc_assert (VTI (bb)->flooded); @@ -8572,7 +8628,7 @@ struct expand_loc_callback_data data; rtx result; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return loc; INIT_ELCD (data, vars); @@ -8627,7 +8683,6 @@ 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; @@ -8649,7 +8704,7 @@ { machine_mode mode, wider_mode; rtx loc2; - HOST_WIDE_INT offset; + HOST_WIDE_INT offset, size, wider_size; if (i == 0 && var->onepart) { @@ -8704,7 +8759,14 @@ 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. */ for (j = i + 1; j < var->n_var_parts; j++) @@ -8712,6 +8774,7 @@ break; if (j < var->n_var_parts && 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])) @@ -8720,6 +8783,7 @@ && 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 @@ -8744,20 +8808,13 @@ 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); } @@ -8766,14 +8823,15 @@ { 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) @@ -8818,14 +8876,12 @@ /* 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); @@ -9007,7 +9063,7 @@ if (!changed_variables->elements ()) return; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) process_changed_values (htab); data.insn = insn; @@ -9168,7 +9224,6 @@ 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) @@ -9176,7 +9231,11 @@ 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) @@ -9192,8 +9251,7 @@ 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; @@ -9491,10 +9549,8 @@ 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); @@ -9504,13 +9560,13 @@ 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<rtx, rtx>; /* 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; @@ -9526,7 +9582,7 @@ dataflow_set_destroy (&cur); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) delete dropped_values; dropped_values = NULL; @@ -9537,7 +9593,7 @@ 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)) { @@ -9563,8 +9619,10 @@ 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) @@ -9579,7 +9637,7 @@ if (MEM_ATTRS (rtl)) { *declp = MEM_EXPR (rtl); - *offsetp = INT_MEM_OFFSET (rtl); + *offsetp = int_mem_offset (rtl); return true; } } @@ -9608,9 +9666,10 @@ 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; @@ -9625,20 +9684,17 @@ 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 @@ -9701,6 +9757,7 @@ if (!vt_get_decl_and_offset (incoming, &decl, &offset)) { + incoming_ok = false; if (MEM_P (incoming)) { /* This means argument is passed by invisible reference. */ @@ -9731,7 +9788,8 @@ 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; @@ -9752,7 +9810,7 @@ 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); @@ -9767,7 +9825,7 @@ 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); } @@ -9788,9 +9846,9 @@ { 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)) { @@ -9818,20 +9876,26 @@ { 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); } } @@ -9845,8 +9909,7 @@ 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))) { @@ -9886,7 +9949,7 @@ 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 @@ -9902,6 +9965,35 @@ 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. */ @@ -9909,7 +10001,7 @@ 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)); @@ -9928,7 +10020,7 @@ 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); @@ -9941,7 +10033,7 @@ global_get_addr_cache = NULL; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { rtx reg, expr; int ofst; @@ -10024,7 +10116,7 @@ { 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) @@ -10071,7 +10163,7 @@ 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)) @@ -10098,8 +10190,9 @@ { 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)) { @@ -10116,20 +10209,32 @@ 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 (!frame_pointer_needed && 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); } } @@ -10150,14 +10255,14 @@ 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); @@ -10177,7 +10282,7 @@ 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 ()); @@ -10197,10 +10302,40 @@ static int debug_label_num = 1; -/* Get rid of all debug insns from the insn stream. */ - -static void -delete_debug_insns (void) +/* Remove from the insn stream a single debug insn used for + variable tracking at assignments. */ + +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; @@ -10208,27 +10343,20 @@ 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 @@ -10241,7 +10369,7 @@ 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. */ @@ -10276,7 +10404,7 @@ 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; @@ -10306,17 +10434,23 @@ { 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; @@ -10336,7 +10470,7 @@ { vt_finalize (); - delete_debug_insns (); + delete_vta_debug_insns (true); /* This is later restored by our caller. */ flag_var_tracking_assignments = 0;