summaryrefslogtreecommitdiffstats
path: root/gcc/haifa-sched.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-03-08 02:15:26 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-03-08 02:15:26 +0000
commitdf6c1c81ab4afd443018c0bfb5624fe0392edcf5 (patch)
tree56bb1b57f71a20e0b59f7213f7821d27d1f5b592 /gcc/haifa-sched.c
parent9ed8bc90030122d4a0a36b05e54dc968a706052d (diff)
downloadppe42-gcc-df6c1c81ab4afd443018c0bfb5624fe0392edcf5.tar.gz
ppe42-gcc-df6c1c81ab4afd443018c0bfb5624fe0392edcf5.zip
* haifa-sched.c (is_cfg_nonregular): Change return type to
an int. No longer compute "estimated" number of edges. Use computed_jump_p instead of duplicating the code. Fixup/add some comments. (build_control_flow): Returns a value indicating an irregularity in the cfg was detected. Count the number of edges in the cfg. allocate various edge tables. (find_rgns): No longer look for unreachable blocks. (schedule_insns): Do not allocate memory for edge tables here. Free memory for edge tables before returning. Do not perform cross block scheduling if build_control_flow returns nonzero. * flow.c (compute_preds_succs): More accurately determine when a block drops in. Fixes various compile hangs after haifa cleanup. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18439 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/haifa-sched.c')
-rw-r--r--gcc/haifa-sched.c262
1 files changed, 77 insertions, 185 deletions
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index b9b6202e3ec..264e4226fa0 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -517,10 +517,9 @@ static int *out_edges;
extern rtx forced_labels;
-static char is_cfg_nonregular PROTO ((void));
-static int uses_reg_or_mem PROTO ((rtx));
+static int is_cfg_nonregular PROTO ((void));
void debug_control_flow PROTO ((void));
-static void build_control_flow PROTO ((void));
+static int build_control_flow PROTO ((void));
static void new_edge PROTO ((int, int));
@@ -1078,37 +1077,35 @@ static rtx *bb_sched_before_next_call;
/* functions for construction of the control flow graph. */
/* Return 1 if control flow graph should not be constructed, 0 otherwise.
- Estimate in nr_edges the number of edges on the graph.
+
We decide not to build the control flow graph if there is possibly more
- than one entry to the function, or if computed branches exist. */
+ than one entry to the function, if computed branches exist, of if we
+ have nonlocal gotos. */
-static char
+static int
is_cfg_nonregular ()
{
int b;
rtx insn;
RTX_CODE code;
- rtx nonlocal_label_list = nonlocal_label_rtx_list ();
-
- /* check for non local labels */
- if (nonlocal_label_list)
- {
- return 1;
- }
+ /* If we have a label that could be the target of a nonlocal goto, then
+ the cfg is not well structured. */
+ if (nonlocal_label_rtx_list () != NULL)
+ return 1;
- /* check for labels which cannot be deleted */
+ /* If we have any forced labels, then the cfg is not well structured. */
if (forced_labels)
- {
- return 1;
- }
+ return 1;
- /* check for labels which probably cannot be deleted */
+ /* If we have exception handlers, then we consider the cfg not well
+ structured. ?!? We should be able to handle this now that flow.c
+ computes an accurate cfg for EH. */
if (exception_handler_labels)
- {
- return 1;
- }
+ return 1;
+ /* If we have non-jumping insns which refer to labels, then we consider
+ the cfg not well structured. */
/* check for labels referred to other thn by jumps */
for (b = 0; b < n_basic_blocks; b++)
for (insn = basic_block_head[b];; insn = NEXT_INSN (insn))
@@ -1120,150 +1117,31 @@ is_cfg_nonregular ()
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_LABEL)
- {
- return 1;
- }
+ return 1;
}
if (insn == basic_block_end[b])
break;
}
- nr_edges = 0;
-
- /* check for computed branches */
+ /* If this function has a computed jump, then we consider the cfg
+ not well structured. */
for (b = 0; b < n_basic_blocks; b++)
{
for (insn = basic_block_head[b];; insn = NEXT_INSN (insn))
{
-
- if (GET_CODE (insn) == JUMP_INSN)
- {
- rtx pat = PATTERN (insn);
- int i;
-
- if (GET_CODE (pat) == PARALLEL)
- {
- int len = XVECLEN (pat, 0);
- int has_use_labelref = 0;
-
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == USE
- && (GET_CODE (XEXP (XVECEXP (pat, 0, i), 0))
- == LABEL_REF))
- {
- nr_edges++;
- has_use_labelref = 1;
- }
-
- if (!has_use_labelref)
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET
- && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
- && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
- {
- return 1;
- }
- }
- /* check for branch table */
- else if (GET_CODE (pat) == ADDR_VEC
- || GET_CODE (pat) == ADDR_DIFF_VEC)
- {
- int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
- int len = XVECLEN (pat, diff_vec_p);
-
- nr_edges += len;
- }
- else
- {
- /* check for computed branch */
- if (GET_CODE (pat) == SET
- && SET_DEST (pat) == pc_rtx
- && uses_reg_or_mem (SET_SRC (pat)))
- {
- return 1;
- }
- }
- }
+ if (computed_jump_p (insn))
+ return 1;
if (insn == basic_block_end[b])
break;
}
}
- /* count for the fallthrough edges */
- for (b = 0; b < n_basic_blocks; b++)
- {
- for (insn = PREV_INSN (basic_block_head[b]);
- insn && GET_CODE (insn) == NOTE; insn = PREV_INSN (insn))
- ;
-
- if (!insn && b != 0)
- nr_edges++;
- else if (insn && GET_CODE (insn) != BARRIER)
- nr_edges++;
- }
-
- nr_edges++;
-
- return 0;
-}
-
-
-/* Returns 1 if x uses a reg or a mem (function was taken from flow.c).
- x is a target of a jump. Used for the detection of computed
- branches. For each label seen, updates the edges estimation
- counter nr_edges. */
-
-static int
-uses_reg_or_mem (x)
- rtx x;
-{
- enum rtx_code code = GET_CODE (x);
- int i, j;
- char *fmt;
-
- if (code == REG)
- return 1;
-
- if (code == MEM
- && !(GET_CODE (XEXP (x, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))))
- return 1;
-
- if (code == IF_THEN_ELSE)
- {
- if (uses_reg_or_mem (XEXP (x, 1))
- || uses_reg_or_mem (XEXP (x, 2)))
- return 1;
- else
- return 0;
- }
-
- if (code == LABEL_REF)
- {
- nr_edges++;
-
- return 0;
- }
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e'
- && uses_reg_or_mem (XEXP (x, i)))
- return 1;
-
- if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x, i); j++)
- if (uses_reg_or_mem (XVECEXP (x, i, j)))
- return 1;
- }
-
+ /* All the tests passed. Consider the cfg well structured. */
return 0;
}
-
/* Print the control flow graph, for debugging purposes.
Callable from the debugger. */
@@ -1312,9 +1190,12 @@ debug_control_flow ()
/* Build the control flow graph and set nr_edges.
Instead of trying to build a cfg ourselves, we rely on flow to
- do it for us. Stamp out useless code (and bug) duplication. */
+ do it for us. Stamp out useless code (and bug) duplication.
-static void
+ Return nonzero if an irregularity in the cfg is found which would
+ prevent cross block scheduling. */
+
+static int
build_control_flow ()
{
int i, j;
@@ -1323,6 +1204,7 @@ build_control_flow ()
int_list_ptr succ;
int *num_preds;
int *num_succs;
+ int unreachable;
/* The scheduler runs after flow; therefore, we can't blindly call
back into find_basic_blocks since doing so could invalidate the
@@ -1341,6 +1223,27 @@ build_control_flow ()
num_succs = (int *) alloca (n_basic_blocks * sizeof (int));
compute_preds_succs (s_preds, s_succs, num_preds, num_succs);
+ /* Count the number of edges in the cfg. */
+ nr_edges = 0;
+ unreachable = 0;
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ nr_edges += num_succs[i];
+ if (num_preds[i] == 0)
+ unreachable = 1;
+ }
+
+ /* Account for entry/exit edges. */
+ nr_edges += 2;
+
+ in_edges = (int *) xmalloc (n_basic_blocks * sizeof (int));
+ out_edges = (int *) xmalloc (n_basic_blocks * sizeof (int));
+ bzero ((char *) in_edges, n_basic_blocks * sizeof (int));
+ bzero ((char *) out_edges, n_basic_blocks * sizeof (int));
+
+ edge_table = (edge *) xmalloc ((nr_edges) * sizeof (edge));
+ bzero ((char *) edge_table, ((nr_edges) * sizeof (edge)));
+
nr_edges = 0;
for (i = 0; i < n_basic_blocks; i++)
for (succ = s_succs[i]; succ; succ = succ->next)
@@ -1355,6 +1258,7 @@ build_control_flow ()
/* For now. This will move as more and more of haifa is converted
to using the cfg code in flow.c */
free_bb_mem ();
+ return unreachable;
}
@@ -1627,7 +1531,6 @@ find_rgns ()
int count = 0, sp, idx = 0, current_edge = out_edges[0];
int num_bbs, num_insns;
int too_large_failure;
- char *reachable;
/*
The following data structures are computed by the first traversal and
@@ -1664,8 +1567,6 @@ find_rgns ()
bzero ((char *) passed, nr_edges * sizeof (char));
in_stack = (char *) alloca (nr_edges * sizeof (char));
bzero ((char *) in_stack, nr_edges * sizeof (char));
- reachable = (char *) alloca (n_basic_blocks * sizeof (char));
- bzero ((char *) reachable, n_basic_blocks * sizeof (char));
in_queue = (char *) alloca (n_basic_blocks * sizeof (char));
@@ -1677,7 +1578,6 @@ find_rgns ()
/* First traversal: DFS, finds inner loops in control flow graph */
- reachable[0] = 1;
sp = -1;
while (1)
{
@@ -1711,7 +1611,6 @@ find_rgns ()
dfs_nr[node] = ++count;
in_stack[node] = 1;
child = TO_BLOCK (current_edge);
- reachable[child] = 1;
/* found a loop header */
if (in_stack[child])
@@ -1742,19 +1641,6 @@ find_rgns ()
current_edge = OUT_EDGES (child);
} /* while (1); */
- /* if there are unreachable blocks, or more than one entry to
- the subroutine, give up on interblock scheduling */
- for (i = 1; i < n_basic_blocks; i++)
- {
- if (reachable[i] == 0)
- {
- find_single_block_region ();
- if (sched_verbose >= 3)
- fprintf (stderr, "sched: warning: found an unreachable block %d \n", i);
- return;
- }
- }
-
/* Second travsersal: find reducible inner loops, and sort
topologically the blocks of each region */
degree = dfs_nr; /* reuse dfs_nr array - it is not needed anymore */
@@ -8547,31 +8433,20 @@ schedule_insns (dump_file)
}
else
{
- /* an estimation for nr_edges is computed in is_cfg_nonregular () */
- nr_edges = 0;
-
/* verify that a 'good' control flow graph can be built */
- if (is_cfg_nonregular ()
- || nr_edges <= 1)
+ if (is_cfg_nonregular ())
{
find_single_block_region ();
}
else
{
- /* build control flow graph */
- in_edges = (int *) alloca (n_basic_blocks * sizeof (int));
- out_edges = (int *) alloca (n_basic_blocks * sizeof (int));
- bzero ((char *) in_edges, n_basic_blocks * sizeof (int));
- bzero ((char *) out_edges, n_basic_blocks * sizeof (int));
-
- edge_table =
- (edge *) alloca ((nr_edges) * sizeof (edge));
- bzero ((char *) edge_table,
- ((nr_edges) * sizeof (edge)));
- build_control_flow ();
-
- /* identify reducible inner loops and compute regions */
- find_rgns ();
+ /* build_control_flow will return nonzero if it detects unreachable
+ blocks or any other irregularity with the cfg which prevents
+ cross block scheduling. */
+ if (build_control_flow () != 0)
+ find_single_block_region ();
+ else
+ find_rgns ();
if (sched_verbose >= 3)
{
@@ -8711,5 +8586,22 @@ schedule_insns (dump_file)
if (bb_live_regs)
FREE_REG_SET (bb_live_regs);
+
+ if (edge_table)
+ {
+ free (edge_table);
+ edge_table = NULL;
+ }
+
+ if (in_edges)
+ {
+ free (in_edges);
+ in_edges = NULL;
+ }
+ if (out_edges)
+ {
+ free (out_edges);
+ out_edges = NULL;
+ }
}
#endif /* INSN_SCHEDULING */
OpenPOWER on IntegriCloud