@@ -5752,6 +5752,18 @@ contains (const_rtx insn, hash_table<insn_cache_hasher> *hash)
}
int
+prologue_contains (const_rtx insn)
+{
+ return contains (insn, prologue_insn_hash);
+}
+
+int
+epilogue_contains (const_rtx insn)
+{
+ return contains (insn, epilogue_insn_hash);
+}
+
+int
prologue_epilogue_contains (const_rtx insn)
{
if (contains (insn, prologue_insn_hash))
@@ -5761,6 +5773,17 @@ prologue_epilogue_contains (const_rtx insn)
return 0;
}
+void
+record_prologue_seq (rtx_insn *seq)
+{
+ record_insns (seq, NULL, &prologue_insn_hash);
+}
+
+void
+record_epilogue_seq (rtx_insn *seq)
+{
+ record_insns (seq, NULL, &epilogue_insn_hash);
+}
/* Set JUMP_LABEL for a return insn. */
@@ -628,7 +628,11 @@ extern void clobber_return_register (void);
extern void expand_function_end (void);
extern rtx get_arg_pointer_save_area (void);
extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
+extern int prologue_contains (const_rtx);
+extern int epilogue_contains (const_rtx);
extern int prologue_epilogue_contains (const_rtx);
+extern void record_prologue_seq (rtx_insn *);
+extern void record_epilogue_seq (rtx_insn *);
extern void emit_return_into_block (bool simple_p, basic_block bb);
extern void set_return_jump_label (rtx_insn *);
extern bool active_insn_between (rtx_insn *head, rtx_insn *tail);
@@ -3502,6 +3502,31 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
if (!deps->readonly)
deps->last_args_size = insn;
}
+
+ /* We must not mix prologue and epilogue insns. See PR78029. */
+ if (prologue_contains (insn))
+ {
+ add_dependence_list (insn, deps->last_epilogue, true, REG_DEP_ANTI, true);
+ if (!deps->readonly)
+ {
+ if (deps->last_logue_was_epilogue)
+ free_INSN_LIST_list (&deps->last_prologue);
+ deps->last_prologue = alloc_INSN_LIST (insn, deps->last_prologue);
+ deps->last_logue_was_epilogue = false;
+ }
+ }
+
+ if (epilogue_contains (insn))
+ {
+ add_dependence_list (insn, deps->last_prologue, true, REG_DEP_ANTI, true);
+ if (!deps->readonly)
+ {
+ if (!deps->last_logue_was_epilogue)
+ free_INSN_LIST_list (&deps->last_epilogue);
+ deps->last_epilogue = alloc_INSN_LIST (insn, deps->last_epilogue);
+ deps->last_logue_was_epilogue = true;
+ }
+ }
}
/* Return TRUE if INSN might not always return normally (e.g. call exit,
@@ -3907,6 +3932,9 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
deps->in_post_call_group_p = not_post_call;
deps->last_debug_insn = 0;
deps->last_args_size = 0;
+ deps->last_prologue = 0;
+ deps->last_epilogue = 0;
+ deps->last_logue_was_epilogue = false;
deps->last_reg_pending_barrier = NOT_A_BARRIER;
deps->readonly = 0;
}
@@ -537,6 +537,17 @@ struct deps_desc
/* The last insn bearing REG_ARGS_SIZE that we've seen. */
rtx_insn *last_args_size;
+ /* A list of all prologue insns we have seen without intervening epilogue
+ insns, and one of all epilogue insns we have seen without intervening
+ prologue insns. This is used to prevent mixing prologue and epilogue
+ insns. See PR78029. */
+ rtx_insn_list *last_prologue;
+ rtx_insn_list *last_epilogue;
+
+ /* Whether the last *logue insn was an epilogue insn or a prologue insn
+ instead. */
+ bool last_logue_was_epilogue;
+
/* The maximum register number for the following arrays. Before reload
this is max_reg_num; after reload it is FIRST_PSEUDO_REGISTER. */
int max_reg;
@@ -1434,6 +1434,7 @@ emit_common_heads_for_components (sbitmap components)
targetm.shrink_wrap.emit_prologue_components (pro);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_prologue_seq (seq);
emit_insn_after (seq, bb_note (bb));
@@ -1446,6 +1447,7 @@ emit_common_heads_for_components (sbitmap components)
targetm.shrink_wrap.emit_epilogue_components (epi);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_epilogue_seq (seq);
emit_insn_after (seq, bb_note (bb));
@@ -1533,6 +1535,7 @@ emit_common_tails_for_components (sbitmap components)
targetm.shrink_wrap.emit_epilogue_components (epi);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_epilogue_seq (seq);
if (control_flow_insn_p (last_insn))
emit_insn_before (seq, last_insn);
@@ -1548,6 +1551,7 @@ emit_common_tails_for_components (sbitmap components)
targetm.shrink_wrap.emit_prologue_components (pro);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_prologue_seq (seq);
if (control_flow_insn_p (last_insn))
emit_insn_before (seq, last_insn);
@@ -1612,6 +1616,7 @@ insert_prologue_epilogue_for_components (sbitmap components)
targetm.shrink_wrap.emit_epilogue_components (epi);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_epilogue_seq (seq);
if (e->flags & EDGE_SIBCALL)
{
@@ -1635,6 +1640,7 @@ insert_prologue_epilogue_for_components (sbitmap components)
targetm.shrink_wrap.emit_prologue_components (pro);
seq = get_insns ();
end_sequence ();
+ record_prologue_seq (seq);
insert_insn_on_edge (seq, e);
}