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
This commit is contained in:
Daniel Berlin 2001-11-25 17:22:55 +00:00 committed by Daniel Berlin
parent cb33a143b9
commit a6253d46c5
2 changed files with 314 additions and 211 deletions

View File

@ -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

516
gcc/df.c
View File

@ -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,202 +3596,28 @@ 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;
enum df_flow_dir dir;
enum df_confluence_op conf_op;
transfer_function_sbitmap transfun;
int *order;
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))
{
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]);
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
continue;
switch (conf_op)
{
case UNION:
sbitmap_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]);
break;
}
}
}
else
{
/* Calculate <conf_op> of successor ins */
sbitmap_zero (out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
switch (conf_op)
{
case UNION:
sbitmap_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]);
break;
}
}
}
/* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
if (changed)
{
if (dir == FORWARD)
{
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
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);
}
}
}
else
{
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
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);
}
}
}
}
}
sbitmap_free (onqueue);
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)
/* 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;
bitmap blocks;
enum df_flow_dir dir;
enum df_confluence_op conf_op;
transfer_function_bitmap transfun;
int *order;
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))
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 */
@ -3824,43 +3658,303 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
}
/* 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);
}
}
}
/* 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_sbitmap transfun;
sbitmap visited;
sbitmap pending;
void *data;
{
int changed;
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 */
sbitmap_zero (in[i]);
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
continue;
switch (conf_op)
{
case UNION:
sbitmap_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]);
break;
}
}
}
else
{
/* Calculate <conf_op> of successor ins */
sbitmap_zero(out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
switch (conf_op)
{
case UNION:
sbitmap_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]);
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 || e->dest->index == i)
continue;
SET_BIT (pending, e->dest->index);
}
}
else
{
for (e = bb->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR || e->dest->index == i)
continue;
SET_BIT (pending, e->src->index);
}
}
}
}
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);
}