/* 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)
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);
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);
/* 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))
/* 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 <scalar_int_mode> (GET_MODE (op1))))
op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
return simplify_gen_binary (ASHIFT, mode, op0, op1);
default:
rtx mem, addr = loc, tem;
machine_mode mem_mode_save;
bool store_save;
+ scalar_int_mode tem_mode, tem_subreg_mode;
switch (GET_CODE (loc))
{
case REG:
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 <scalar_int_mode> (GET_MODE (tem), &tem_mode)
+ && is_a <scalar_int_mode> (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
{
tree decl;
- if (!MAY_HAVE_DEBUG_INSNS)
+ if (!MAY_HAVE_DEBUG_BIND_INSNS)
return NOT_ONEPART;
if (dv_is_value_p (dv))
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
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);
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;
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);
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);
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);
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);
{
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)
{
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. */
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;
/* 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. */
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)
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)
|| (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;
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;
}
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;
else if (MEM_P (loc))
{
expr2 = MEM_EXPR (loc);
- offset2 = INT_MEM_OFFSET (loc);
+ offset2 = int_mem_offset (loc);
}
else
return false;
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.
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;
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;
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;
}
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;
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);
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
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;
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 <scalar_int_mode> (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);
{
/* 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);
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)
}
}
- if (MAY_HAVE_DEBUG_INSNS)
+ if (MAY_HAVE_DEBUG_BIND_INSNS)
{
delete local_get_addr_cache;
local_get_addr_cache = NULL;
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;
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");
}
}
- if (success && MAY_HAVE_DEBUG_INSNS)
+ if (success && MAY_HAVE_DEBUG_BIND_INSNS)
FOR_EACH_BB_FN (bb, cfun)
gcc_assert (VTI (bb)->flooded);
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);
last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
/* Attempt to merge adjacent registers or memory. */
- wider_mode = GET_MODE_WIDER_MODE (mode);
for (j = i + 1; j < var->n_var_parts; j++)
if (last_limit <= VAR_PART_OFFSET (var, j))
break;
if (j < var->n_var_parts
- && wider_mode != VOIDmode
+ && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
&& 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]))
rtx new_loc = NULL;
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))
{
if (!changed_variables->elements ())
return;
- if (MAY_HAVE_DEBUG_INSNS)
+ if (MAY_HAVE_DEBUG_BIND_INSNS)
process_changed_values (htab);
data.insn = insn;
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);
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;
dataflow_set_destroy (&cur);
- if (MAY_HAVE_DEBUG_INSNS)
+ if (MAY_HAVE_DEBUG_BIND_INSNS)
delete dropped_values;
dropped_values = NULL;
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))
{
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)
if (MEM_ATTRS (rtl))
{
*declp = MEM_EXPR (rtl);
- *offsetp = INT_MEM_OFFSET (rtl);
+ *offsetp = int_mem_offset (rtl);
return true;
}
}
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;
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;
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);
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);
}
{
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))
{
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);
}
}
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
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:
+ {
+ 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. */
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);
global_get_addr_cache = NULL;
}
- if (MAY_HAVE_DEBUG_INSNS)
+ if (MAY_HAVE_DEBUG_BIND_INSNS)
{
rtx reg, expr;
int ofst;
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))
{
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))
{
cselib_hook_called = false;
adjust_insn (bb, insn);
- if (MAY_HAVE_DEBUG_INSNS)
+ 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);
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);
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 ());
static int debug_label_num = 1;
-/* Get rid of all debug insns from the insn stream. */
+/* Remove from the insn stream all debug insns used for variable
+ tracking at assignments. */
static void
-delete_debug_insns (void)
+delete_vta_debug_insns (void)
{
basic_block bb;
rtx_insn *insn, *next;
FOR_BB_INSNS_SAFE (bb, insn, next)
if (DEBUG_INSN_P (insn))
{
+ if (DEBUG_MARKER_INSN_P (insn))
+ {
+ reemit_marker_as_note (insn);
+ continue;
+ }
+
tree decl = INSN_VAR_LOCATION_DECL (insn);
if (TREE_CODE (decl) == LABEL_DECL
&& DECL_NAME (decl)
vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
{
/* ??? Just skip it all for now. */
- delete_debug_insns ();
+ delete_vta_debug_insns ();
}
/* Free the data structures needed for variable tracking. */
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;
{
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 ();
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;
{
vt_finalize ();
- delete_debug_insns ();
+ delete_vta_debug_insns ();
/* This is later restored by our caller. */
flag_var_tracking_assignments = 0;