summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2016-10-28 14:39:28 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2016-10-28 14:39:28 +0000
commit5a321af036921c86828f9c4c88146d870aa7cbaa (patch)
tree32410170d71a2ec4dfcafe368b6e6f93cbd4ae0e
parent3d3e04acc6a8f7545d2c589319162967fb7f763a (diff)
downloadgcc-5a321af036921c86828f9c4c88146d870aa7cbaa.tar.gz
sched: Do not mix prologue and epilogue insns
This patch makes scheduling not reorder prologue insns relative to epilogue insns and vice versa. This fixes PR78029. The problem in that PR: We have two insns, in this order: (insn/f 300 299 267 8 (set (reg:DI 65 lr) (reg:DI 0 0)) 579 {*movdi_internal64} (expr_list:REG_DEAD (reg:DI 0 0) (expr_list:REG_CFA_RESTORE (reg:DI 65 lr) (nil)))) ... (insn/f 310 268 134 8 (set (mem/c:DI (plus:DI (reg/f:DI 1 1) (const_int 144 [0x90])) [6 S8 A8]) (reg:DI 0 0)) 579 {*movdi_internal64} (expr_list:REG_DEAD (reg:DI 0 0) (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 1 1) (const_int 144 [0x90])) [6 S8 A8]) (reg:DI 65 lr)) (nil)))) and sched swaps them (when compiling for power6, it tries to put memory stores together, so insn 310 is moved up past 300 to go together with some other store). But the REG_CFA_RESTORE and REG_CFA_OFFSET cannot be swapped (they both say where the orig value of LR now lives). 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@241650 138bc75d-0d04-0410-961f-82ee72b054a4
-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);
}