aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-07-26 22:36:01 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2001-07-26 20:36:01 +0000
commit01f62f016bb811b0010a36d058c660882a92ca1c (patch)
tree4d6e8197e32e92b663df66e7f3d07be1ccf41202 /gcc
parentaa069f77b2591aed51274befe68aeef5c903f45c (diff)
downloadgcc-01f62f016bb811b0010a36d058c660882a92ca1c.zip
gcc-01f62f016bb811b0010a36d058c660882a92ca1c.tar.gz
gcc-01f62f016bb811b0010a36d058c660882a92ca1c.tar.bz2
rtl.h (cleanup_barriers): Declare.
* rtl.h (cleanup_barriers): Declare. * jump.c (cleanup_barriers): New function. * toplev.c (rest_of_compilation): Call cleanup_barriers before loop optimizer and after bb_reorder. * flow.c (back_edge_of_syntactic_loop_p): New. (split_edge): Use it. From-SVN: r44409
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/flow.c28
-rw-r--r--gcc/jump.c26
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/toplev.c4
5 files changed, 68 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0ab4a10..fddead1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+Thu Jul 26 22:30:22 CEST 2001 Jan Hubicka <jh@suse.cz>
+
+ * rtl.h (cleanup_barriers): Declare.
+ * jump.c (cleanup_barriers): New function.
+ * toplev.c (rest_of_compilation): Call cleanup_barriers
+ before loop optimizer and after bb_reorder.
+
+ * flow.c (back_edge_of_syntactic_loop_p): New.
+ (split_edge): Use it.
+
2001-07-26 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
* glimits.h (_MACH_MACHLIMITS_H_): Delete.
diff --git a/gcc/flow.c b/gcc/flow.c
index cd33dec..248d429 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -482,6 +482,7 @@ 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));
+static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
/* Find basic blocks of the current function.
F is the first insn of the function and NREGS the number of register
@@ -1968,6 +1969,30 @@ redirect_edge_and_branch_force (e, target)
return new_bb;
}
+/* Helper function for split_edge. Return true in case edge BB2 to BB1
+ is back edge of syntactic loop. */
+static bool
+back_edge_of_syntactic_loop_p (bb1, bb2)
+ basic_block bb1, bb2;
+{
+ rtx insn;
+ int count;
+ if (bb1->index > bb2->index)
+ return false;
+ if (bb1->index == bb2->index)
+ return true;
+ for (insn = bb1->end; insn != bb2->head && count >= 0;
+ insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ count++;
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+ count--;
+ }
+ return count >= 0;
+}
+
/* Split a (typically critical) edge. Return the new block.
Abort on abnormal edges.
@@ -2115,7 +2140,8 @@ split_edge (edge_in)
if (old_succ != EXIT_BLOCK_PTR
&& PREV_INSN (old_succ->head)
&& GET_CODE (PREV_INSN (old_succ->head)) == NOTE
- && NOTE_LINE_NUMBER (PREV_INSN (old_succ->head)) == NOTE_INSN_LOOP_BEG)
+ && NOTE_LINE_NUMBER (PREV_INSN (old_succ->head)) == NOTE_INSN_LOOP_BEG
+ && !back_edge_of_syntactic_loop_p (old_succ, old_pred))
bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
PREV_INSN (old_succ->head));
else if (old_succ != EXIT_BLOCK_PTR)
diff --git a/gcc/jump.c b/gcc/jump.c
index 01fc741..e77ba56 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -100,6 +100,32 @@ rebuild_jump_labels (f)
LABEL_NUSES (XEXP (insn, 0))++;
}
+/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
+ non-fallthru insn. This is not generally true, as multiple barriers
+ may have crept in, or the BARRIER may be separated from the last
+ real insn by one or more NOTEs.
+
+ This simple pass moves barriers and removes duplicates so that the
+ old code is happy.
+ */
+void
+cleanup_barriers ()
+{
+ rtx insn, next, prev;
+ for (insn = get_insns (); insn; insn = next)
+ {
+ next = NEXT_INSN (insn);
+ if (GET_CODE (insn) == BARRIER)
+ {
+ prev = prev_nonnote_insn (insn);
+ if (GET_CODE (prev) == BARRIER)
+ delete_barrier (insn);
+ else if (prev != PREV_INSN (insn))
+ reorder_insns (insn, insn, prev);
+ }
+ }
+}
+
void
copy_loop_headers (f)
rtx f;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 1fbc9da..7cacfab 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1286,6 +1286,7 @@ extern enum rtx_code swap_condition PARAMS ((enum rtx_code));
extern enum rtx_code unsigned_condition PARAMS ((enum rtx_code));
extern enum rtx_code signed_condition PARAMS ((enum rtx_code));
extern void mark_jump_label PARAMS ((rtx, rtx, int));
+extern void cleanup_barriers PARAMS ((void));
/* In jump.c */
extern rtx squeeze_notes PARAMS ((rtx, rtx));
diff --git a/gcc/toplev.c b/gcc/toplev.c
index a28b38e..21d4fbb 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3096,6 +3096,8 @@ rest_of_compilation (decl)
if (flag_rerun_loop_opt)
{
+ cleanup_barriers ();
+
/* We only want to perform unrolling once. */
loop_optimize (insns, rtl_dump_file, 0);
@@ -3110,6 +3112,7 @@ rest_of_compilation (decl)
analysis code depends on this information. */
reg_scan (insns, max_reg_num (), 1);
}
+ cleanup_barriers ();
loop_optimize (insns, rtl_dump_file,
(flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
@@ -3614,6 +3617,7 @@ rest_of_compilation (decl)
/* CFG no longer kept up to date. */
purge_line_number_notes (insns);
+ cleanup_barriers ();
/* If a scheduling pass for delayed branches is to be done,
call the scheduling code. */