diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/function.c | 23 | ||||
-rw-r--r-- | gcc/function.h | 4 | ||||
-rw-r--r-- | gcc/sched-deps.c | 28 | ||||
-rw-r--r-- | gcc/sched-int.h | 11 | ||||
-rw-r--r-- | gcc/shrink-wrap.c | 6 |
6 files changed, 89 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b64672..cfd0929 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 ea40ad1..0b1d168 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 590a490..e854c7f 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 6cd8332..1ebd776 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 b4a7f92..d067b43 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 7345d25..4395d8a 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); } |