summaryrefslogtreecommitdiff
path: root/gcc/var-tracking.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-15 20:10:04 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-15 20:10:04 +0000
commit438ee47fa49f415baa8e6e9aea8d697aff121c93 (patch)
tree3519298958c5b72ad7fd278d9325609ae878f932 /gcc/var-tracking.c
parenta50f08393c40a888a5d8786b289e3c63cd0cc7c3 (diff)
downloadgcc-438ee47fa49f415baa8e6e9aea8d697aff121c93.tar.gz
2011-07-15 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 176319 using svnmerge. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@176330 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/var-tracking.c')
-rw-r--r--gcc/var-tracking.c100
1 files changed, 95 insertions, 5 deletions
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index b3f84a17044..4842b780201 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -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)