summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/function.c23
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/sched-deps.c28
-rw-r--r--gcc/sched-int.h11
-rw-r--r--gcc/shrink-wrap.c6
6 files changed, 89 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5b6467293d1..cfd0929a1fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+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
diff --git a/gcc/function.c b/gcc/function.c
index ea40ad1be89..0b1d16805ac 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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. */
diff --git a/gcc/function.h b/gcc/function.h
index 590a490af05..e854c7f1c99 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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);
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 6cd833272b8..1ebd7766901 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -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;
}
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index b4a7f925287..d067b43c36e 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -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;
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
index 7345d2573ef..4395d8a1cf7 100644
--- a/gcc/shrink-wrap.c
+++ b/gcc/shrink-wrap.c
@@ -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);
}