+2016-10-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/78029
+ * function.c (prologue_contains, epilogue_contains): New functions.
+ (record_prologue_seq, record_epilogue_seq): New functions.
+ * function.h (prologue_contains, epilogue_contains,
+ record_prologue_seq, record_epilogue_seq): New declarations.
+ * sched-deps.c (sched_analyze_insn): Make dependencies to prevent
+ mixing prologue and epilogue insns.
+ (init_deps): Initialize the new fields in struct deps_desc.
+ * sched-int.h (struct deps_desc): New fields last_prologue,
+ last_epilogue, and last_logue_was_epilogue.
+ * shrink-wrap.c (emit_common_heads_for_components): Record all
+ emitted prologue and epilogue insns.
+ (emit_common_tails_for_components): Ditto.
+ (insert_prologue_epilogue_for_components): Ditto.
+
2016-10-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR middle-end/22141
return hash->find (const_cast<rtx> (insn)) != NULL;
}
+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)
{
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. */
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);
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,
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;
}
/* 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;
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));
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));
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);
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);
targetm.shrink_wrap.emit_epilogue_components (epi);
rtx_insn *seq = get_insns ();
end_sequence ();
+ record_epilogue_seq (seq);
if (e->flags & EDGE_SIBCALL)
{
targetm.shrink_wrap.emit_prologue_components (pro);
seq = get_insns ();
end_sequence ();
+ record_prologue_seq (seq);
insert_insn_on_edge (seq, e);
}