aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-08-04 14:08:43 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2001-08-04 12:08:43 +0000
commitf133022600b6df6e3ed8eae718b22a8534b60874 (patch)
tree52edd2af4071bdd3a36e9e4326fda3898b0340fc /gcc/reload1.c
parentef6e958a8611ff372211d0fd3cd9659614583bb4 (diff)
downloadgcc-f133022600b6df6e3ed8eae718b22a8534b60874.zip
gcc-f133022600b6df6e3ed8eae718b22a8534b60874.tar.gz
gcc-f133022600b6df6e3ed8eae718b22a8534b60874.tar.bz2
* loop.c (try_copy_prop); Kill invalidated REG_EQUAL notes.
* reload1.c (fixup_abnormal_edges): New static function. (reload): Use it. * flow.c (need_fake_edge_p): New function. (flow_call_edges_add): Fix handling of noreturn and sibbling calls; avoid call insn to be very last insn in the insn stream. * profile.c (branch_prob): Call flow_call_edges_add instead of doing that by hand; cleanup cfg to re-merge basic blocks once we are done. From-SVN: r44635
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index ced823b..09ef4ef 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -461,6 +461,7 @@ static void failed_reload PARAMS ((rtx, int));
static int set_reload_reg PARAMS ((int, int));
static void reload_cse_delete_noop_set PARAMS ((rtx, rtx));
static void reload_cse_simplify PARAMS ((rtx));
+static void fixup_abnormal_edges PARAMS ((void));
extern void dump_needs PARAMS ((struct insn_chain *));
/* Initialize the reload pass once per compilation. */
@@ -1269,6 +1270,7 @@ reload (first, global)
/* Free all the insn_chain structures at once. */
obstack_free (&reload_obstack, reload_startobj);
unused_insn_chains = 0;
+ fixup_abnormal_edges ();
return failure;
}
@@ -9470,3 +9472,56 @@ copy_eh_notes (insn, x)
}
}
+/* This is used by reload pass, that does emit some instructions after
+ abnormal calls moving basic block end, but in fact it wants to emit
+ them on the edge. Looks for abnormal call edges, find backward the
+ proper call and fix the damage.
+
+ Similar handle instructions throwing exceptions internally. */
+static void
+fixup_abnormal_edges ()
+{
+ int i;
+ bool inserted = false;
+
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ edge e;
+
+ /* Look for cases we are interested in - an calls or instructions causing
+ exceptions. */
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ if (e->flags & EDGE_ABNORMAL_CALL)
+ break;
+ if ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
+ == (EDGE_ABNORMAL | EDGE_EH))
+ break;
+ }
+ if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end))
+ {
+ rtx insn = bb->end;
+ rtx next;
+ for (e = bb->succ; e; e = e->succ_next)
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+ while (GET_CODE (insn) == INSN && !can_throw_internal (insn))
+ insn = PREV_INSN (insn);
+ if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
+ abort ();
+ bb->end = insn;
+ inserted = true;
+ insn = NEXT_INSN (insn);
+ while (insn && GET_CODE (insn) == INSN)
+ {
+ next = NEXT_INSN (insn);
+ insert_insn_on_edge (PATTERN (insn), e);
+ flow_delete_insn (insn);
+ insn = next;
+ }
+ }
+ }
+ if (inserted)
+ commit_edge_insertions ();
+}