#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
+#include "insn-config.h"
+#include "recog.h"
#include "toplev.h"
-
#include "obstack.h"
+#include "tm_p.h"
/* Store the data structures necessary for depth-first search. */
struct depth_first_search_dsS {
spanning tree in the case that the call doesn't return.
Handle this by adding a dummy instruction in a new last basic block. */
- if (check_last_block
- && need_fake_edge_p (BASIC_BLOCK (n_basic_blocks - 1)->end))
+ if (check_last_block)
{
- edge e;
+ basic_block bb = BASIC_BLOCK (n_basic_blocks - 1);
+ rtx insn = bb->end;
- for (e = BASIC_BLOCK (n_basic_blocks - 1)->succ; e; e = e->succ_next)
- if (e->dest == EXIT_BLOCK_PTR)
- break;
+ /* Back up past insns that must be kept in the same block as a call. */
+ while (insn != bb->head
+ && keep_with_call_p (insn))
+ insn = PREV_INSN (insn);
+
+ if (need_fake_edge_p (insn))
+ {
+ edge e;
- insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
- commit_edge_insertions ();
+ for (e = bb->succ; e; e = e->succ_next)
+ if (e->dest == EXIT_BLOCK_PTR)
+ break;
+
+ insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
+ commit_edge_insertions ();
+ }
}
/* Now add fake edges to the function exit for any non constant
if (need_fake_edge_p (insn))
{
edge e;
+ rtx split_at_insn = insn;
+
+ /* Don't split the block between a call and an insn that should
+ remain in the same block as the call. */
+ if (GET_CODE (insn) == CALL_INSN)
+ while (split_at_insn != bb->end
+ && keep_with_call_p (NEXT_INSN (split_at_insn)))
+ split_at_insn = NEXT_INSN (split_at_insn);
- /* The above condition should be enough to verify that there is
- no edge to the exit block in CFG already. Calling make_edge
- in such case would make us to mark that edge as fake and
- remove it later. */
+ /* The handling above of the final block before the epilogue
+ should be enough to verify that there is no edge to the exit
+ block in CFG already. Calling make_edge in such case would
+ cause us to mark that edge as fake and remove it later. */
#ifdef ENABLE_CHECKING
- if (insn == bb->end)
+ if (split_at_insn == bb->end)
for (e = bb->succ; e; e = e->succ_next)
if (e->dest == EXIT_BLOCK_PTR)
abort ();
/* Note that the following may create a new basic block
and renumber the existing basic blocks. */
- e = split_block (bb, insn);
+ e = split_block (bb, split_at_insn);
if (e)
blocks_split++;