aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgrtl.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2011-03-26 13:03:46 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2011-03-26 13:03:46 +0000
commitba5e9aca8690bcb5ff4e353dc2738050ab3d9fd0 (patch)
treed62fdb4e2bf55596cf3feea95658385026ca7c2f /gcc/cfgrtl.c
parent5d369d583699112c7339f1f5555bd592f6fed70c (diff)
downloadgcc-ba5e9aca8690bcb5ff4e353dc2738050ab3d9fd0.zip
gcc-ba5e9aca8690bcb5ff4e353dc2738050ab3d9fd0.tar.gz
gcc-ba5e9aca8690bcb5ff4e353dc2738050ab3d9fd0.tar.bz2
basic-block.h (fixup_abnormal_edges): Adjust prototype.
* basic-block.h (fixup_abnormal_edges): Adjust prototype. * reload1.c (reload): Adjust call to fixup_abnormal_edges. Rediscover basic blocks and call commit_edge_insertions directly. (fixup_abnormal_edges): Move from here to... * cfgrtl.c (fixup_abnormal_edges): ...here. Only insert instructions on the edges and return whether some have actually been inserted. * reg-stack.c (convert_regs): Fix up abnormal edges before inserting compensation code. From-SVN: r171556
Diffstat (limited to 'gcc/cfgrtl.c')
-rw-r--r--gcc/cfgrtl.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index e78f5ba..9031886 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
insert_insn_on_edge, commit_edge_insertions
- CFG updating after insn simplification
purge_dead_edges, purge_all_dead_edges
+ - CFG fixing after coarse manipulation
+ fixup_abnormal_edges
Functions not supposed for generic use:
- Infrastructure to determine quickly basic block for insn
@@ -2471,6 +2473,95 @@ purge_all_dead_edges (void)
return purged;
}
+/* This is used by a few passes that emit some instructions after abnormal
+ calls, moving the basic block's end, while they in fact do want to emit
+ them on the fallthru edge. Look for abnormal call edges, find backward
+ the call in the block and insert the instructions on the edge instead.
+
+ Similarly, handle instructions throwing exceptions internally.
+
+ Return true when instructions have been found and inserted on edges. */
+
+bool
+fixup_abnormal_edges (void)
+{
+ bool inserted = false;
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+ edge_iterator ei;
+
+ /* Look for cases we are interested in - calls or instructions causing
+ exceptions. */
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if ((e->flags & EDGE_ABNORMAL_CALL)
+ || ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
+ == (EDGE_ABNORMAL | EDGE_EH)))
+ break;
+
+ if (e && !CALL_P (BB_END (bb)) && !can_throw_internal (BB_END (bb)))
+ {
+ rtx insn;
+
+ /* Get past the new insns generated. Allow notes, as the insns
+ may be already deleted. */
+ insn = BB_END (bb);
+ while ((NONJUMP_INSN_P (insn) || NOTE_P (insn))
+ && !can_throw_internal (insn)
+ && insn != BB_HEAD (bb))
+ insn = PREV_INSN (insn);
+
+ if (CALL_P (insn) || can_throw_internal (insn))
+ {
+ rtx stop, next;
+
+ e = find_fallthru_edge (bb->succs);
+
+ stop = NEXT_INSN (BB_END (bb));
+ BB_END (bb) = insn;
+
+ for (insn = NEXT_INSN (insn); insn != stop; insn = next)
+ {
+ next = NEXT_INSN (insn);
+ if (INSN_P (insn))
+ {
+ delete_insn (insn);
+
+ /* Sometimes there's still the return value USE.
+ If it's placed after a trapping call (i.e. that
+ call is the last insn anyway), we have no fallthru
+ edge. Simply delete this use and don't try to insert
+ on the non-existent edge. */
+ if (GET_CODE (PATTERN (insn)) != USE)
+ {
+ /* We're not deleting it, we're moving it. */
+ INSN_DELETED_P (insn) = 0;
+ PREV_INSN (insn) = NULL_RTX;
+ NEXT_INSN (insn) = NULL_RTX;
+
+ insert_insn_on_edge (insn, e);
+ inserted = true;
+ }
+ }
+ else if (!BARRIER_P (insn))
+ set_block_for_insn (insn, NULL);
+ }
+ }
+
+ /* It may be that we don't find any trapping insn. In this
+ case we discovered quite late that the insn that had been
+ marked as can_throw_internal in fact couldn't trap at all.
+ So we should in fact delete the EH edges out of the block. */
+ else
+ purge_dead_edges (bb);
+ }
+ }
+
+ return inserted;
+}
+
/* Same as split_block but update cfg_layout structures. */
static basic_block