aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/df.c414
2 files changed, 263 insertions, 160 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e6ec65b..2450132 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2001-11-25 Daniel Berlin <dan@cgsoftware.com>
+
+ * df.c: Add prototypes for hybrid_search_bitmap and
+ hybrid_search_sbitmap.
+ (hybrid_search_bitmap): New function.
+ (hybrid_search_sbitmap): New function.
+ (iterative_dataflow_sbitmap): Change to use hybrid_search_sbitmap.
+ (iterative_dataflow_bitmap): Ditto.
+
2001-11-25 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* config/m68hc11/m68hc11.md (peephole2): New peephole2 to optimize
diff --git a/gcc/df.c b/gcc/df.c
index 9bd0ad2..9cb0230 100644
--- a/gcc/df.c
+++ b/gcc/df.c
@@ -301,6 +301,16 @@ static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *));
static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *));
+static void hybrid_search_bitmap PARAMS ((basic_block, bitmap *, bitmap *,
+ bitmap *, bitmap *, enum df_flow_dir,
+ enum df_confluence_op,
+ transfer_function_bitmap,
+ sbitmap, sbitmap, void *));
+static void hybrid_search_sbitmap PARAMS ((basic_block, sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *, enum df_flow_dir,
+ enum df_confluence_op,
+ transfer_function_sbitmap,
+ sbitmap, sbitmap, void *));
static inline bool read_modify_subreg_p PARAMS ((rtx));
@@ -1014,7 +1024,6 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
{
RTX_CODE code;
rtx x;
-
retry:
x = *loc;
if (!x)
@@ -1928,7 +1937,6 @@ df_luids_set (df, blocks)
return total;
}
-
/* Perform dataflow analysis using existing DF structure for blocks
within BLOCKS. If BLOCKS is zero, use all basic blocks in the CFG. */
static void
@@ -3588,82 +3596,32 @@ debug_df_chain (link)
fputc ('\n', stderr);
}
-/* gen = GEN set.
- kill = KILL set.
- in, out = Filled in by function.
- blocks = Blocks to analyze.
- dir = Dataflow direction.
- conf_op = Confluence operation.
- transfun = Transfer function.
- order = Order to iterate in. (Should map block numbers -> order)
- data = Whatever you want. It's passed to the transfer function.
-
- This function will perform iterative bitvector dataflow, producing
- the in and out sets. Even if you only want to perform it for a
- small number of blocks, the vectors for in and out must be large
- enough for *all* blocks, because changing one block might affect
- others. However, it'll only put what you say to analyze on the
- initial worklist.
-
- For forward problems, you probably want to pass in a mapping of
- block number to rc_order (like df->inverse_rc_map).
-*/
-
-void
-iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
- dir, conf_op, transfun, order, data)
- sbitmap *in, *out, *gen, *kill;
- bitmap blocks;
+/* Hybrid search algorithm from "Implementation Techniques for
+ Efficient Data-Flow Analysis of Large Programs". */
+static void
+hybrid_search_bitmap (block, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data)
+ basic_block block;
+ bitmap *in, *out, *gen, *kill;
enum df_flow_dir dir;
enum df_confluence_op conf_op;
- transfer_function_sbitmap transfun;
- int *order;
+ transfer_function_bitmap transfun;
+ sbitmap visited;
+ sbitmap pending;
void *data;
{
int changed;
- int i;
- fibheap_t worklist;
- sbitmap onqueue;
- basic_block bb;
- onqueue = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (onqueue);
- worklist = fibheap_new ();
- EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
- {
- fibheap_insert (worklist, order[i], (void *) i);
- SET_BIT (onqueue, i);
- if (dir == FORWARD)
- {
- sbitmap_copy (out[i], gen[i]);
- }
- else
- {
- sbitmap_copy (in[i], gen[i]);
- }
-
- });
- while (!fibheap_empty (worklist))
+ int i = block->index;
+ edge e;
+ basic_block bb= block;
+ SET_BIT (visited, block->index);
+ if (TEST_BIT (pending, block->index))
{
- edge e;
- i = (int) fibheap_extract_min (worklist);
- changed = 0;
- bb = BASIC_BLOCK (i);
- RESET_BIT (onqueue, i);
if (dir == FORWARD)
{
/* Calculate <conf_op> of predecessor_outs */
- for (e = bb->pred; e != 0; e = e->pred_next)
- {
- if (e->src == ENTRY_BLOCK_PTR)
- {
- sbitmap_zero (in[i]);
- continue;
- }
- sbitmap_copy (in[i], out[e->src->index]);
- break;
- }
- if (e == 0)
- sbitmap_zero (in[i]);
+ bitmap_zero (in[i]);
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
@@ -3671,10 +3629,10 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
switch (conf_op)
{
case UNION:
- sbitmap_a_or_b (in[i], in[i], out[e->src->index]);
+ bitmap_a_or_b (in[i], in[i], out[e->src->index]);
break;
case INTERSECTION:
- sbitmap_a_and_b (in[i], in[i], out[e->src->index]);
+ bitmap_a_and_b (in[i], in[i], out[e->src->index]);
break;
}
}
@@ -3682,7 +3640,7 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
else
{
/* Calculate <conf_op> of successor ins */
- sbitmap_zero (out[i]);
+ bitmap_zero(out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
@@ -3690,104 +3648,91 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
switch (conf_op)
{
case UNION:
- sbitmap_a_or_b (out[i], out[i], in[e->dest->index]);
+ bitmap_a_or_b (out[i], out[i], in[e->dest->index]);
break;
case INTERSECTION:
- sbitmap_a_and_b (out[i], out[i], in[e->dest->index]);
+ bitmap_a_and_b (out[i], out[i], in[e->dest->index]);
break;
}
}
}
/* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
-
+ RESET_BIT (pending, i);
if (changed)
{
if (dir == FORWARD)
{
for (e = bb->succ; e != 0; e = e->succ_next)
{
- if (e->dest == EXIT_BLOCK_PTR)
+ if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
continue;
- if (!TEST_BIT (onqueue, e->dest->index))
- {
- SET_BIT (onqueue, e->dest->index);
- fibheap_insert (worklist,
- order[e->dest->index],
- (void *)e->dest->index);
- }
+ SET_BIT (pending, e->dest->index);
}
}
else
{
for (e = bb->pred; e != 0; e = e->pred_next)
{
- if (e->src == ENTRY_BLOCK_PTR)
+ if (e->src == ENTRY_BLOCK_PTR || e->dest->index == i)
continue;
- if (!TEST_BIT (onqueue, e->src->index))
- {
- SET_BIT (onqueue, e->src->index);
- fibheap_insert (worklist,
- order[e->src->index],
- (void *)e->src->index);
- }
-
+ SET_BIT (pending, e->src->index);
}
}
}
}
- sbitmap_free (onqueue);
- fibheap_delete (worklist);
-
+ if (dir == FORWARD)
+ {
+ for (e = bb->succ; e != 0; e = e->succ_next)
+ {
+ if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
+ continue;
+ if (!TEST_BIT (visited, e->dest->index))
+ hybrid_search_bitmap (e->dest, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ }
+ else
+ {
+ for (e = bb->pred; e != 0; e = e->pred_next)
+ {
+ if (e->src == ENTRY_BLOCK_PTR || e->src->index == i)
+ continue;
+ if (!TEST_BIT (visited, e->src->index))
+ hybrid_search_bitmap (e->src, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ }
}
-/* Exactly the same as iterative_dataflow_sbitmap, except it works on
- bitmaps instead */
-void
-iterative_dataflow_bitmap (in, out, gen, kill, blocks,
- dir, conf_op, transfun, order, data)
- bitmap *in, *out, *gen, *kill;
- bitmap blocks;
+
+
+/* Hybrid search for sbitmaps, rather than bitmaps. */
+static void
+hybrid_search_sbitmap (block, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data)
+ basic_block block;
+ sbitmap *in, *out, *gen, *kill;
enum df_flow_dir dir;
enum df_confluence_op conf_op;
- transfer_function_bitmap transfun;
- int *order;
+ transfer_function_sbitmap transfun;
+ sbitmap visited;
+ sbitmap pending;
void *data;
{
int changed;
- int i;
- fibheap_t worklist;
- sbitmap onqueue;
- basic_block bb;
-
- onqueue = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (onqueue);
- worklist = fibheap_new ();
- EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
- {
- fibheap_insert (worklist, order[i], (void *) i);
- SET_BIT (onqueue, i);
- if (dir == FORWARD)
- {
- bitmap_copy (out[i], gen[i]);
- }
- else
- {
- bitmap_copy (in[i], gen[i]);
- }
-
- });
- while (!fibheap_empty (worklist))
- {
- edge e;
- i = (int) fibheap_extract_min (worklist);
- changed = 0;
- bb = BASIC_BLOCK (i);
- RESET_BIT (onqueue, i);
-
+ int i = block->index;
+ edge e;
+ basic_block bb= block;
+ SET_BIT (visited, block->index);
+ if (TEST_BIT (pending, block->index))
+ {
if (dir == FORWARD)
{
/* Calculate <conf_op> of predecessor_outs */
- bitmap_zero (in[i]);
+ sbitmap_zero (in[i]);
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
@@ -3795,10 +3740,10 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
switch (conf_op)
{
case UNION:
- bitmap_a_or_b (in[i], in[i], out[e->src->index]);
+ sbitmap_a_or_b (in[i], in[i], out[e->src->index]);
break;
case INTERSECTION:
- bitmap_a_and_b (in[i], in[i], out[e->src->index]);
+ sbitmap_a_and_b (in[i], in[i], out[e->src->index]);
break;
}
}
@@ -3806,7 +3751,7 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
else
{
/* Calculate <conf_op> of successor ins */
- bitmap_zero(out[i]);
+ sbitmap_zero(out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
@@ -3814,53 +3759,202 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
switch (conf_op)
{
case UNION:
- bitmap_a_or_b (out[i], out[i], in[e->dest->index]);
+ sbitmap_a_or_b (out[i], out[i], in[e->dest->index]);
break;
case INTERSECTION:
- bitmap_a_and_b (out[i], out[i], in[e->dest->index]);
+ sbitmap_a_and_b (out[i], out[i], in[e->dest->index]);
break;
}
}
}
/* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
-
+ RESET_BIT (pending, i);
if (changed)
{
if (dir == FORWARD)
{
for (e = bb->succ; e != 0; e = e->succ_next)
{
- if (e->dest == EXIT_BLOCK_PTR)
+ if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
continue;
- if (!TEST_BIT (onqueue, e->dest->index))
- {
- SET_BIT (onqueue, e->dest->index);
- fibheap_insert (worklist,
- order[e->dest->index],
- (void *)e->dest->index);
- }
+ SET_BIT (pending, e->dest->index);
}
}
else
{
for (e = bb->pred; e != 0; e = e->pred_next)
{
- if (e->src == ENTRY_BLOCK_PTR)
+ if (e->src == ENTRY_BLOCK_PTR || e->dest->index == i)
continue;
- if (!TEST_BIT (onqueue, e->src->index))
- {
- SET_BIT (onqueue, e->src->index);
- fibheap_insert (worklist,
- order[e->src->index],
- (void *)e->src->index);
- }
-
+ SET_BIT (pending, e->src->index);
}
}
}
}
- sbitmap_free (onqueue);
+ if (dir == FORWARD)
+ {
+ for (e = bb->succ; e != 0; e = e->succ_next)
+ {
+ if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
+ continue;
+ if (!TEST_BIT (visited, e->dest->index))
+ hybrid_search_sbitmap (e->dest, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ }
+ else
+ {
+ for (e = bb->pred; e != 0; e = e->pred_next)
+ {
+ if (e->src == ENTRY_BLOCK_PTR || e->src->index == i)
+ continue;
+ if (!TEST_BIT (visited, e->src->index))
+ hybrid_search_sbitmap (e->src, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ }
+}
+
+
+
+
+/* gen = GEN set.
+ kill = KILL set.
+ in, out = Filled in by function.
+ blocks = Blocks to analyze.
+ dir = Dataflow direction.
+ conf_op = Confluence operation.
+ transfun = Transfer function.
+ order = Order to iterate in. (Should map block numbers -> order)
+ data = Whatever you want. It's passed to the transfer function.
+
+ This function will perform iterative bitvector dataflow, producing
+ the in and out sets. Even if you only want to perform it for a
+ small number of blocks, the vectors for in and out must be large
+ enough for *all* blocks, because changing one block might affect
+ others. However, it'll only put what you say to analyze on the
+ initial worklist.
+
+ For forward problems, you probably want to pass in a mapping of
+ block number to rc_order (like df->inverse_rc_map).
+*/
+void
+iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
+ dir, conf_op, transfun, order, data)
+ sbitmap *in, *out, *gen, *kill;
+ bitmap blocks;
+ enum df_flow_dir dir;
+ enum df_confluence_op conf_op;
+ transfer_function_sbitmap transfun;
+ int *order;
+ void *data;
+{
+ int i;
+ fibheap_t worklist;
+ basic_block bb;
+ sbitmap visited, pending;
+ pending = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (n_basic_blocks);
+ sbitmap_zero (pending);
+ sbitmap_zero (visited);
+ worklist = fibheap_new ();
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
+ {
+ fibheap_insert (worklist, order[i], (void *) i);
+ SET_BIT (pending, i);
+ if (dir == FORWARD)
+ sbitmap_copy (out[i], gen[i]);
+ else
+ sbitmap_copy (in[i], gen[i]);
+ });
+ while (sbitmap_first_set_bit (pending) != -1)
+ {
+ while (!fibheap_empty (worklist))
+ {
+ i = (int) fibheap_extract_min (worklist);
+ bb = BASIC_BLOCK (i);
+ if (!TEST_BIT (visited, bb->index))
+ hybrid_search_sbitmap (bb, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ if (sbitmap_first_set_bit (pending) != -1)
+ {
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
+ {
+ fibheap_insert (worklist, order[i], (void *) i);
+ });
+ sbitmap_zero (visited);
+ }
+ else
+ {
+ break;
+ }
+ }
+ sbitmap_free (pending);
+ sbitmap_free (visited);
fibheap_delete (worklist);
-
+}
+
+/* Exactly the same as iterative_dataflow_sbitmap, except it works on
+ bitmaps instead */
+void
+iterative_dataflow_bitmap (in, out, gen, kill, blocks,
+ dir, conf_op, transfun, order, data)
+ bitmap *in, *out, *gen, *kill;
+ bitmap blocks;
+ enum df_flow_dir dir;
+ enum df_confluence_op conf_op;
+ transfer_function_bitmap transfun;
+ int *order;
+ void *data;
+{
+ int i;
+ fibheap_t worklist;
+ basic_block bb;
+ sbitmap visited, pending;
+ pending = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (n_basic_blocks);
+ sbitmap_zero (pending);
+ sbitmap_zero (visited);
+ worklist = fibheap_new ();
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
+ {
+ fibheap_insert (worklist, order[i], (void *) i);
+ SET_BIT (pending, i);
+ if (dir == FORWARD)
+ bitmap_copy (out[i], gen[i]);
+ else
+ bitmap_copy (in[i], gen[i]);
+ });
+ while (sbitmap_first_set_bit (pending) != -1)
+ {
+ while (!fibheap_empty (worklist))
+ {
+ i = (int) fibheap_extract_min (worklist);
+ bb = BASIC_BLOCK (i);
+ if (!TEST_BIT (visited, bb->index))
+ hybrid_search_bitmap (bb, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
+ data);
+ }
+ if (sbitmap_first_set_bit (pending) != -1)
+ {
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
+ {
+ fibheap_insert (worklist, order[i], (void *) i);
+ });
+ sbitmap_zero (visited);
+ }
+ else
+ {
+ break;
+ }
+ }
+ sbitmap_free (pending);
+ sbitmap_free (visited);
+ fibheap_delete (worklist);
}