Commit a6253d46 by Daniel Berlin Committed by Daniel Berlin

df.c: Add prototypes for hybrid_search_bitmap and hybrid_search_sbitmap.

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.

From-SVN: r47326
parent cb33a143
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> 2001-11-25 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* config/m68hc11/m68hc11.md (peephole2): New peephole2 to optimize * config/m68hc11/m68hc11.md (peephole2): New peephole2 to optimize
......
...@@ -301,6 +301,16 @@ static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap, ...@@ -301,6 +301,16 @@ static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *)); bitmap, bitmap, void *));
static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap, static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *)); 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)); static inline bool read_modify_subreg_p PARAMS ((rtx));
...@@ -1014,7 +1024,6 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) ...@@ -1014,7 +1024,6 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
{ {
RTX_CODE code; RTX_CODE code;
rtx x; rtx x;
retry: retry:
x = *loc; x = *loc;
if (!x) if (!x)
...@@ -1928,7 +1937,6 @@ df_luids_set (df, blocks) ...@@ -1928,7 +1937,6 @@ df_luids_set (df, blocks)
return total; return total;
} }
/* Perform dataflow analysis using existing DF structure for blocks /* Perform dataflow analysis using existing DF structure for blocks
within BLOCKS. If BLOCKS is zero, use all basic blocks in the CFG. */ within BLOCKS. If BLOCKS is zero, use all basic blocks in the CFG. */
static void static void
...@@ -3588,82 +3596,32 @@ debug_df_chain (link) ...@@ -3588,82 +3596,32 @@ debug_df_chain (link)
fputc ('\n', stderr); fputc ('\n', stderr);
} }
/* gen = GEN set. /* Hybrid search algorithm from "Implementation Techniques for
kill = KILL set. Efficient Data-Flow Analysis of Large Programs". */
in, out = Filled in by function. static void
blocks = Blocks to analyze. hybrid_search_bitmap (block, in, out, gen, kill, dir,
dir = Dataflow direction. conf_op, transfun, visited, pending,
conf_op = Confluence operation. data)
transfun = Transfer function. basic_block block;
order = Order to iterate in. (Should map block numbers -> order) bitmap *in, *out, *gen, *kill;
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_flow_dir dir;
enum df_confluence_op conf_op; enum df_confluence_op conf_op;
transfer_function_sbitmap transfun; transfer_function_bitmap transfun;
int *order; sbitmap visited;
sbitmap pending;
void *data; void *data;
{ {
int changed; int changed;
int i; int i = block->index;
fibheap_t worklist; edge e;
sbitmap onqueue; basic_block bb= block;
basic_block bb; SET_BIT (visited, block->index);
onqueue = sbitmap_alloc (n_basic_blocks); if (TEST_BIT (pending, block->index))
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))
{ {
edge e;
i = (int) fibheap_extract_min (worklist);
changed = 0;
bb = BASIC_BLOCK (i);
RESET_BIT (onqueue, i);
if (dir == FORWARD) if (dir == FORWARD)
{ {
/* Calculate <conf_op> of predecessor_outs */ /* Calculate <conf_op> of predecessor_outs */
for (e = bb->pred; e != 0; e = e->pred_next) bitmap_zero (in[i]);
{
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]);
for (e = bb->pred; e != 0; e = e->pred_next) for (e = bb->pred; e != 0; e = e->pred_next)
{ {
if (e->src == ENTRY_BLOCK_PTR) if (e->src == ENTRY_BLOCK_PTR)
...@@ -3671,10 +3629,10 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks, ...@@ -3671,10 +3629,10 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
switch (conf_op) switch (conf_op)
{ {
case UNION: 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; break;
case INTERSECTION: 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; break;
} }
} }
...@@ -3682,7 +3640,7 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks, ...@@ -3682,7 +3640,7 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
else else
{ {
/* Calculate <conf_op> of successor ins */ /* Calculate <conf_op> of successor ins */
sbitmap_zero (out[i]); bitmap_zero(out[i]);
for (e = bb->succ; e != 0; e = e->succ_next) for (e = bb->succ; e != 0; e = e->succ_next)
{ {
if (e->dest == EXIT_BLOCK_PTR) if (e->dest == EXIT_BLOCK_PTR)
...@@ -3690,104 +3648,91 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks, ...@@ -3690,104 +3648,91 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
switch (conf_op) switch (conf_op)
{ {
case UNION: 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; break;
case INTERSECTION: 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; break;
} }
} }
} }
/* Common part */ /* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data); (*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
RESET_BIT (pending, i);
if (changed) if (changed)
{ {
if (dir == FORWARD) if (dir == FORWARD)
{ {
for (e = bb->succ; e != 0; e = e->succ_next) 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; continue;
if (!TEST_BIT (onqueue, e->dest->index)) SET_BIT (pending, e->dest->index);
{
SET_BIT (onqueue, e->dest->index);
fibheap_insert (worklist,
order[e->dest->index],
(void *)e->dest->index);
}
} }
} }
else else
{ {
for (e = bb->pred; e != 0; e = e->pred_next) 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; continue;
if (!TEST_BIT (onqueue, e->src->index)) SET_BIT (pending, e->src->index);
{
SET_BIT (onqueue, e->src->index);
fibheap_insert (worklist,
order[e->src->index],
(void *)e->src->index);
}
} }
} }
} }
} }
sbitmap_free (onqueue); if (dir == FORWARD)
fibheap_delete (worklist); {
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 /* Hybrid search for sbitmaps, rather than bitmaps. */
iterative_dataflow_bitmap (in, out, gen, kill, blocks, static void
dir, conf_op, transfun, order, data) hybrid_search_sbitmap (block, in, out, gen, kill, dir,
bitmap *in, *out, *gen, *kill; conf_op, transfun, visited, pending,
bitmap blocks; data)
basic_block block;
sbitmap *in, *out, *gen, *kill;
enum df_flow_dir dir; enum df_flow_dir dir;
enum df_confluence_op conf_op; enum df_confluence_op conf_op;
transfer_function_bitmap transfun; transfer_function_sbitmap transfun;
int *order; sbitmap visited;
sbitmap pending;
void *data; void *data;
{ {
int changed; int changed;
int i; int i = block->index;
fibheap_t worklist; edge e;
sbitmap onqueue; basic_block bb= block;
basic_block bb; SET_BIT (visited, block->index);
if (TEST_BIT (pending, block->index))
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);
if (dir == FORWARD) if (dir == FORWARD)
{ {
/* Calculate <conf_op> of predecessor_outs */ /* Calculate <conf_op> of predecessor_outs */
bitmap_zero (in[i]); sbitmap_zero (in[i]);
for (e = bb->pred; e != 0; e = e->pred_next) for (e = bb->pred; e != 0; e = e->pred_next)
{ {
if (e->src == ENTRY_BLOCK_PTR) if (e->src == ENTRY_BLOCK_PTR)
...@@ -3795,10 +3740,10 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks, ...@@ -3795,10 +3740,10 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
switch (conf_op) switch (conf_op)
{ {
case UNION: 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; break;
case INTERSECTION: 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; break;
} }
} }
...@@ -3806,7 +3751,7 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks, ...@@ -3806,7 +3751,7 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
else else
{ {
/* Calculate <conf_op> of successor ins */ /* Calculate <conf_op> of successor ins */
bitmap_zero(out[i]); sbitmap_zero(out[i]);
for (e = bb->succ; e != 0; e = e->succ_next) for (e = bb->succ; e != 0; e = e->succ_next)
{ {
if (e->dest == EXIT_BLOCK_PTR) if (e->dest == EXIT_BLOCK_PTR)
...@@ -3814,53 +3759,202 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks, ...@@ -3814,53 +3759,202 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
switch (conf_op) switch (conf_op)
{ {
case UNION: 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; break;
case INTERSECTION: 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; break;
} }
} }
} }
/* Common part */ /* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data); (*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
RESET_BIT (pending, i);
if (changed) if (changed)
{ {
if (dir == FORWARD) if (dir == FORWARD)
{ {
for (e = bb->succ; e != 0; e = e->succ_next) 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; continue;
if (!TEST_BIT (onqueue, e->dest->index)) SET_BIT (pending, e->dest->index);
{
SET_BIT (onqueue, e->dest->index);
fibheap_insert (worklist,
order[e->dest->index],
(void *)e->dest->index);
}
} }
} }
else else
{ {
for (e = bb->pred; e != 0; e = e->pred_next) 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; continue;
if (!TEST_BIT (onqueue, e->src->index)) SET_BIT (pending, e->src->index);
{
SET_BIT (onqueue, e->src->index);
fibheap_insert (worklist,
order[e->src->index],
(void *)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); 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);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment