* [patch] Fix PR target/48220 for the SPARC
@ 2011-07-14 21:45 Eric Botcazou
2011-07-15 16:09 ` Richard Henderson
0 siblings, 1 reply; 3+ messages in thread
From: Eric Botcazou @ 2011-07-14 21:45 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1495 bytes --]
Hi,
this adds support for DW_OP_GNU_entry_value/DW_TAG_GNU_call_site_parameter on
SPARC-like architectures (architectures with register windows and explicit
window save instruction). The transformation OUTGOING_REGNO -> INCOMING_REGNO
is explicit for them and not tied to the call-to-subroutine instruction, so
this needs to be modelled if you want precise variable tracking.
Tested on SPARC/Solaris (both GCC and GDB) and x86/Linux. OK for mainline?
2011-07-14 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.
--
Eric Botcazou
[-- Attachment #2: pr48220.diff --]
[-- Type: text/x-diff, Size: 11384 bytes --]
Index: cfgexpand.c
===================================================================
--- cfgexpand.c (revision 176072)
+++ cfgexpand.c (working copy)
@@ -2358,8 +2358,60 @@ convert_debug_memory_address (enum machi
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;
Index: var-tracking.c
===================================================================
--- var-tracking.c (revision 176072)
+++ var-tracking.c (working copy)
@@ -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, da
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, datafl
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, datafl
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, datafl
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, datafl
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, datafl
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)
Index: doc/md.texi
===================================================================
--- doc/md.texi (revision 176072)
+++ doc/md.texi (working copy)
@@ -5250,6 +5250,14 @@ Using a prologue pattern is generally pr
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}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch] Fix PR target/48220 for the SPARC
2011-07-14 21:45 [patch] Fix PR target/48220 for the SPARC Eric Botcazou
@ 2011-07-15 16:09 ` Richard Henderson
2011-07-22 19:43 ` Eric Botcazou
0 siblings, 1 reply; 3+ messages in thread
From: Richard Henderson @ 2011-07-15 16:09 UTC (permalink / raw)
To: Eric Botcazou; +Cc: gcc-patches
On 07/14/2011 02:42 PM, Eric Botcazou wrote:
> 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.
Ok.
r~
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch] Fix PR target/48220 for the SPARC
2011-07-15 16:09 ` Richard Henderson
@ 2011-07-22 19:43 ` Eric Botcazou
0 siblings, 0 replies; 3+ messages in thread
From: Eric Botcazou @ 2011-07-22 19:43 UTC (permalink / raw)
To: Richard Henderson; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1323 bytes --]
> > * 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.
>
> Ok.
Thanks. As found out by Rainer, I made a stupid mistake in the last hunk.
Tested on i586-suse-linux, pre-approved by Jakub, applied on the mainline.
2011-07-22 Eric Botcazou <ebotcazou@adacore.com>
PR debug/49815
* var-tracking.c (vt_finalize): Always free windowed_parm_regs.
--
Eric Botcazou
[-- Attachment #2: pr49815.diff --]
[-- Type: text/x-diff, Size: 468 bytes --]
Index: var-tracking.c
===================================================================
--- var-tracking.c (revision 176622)
+++ var-tracking.c (working copy)
@@ -9135,9 +9135,10 @@ vt_finalize (void)
cselib_finish ();
BITMAP_FREE (scratch_regs);
scratch_regs = NULL;
- VEC_free (parm_reg_t, gc, windowed_parm_regs);
}
+ VEC_free (parm_reg_t, gc, windowed_parm_regs);
+
if (vui_vec)
XDELETEVEC (vui_vec);
vui_vec = NULL;
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-07-22 18:48 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-14 21:45 [patch] Fix PR target/48220 for the SPARC Eric Botcazou
2011-07-15 16:09 ` Richard Henderson
2011-07-22 19:43 ` Eric Botcazou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).