re PR debug/48220 (DW_OP_GNU_entry_value/DW_TAG_GNU_call_site_parameter vs register window)
PR target/48220 * doc/md.texi (Standard Names): Document window_save. * cfgexpand.c (expand_debug_parm_decl): New function extracted from expand_debug_expr and expand_debug_source_expr. If the target has a window_save instruction, adjust the ENTRY_VALUE_EXP. (expand_debug_expr) <SSA_NAME>: Call expand_debug_parm_decl if the SSA_NAME_VAR is a parameter. (expand_debug_source_expr) <PARM_DECL>: Call expand_debug_parm_decl. * var-tracking.c (parm_reg_t): New type and associated vector type. (windowed_parm_regs): New variable. (adjust_insn): If the target has a window_save instruction and this is the instruction, make its effect on parameter registers explicit. (next_non_note_insn_var_location): New function. (emit_notes_in_bb): Use it instead of NEXT_INSN throughout. (vt_add_function_parameter): If the target has a window_save insn, adjust the incoming RTL and record that in windowed_parm_regs. (vt_finalize): Free windowed_parm_regs. From-SVN: r176318
This commit is contained in:
parent
021a9e7ef2
commit
12c5ffe5ef
|
@ -1,3 +1,23 @@
|
|||
2011-07-15 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR target/48220
|
||||
* doc/md.texi (Standard Names): Document window_save.
|
||||
* cfgexpand.c (expand_debug_parm_decl): New function extracted from
|
||||
expand_debug_expr and expand_debug_source_expr. If the target has
|
||||
a window_save instruction, adjust the ENTRY_VALUE_EXP.
|
||||
(expand_debug_expr) <SSA_NAME>: Call expand_debug_parm_decl if the
|
||||
SSA_NAME_VAR is a parameter.
|
||||
(expand_debug_source_expr) <PARM_DECL>: Call expand_debug_parm_decl.
|
||||
* var-tracking.c (parm_reg_t): New type and associated vector type.
|
||||
(windowed_parm_regs): New variable.
|
||||
(adjust_insn): If the target has a window_save instruction and this
|
||||
is the instruction, make its effect on parameter registers explicit.
|
||||
(next_non_note_insn_var_location): New function.
|
||||
(emit_notes_in_bb): Use it instead of NEXT_INSN throughout.
|
||||
(vt_add_function_parameter): If the target has a window_save insn,
|
||||
adjust the incoming RTL and record that in windowed_parm_regs.
|
||||
(vt_finalize): Free windowed_parm_regs.
|
||||
|
||||
2011-07-15 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi (C6X Options): New section.
|
||||
|
|
120
gcc/cfgexpand.c
120
gcc/cfgexpand.c
|
@ -2358,8 +2358,60 @@ convert_debug_memory_address (enum machine_mode mode, rtx x,
|
|||
return x;
|
||||
}
|
||||
|
||||
/* Return an RTX equivalent to the value of the tree expression
|
||||
EXP. */
|
||||
/* Return an RTX equivalent to the value of the parameter DECL. */
|
||||
|
||||
static rtx
|
||||
expand_debug_parm_decl (tree decl)
|
||||
{
|
||||
rtx incoming = DECL_INCOMING_RTL (decl);
|
||||
|
||||
if (incoming
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& ((REG_P (incoming) && HARD_REGISTER_P (incoming))
|
||||
|| (MEM_P (incoming)
|
||||
&& REG_P (XEXP (incoming, 0))
|
||||
&& HARD_REGISTER_P (XEXP (incoming, 0)))))
|
||||
{
|
||||
rtx rtl = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
|
||||
|
||||
#ifdef HAVE_window_save
|
||||
/* DECL_INCOMING_RTL uses the INCOMING_REGNO of parameter registers.
|
||||
If the target machine has an explicit window save instruction, the
|
||||
actual entry value is the corresponding OUTGOING_REGNO instead. */
|
||||
if (REG_P (incoming)
|
||||
&& OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
|
||||
incoming
|
||||
= gen_rtx_REG_offset (incoming, GET_MODE (incoming),
|
||||
OUTGOING_REGNO (REGNO (incoming)), 0);
|
||||
else if (MEM_P (incoming))
|
||||
{
|
||||
rtx reg = XEXP (incoming, 0);
|
||||
if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
|
||||
{
|
||||
reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
|
||||
incoming = replace_equiv_address_nv (incoming, reg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ENTRY_VALUE_EXP (rtl) = incoming;
|
||||
return rtl;
|
||||
}
|
||||
|
||||
if (incoming
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& !TREE_ADDRESSABLE (decl)
|
||||
&& MEM_P (incoming)
|
||||
&& (XEXP (incoming, 0) == virtual_incoming_args_rtx
|
||||
|| (GET_CODE (XEXP (incoming, 0)) == PLUS
|
||||
&& XEXP (XEXP (incoming, 0), 0) == virtual_incoming_args_rtx
|
||||
&& CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
|
||||
return incoming;
|
||||
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Return an RTX equivalent to the value of the tree expression EXP. */
|
||||
|
||||
static rtx
|
||||
expand_debug_expr (tree exp)
|
||||
|
@ -3169,36 +3221,12 @@ expand_debug_expr (tree exp)
|
|||
if (SSA_NAME_IS_DEFAULT_DEF (exp)
|
||||
&& TREE_CODE (SSA_NAME_VAR (exp)) == PARM_DECL)
|
||||
{
|
||||
rtx incoming = DECL_INCOMING_RTL (SSA_NAME_VAR (exp));
|
||||
if (incoming
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& ((REG_P (incoming) && HARD_REGISTER_P (incoming))
|
||||
|| (MEM_P (incoming)
|
||||
&& REG_P (XEXP (incoming, 0))
|
||||
&& HARD_REGISTER_P (XEXP (incoming, 0)))))
|
||||
{
|
||||
op0 = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
|
||||
ENTRY_VALUE_EXP (op0) = incoming;
|
||||
goto adjust_mode;
|
||||
}
|
||||
if (incoming
|
||||
&& MEM_P (incoming)
|
||||
&& !TREE_ADDRESSABLE (SSA_NAME_VAR (exp))
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& (XEXP (incoming, 0) == virtual_incoming_args_rtx
|
||||
|| (GET_CODE (XEXP (incoming, 0)) == PLUS
|
||||
&& XEXP (XEXP (incoming, 0), 0)
|
||||
== virtual_incoming_args_rtx
|
||||
&& CONST_INT_P (XEXP (XEXP (incoming, 0),
|
||||
1)))))
|
||||
{
|
||||
op0 = incoming;
|
||||
goto adjust_mode;
|
||||
}
|
||||
op0 = expand_debug_parm_decl (SSA_NAME_VAR (exp));
|
||||
if (op0)
|
||||
goto adjust_mode;
|
||||
op0 = expand_debug_expr (SSA_NAME_VAR (exp));
|
||||
if (!op0)
|
||||
return NULL;
|
||||
goto adjust_mode;
|
||||
if (op0)
|
||||
goto adjust_mode;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3327,36 +3355,14 @@ expand_debug_source_expr (tree exp)
|
|||
{
|
||||
case PARM_DECL:
|
||||
{
|
||||
rtx incoming = DECL_INCOMING_RTL (exp);
|
||||
mode = DECL_MODE (exp);
|
||||
if (incoming
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& ((REG_P (incoming) && HARD_REGISTER_P (incoming))
|
||||
|| (MEM_P (incoming)
|
||||
&& REG_P (XEXP (incoming, 0))
|
||||
&& HARD_REGISTER_P (XEXP (incoming, 0)))))
|
||||
{
|
||||
op0 = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
|
||||
ENTRY_VALUE_EXP (op0) = incoming;
|
||||
break;
|
||||
}
|
||||
if (incoming
|
||||
&& MEM_P (incoming)
|
||||
&& !TREE_ADDRESSABLE (exp)
|
||||
&& GET_MODE (incoming) != BLKmode
|
||||
&& (XEXP (incoming, 0) == virtual_incoming_args_rtx
|
||||
|| (GET_CODE (XEXP (incoming, 0)) == PLUS
|
||||
&& XEXP (XEXP (incoming, 0), 0)
|
||||
== virtual_incoming_args_rtx
|
||||
&& CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
|
||||
{
|
||||
op0 = incoming;
|
||||
break;
|
||||
}
|
||||
op0 = expand_debug_parm_decl (exp);
|
||||
if (op0)
|
||||
break;
|
||||
/* See if this isn't an argument that has been completely
|
||||
optimized out. */
|
||||
if (!DECL_RTL_SET_P (exp)
|
||||
&& incoming == NULL_RTX
|
||||
&& !DECL_INCOMING_RTL (exp)
|
||||
&& DECL_ABSTRACT_ORIGIN (current_function_decl))
|
||||
{
|
||||
tree aexp = exp;
|
||||
|
|
|
@ -5333,6 +5333,14 @@ Using a prologue pattern is generally preferred over defining
|
|||
The @code{prologue} pattern is particularly useful for targets which perform
|
||||
instruction scheduling.
|
||||
|
||||
@cindex @code{window_save} instruction pattern
|
||||
@anchor{window_save instruction pattern}
|
||||
@item @samp{window_save}
|
||||
This pattern, if defined, emits RTL for a register window save. It should
|
||||
be defined if the target machine has register windows but the window events
|
||||
are decoupled from calls to subroutines. The canonical example is the SPARC
|
||||
architecture.
|
||||
|
||||
@cindex @code{epilogue} instruction pattern
|
||||
@anchor{epilogue instruction pattern}
|
||||
@item @samp{epilogue}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
operations.
|
||||
The micro operations of one instruction are ordered so that
|
||||
pre-modifying stack adjustment < use < use with no var < call insn <
|
||||
< set < clobber < post-modifying stack adjustment
|
||||
< clobber < set < post-modifying stack adjustment
|
||||
|
||||
Then, a forward dataflow analysis is performed to find out how locations
|
||||
of variables change through code and to propagate the variable locations
|
||||
|
@ -400,6 +400,17 @@ static shared_hash empty_shared_hash;
|
|||
/* Scratch register bitmap used by cselib_expand_value_rtx. */
|
||||
static bitmap scratch_regs = NULL;
|
||||
|
||||
typedef struct GTY(()) parm_reg {
|
||||
rtx outgoing;
|
||||
rtx incoming;
|
||||
} parm_reg_t;
|
||||
|
||||
DEF_VEC_O(parm_reg_t);
|
||||
DEF_VEC_ALLOC_O(parm_reg_t, gc);
|
||||
|
||||
/* Vector of windowed parameter registers, if any. */
|
||||
static VEC(parm_reg_t, gc) *windowed_parm_regs = NULL;
|
||||
|
||||
/* Variable used to tell whether cselib_process_insn called our hook. */
|
||||
static bool cselib_hook_called;
|
||||
|
||||
|
@ -970,6 +981,33 @@ adjust_insn (basic_block bb, rtx insn)
|
|||
{
|
||||
struct adjust_mem_data amd;
|
||||
rtx set;
|
||||
|
||||
#ifdef HAVE_window_save
|
||||
/* If the target machine has an explicit window save instruction, the
|
||||
transformation OUTGOING_REGNO -> INCOMING_REGNO is done there. */
|
||||
if (RTX_FRAME_RELATED_P (insn)
|
||||
&& find_reg_note (insn, REG_CFA_WINDOW_SAVE, NULL_RTX))
|
||||
{
|
||||
unsigned int i, nregs = VEC_length(parm_reg_t, windowed_parm_regs);
|
||||
rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2));
|
||||
parm_reg_t *p;
|
||||
|
||||
FOR_EACH_VEC_ELT (parm_reg_t, windowed_parm_regs, i, p)
|
||||
{
|
||||
XVECEXP (rtl, 0, i * 2)
|
||||
= gen_rtx_SET (VOIDmode, p->incoming, p->outgoing);
|
||||
/* Do not clobber the attached DECL, but only the REG. */
|
||||
XVECEXP (rtl, 0, i * 2 + 1)
|
||||
= gen_rtx_CLOBBER (GET_MODE (p->outgoing),
|
||||
gen_raw_REG (GET_MODE (p->outgoing),
|
||||
REGNO (p->outgoing)));
|
||||
}
|
||||
|
||||
validate_change (NULL_RTX, &PATTERN (insn), rtl, true);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
amd.mem_mode = VOIDmode;
|
||||
amd.stack_adjust = -VTI (bb)->out.stack_adjust;
|
||||
amd.side_effects = NULL_RTX;
|
||||
|
@ -8002,6 +8040,23 @@ emit_notes_for_differences (rtx insn, dataflow_set *old_set,
|
|||
emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
|
||||
}
|
||||
|
||||
/* Return the next insn after INSN that is not a NOTE_INSN_VAR_LOCATION. */
|
||||
|
||||
static rtx
|
||||
next_non_note_insn_var_location (rtx insn)
|
||||
{
|
||||
while (insn)
|
||||
{
|
||||
insn = NEXT_INSN (insn);
|
||||
if (insn == 0
|
||||
|| !NOTE_P (insn)
|
||||
|| NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION)
|
||||
break;
|
||||
}
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Emit the notes for changes of location parts in the basic block BB. */
|
||||
|
||||
static void
|
||||
|
@ -8016,6 +8071,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
|||
FOR_EACH_VEC_ELT (micro_operation, VTI (bb)->mos, i, mo)
|
||||
{
|
||||
rtx insn = mo->insn;
|
||||
rtx next_insn = next_non_note_insn_var_location (insn);
|
||||
|
||||
switch (mo->type)
|
||||
{
|
||||
|
@ -8222,7 +8278,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
|||
val_store (set, XEXP (reverse, 0), XEXP (reverse, 1),
|
||||
insn, false);
|
||||
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
|
||||
emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
|
||||
set->vars);
|
||||
}
|
||||
break;
|
||||
|
@ -8245,7 +8301,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
|||
var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
|
||||
set_src);
|
||||
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
|
||||
emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
|
||||
set->vars);
|
||||
}
|
||||
break;
|
||||
|
@ -8270,7 +8326,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
|||
else
|
||||
var_mem_delete_and_set (set, loc, false, src_status, set_src);
|
||||
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
|
||||
emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
|
||||
set->vars);
|
||||
}
|
||||
break;
|
||||
|
@ -8297,7 +8353,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
|||
else
|
||||
var_mem_delete (set, loc, true);
|
||||
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
|
||||
emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
|
||||
set->vars);
|
||||
}
|
||||
break;
|
||||
|
@ -8483,6 +8539,39 @@ vt_add_function_parameter (tree parm)
|
|||
plus_constant (arg_pointer_rtx, off));
|
||||
}
|
||||
|
||||
#ifdef HAVE_window_save
|
||||
/* DECL_INCOMING_RTL uses the INCOMING_REGNO of parameter registers.
|
||||
If the target machine has an explicit window save instruction, the
|
||||
actual entry value is the corresponding OUTGOING_REGNO instead. */
|
||||
if (REG_P (incoming)
|
||||
&& HARD_REGISTER_P (incoming)
|
||||
&& OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
|
||||
{
|
||||
parm_reg_t *p
|
||||
= VEC_safe_push (parm_reg_t, gc, windowed_parm_regs, NULL);
|
||||
p->incoming = incoming;
|
||||
incoming
|
||||
= gen_rtx_REG_offset (incoming, GET_MODE (incoming),
|
||||
OUTGOING_REGNO (REGNO (incoming)), 0);
|
||||
p->outgoing = incoming;
|
||||
}
|
||||
else if (MEM_P (incoming)
|
||||
&& REG_P (XEXP (incoming, 0))
|
||||
&& HARD_REGISTER_P (XEXP (incoming, 0)))
|
||||
{
|
||||
rtx reg = XEXP (incoming, 0);
|
||||
if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
|
||||
{
|
||||
parm_reg_t *p
|
||||
= VEC_safe_push (parm_reg_t, gc, windowed_parm_regs, NULL);
|
||||
p->incoming = reg;
|
||||
reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
|
||||
p->outgoing = reg;
|
||||
incoming = replace_equiv_address_nv (incoming, reg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!vt_get_decl_and_offset (incoming, &decl, &offset))
|
||||
{
|
||||
if (REG_P (incoming) || MEM_P (incoming))
|
||||
|
@ -9046,6 +9135,7 @@ vt_finalize (void)
|
|||
cselib_finish ();
|
||||
BITMAP_FREE (scratch_regs);
|
||||
scratch_regs = NULL;
|
||||
VEC_free (parm_reg_t, gc, windowed_parm_regs);
|
||||
}
|
||||
|
||||
if (vui_vec)
|
||||
|
|
Loading…
Reference in New Issue