From 6e64a52a928d47c3b8f9dad8549866b869c37491 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 25 Jul 2001 22:51:24 +0200 Subject: [PATCH] flow.c (delete_dead_jumptables): New function. * flow.c (delete_dead_jumptables): New function. (life_analyzis): Call it. * bb-reorder.c (skip_insns_after_block): Handle contradictive sequences. From-SVN: r44365 --- gcc/ChangeLog | 6 ++++ gcc/bb-reorder.c | 35 +++++++++++++++++----- gcc/flow.c | 77 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 102 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 973a821b3c4..9eb513e515a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +Wed Jul 25 22:48:59 CEST 2001 Jan Hubicka + + * flow.c (delete_dead_jumptables): New function. + (life_analyzis): Call it. + * bb-reorder.c (skip_insns_after_block): Handle contradictive sequences. + 2001-07-25 Richard Henderson * except.c (reachable_handlers): Handle a region being removed diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index e2dc44c5053..e1b341755b1 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -205,7 +205,7 @@ static rtx skip_insns_after_block (bb) basic_block bb; { - rtx insn, last_insn, next_head; + rtx insn, last_insn, next_head, prev; next_head = NULL_RTX; if (bb->index + 1 != n_basic_blocks) @@ -234,12 +234,7 @@ skip_insns_after_block (bb) continue; default: - /* Make line notes attached to the succesor block unless they - are followed by something attached to predecesor block. - These notes remained after removing code in the predecesor - block and thus should be kept together. */ - if (NOTE_LINE_NUMBER (insn) >= 0) - continue; + continue; break; } break; @@ -262,6 +257,32 @@ skip_insns_after_block (bb) break; } + /* It is possible to hit contradicting sequence. For instance: + + jump_insn + NOTE_INSN_LOOP_BEG + barrier + + Where barrier belongs to jump_insn, but the note does not. + This can be created by removing the basic block originally + following NOTE_INSN_LOOP_BEG. + + In such case reorder the notes. */ + for (insn = last_insn; insn != bb->end; insn = prev) + { + prev = PREV_INSN (insn); + if (GET_CODE (insn) == NOTE) + switch (NOTE_LINE_NUMBER (insn)) + { + case NOTE_INSN_LOOP_END: + case NOTE_INSN_BLOCK_END: + case NOTE_INSN_DELETED: + case NOTE_INSN_DELETED_LABEL: + continue; + default: + reorder_insns (insn, insn, last_insn); + } + } return last_insn; } diff --git a/gcc/flow.c b/gcc/flow.c index 67a2db559f2..529eb00ddf0 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -481,6 +481,7 @@ static void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *)); static void flow_loops_tree_build PARAMS ((struct loops *)); static int flow_loop_level_compute PARAMS ((struct loop *, int)); static int flow_loops_level_compute PARAMS ((struct loops *)); +static void delete_dead_jumptables PARAMS ((void)); /* Find basic blocks of the current function. F is the first insn of the function and NREGS the number of register @@ -4081,6 +4082,8 @@ life_analysis (f, file, flags) } } #endif + /* Removing dead insns should've made jumptables really dead. */ + delete_dead_jumptables (); } /* A subroutine of verify_wide_reg, called through for_each_rtx. @@ -4334,6 +4337,32 @@ delete_noop_moves (f) } } +/* Delete any jump tables never referenced. We can't delete them at the + time of removing tablejump insn as they are referenced by the preceeding + insns computing the destination, so we delay deleting and garbagecollect + them once life information is computed. */ +static void +delete_dead_jumptables () +{ + rtx insn, next; + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + if (GET_CODE (insn) == CODE_LABEL + && LABEL_NUSES (insn) == 0 + && GET_CODE (next) == JUMP_INSN + && (GET_CODE (PATTERN (next)) == ADDR_VEC + || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)) + { + if (rtl_dump_file) + fprintf (rtl_dump_file, "Dead jumptable %i removed\n", INSN_UID (insn)); + flow_delete_insn (NEXT_INSN (insn)); + flow_delete_insn (insn); + next = NEXT_INSN (next); + } + } +} + /* Determine if the stack pointer is constant over the life of the function. Only useful before prologues have been emitted. */ @@ -7956,7 +7985,7 @@ set_block_for_new_insns (insn, bb) - test head/end pointers - overlapping of basic blocks - - edge list corectness + - edge list correctness - headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note) - tails of basic blocks (ensure that boundary is necesary) - scans body of the basic block for JUMP_INSN, CODE_LABEL @@ -8031,8 +8060,9 @@ verify_flow_info () for (i = n_basic_blocks - 1; i >= 0; i--) { basic_block bb = BASIC_BLOCK (i); - /* Check corectness of edge lists */ + /* Check correctness of edge lists. */ edge e; + int has_fallthru = 0; e = bb->succ; while (e) @@ -8045,17 +8075,31 @@ verify_flow_info () } last_visited [e->dest->index + 2] = bb; + if (e->flags & EDGE_FALLTHRU) + has_fallthru = 1; + if ((e->flags & EDGE_FALLTHRU) && e->src != ENTRY_BLOCK_PTR - && e->dest != EXIT_BLOCK_PTR - && (e->src->index + 1 != e->dest->index - || !can_fallthru (e->src, e->dest))) + && e->dest != EXIT_BLOCK_PTR) { - error ("verify_flow_info: Incorrect fallthru edge %i->%i", - e->src->index, e->dest->index); - err = 1; + rtx insn; + if (e->src->index + 1 != e->dest->index) + { + error ("verify_flow_info: Incorrect blocks for fallthru %i->%i", + e->src->index, e->dest->index); + err = 1; + } + else + for (insn = NEXT_INSN (e->src->end); insn != e->dest->head; + insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == BARRIER || INSN_P (insn)) + { + error ("verify_flow_info: Incorrect fallthru %i->%i", + e->src->index, e->dest->index); + fatal_insn ("Wrong insn in the fallthru edge", insn); + err = 1; + } } - if (e->src != bb) { error ("verify_flow_info: Basic block %d succ edge is corrupted", @@ -8080,6 +8124,21 @@ verify_flow_info () } e = e->succ_next; } + if (!has_fallthru) + { + rtx insn = bb->end; + + /* Ensure existence of barrier in BB with no fallthru edges. */ + for (insn = bb->end; GET_CODE (insn) != BARRIER; + insn = NEXT_INSN (insn)) + if (!insn + || (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)) + { + error ("Missing barrier after block %i", bb->index); + err = 1; + } + } e = bb->pred; while (e) -- 2.30.2