[PATCH] Fix DF sub-CFG analysis slowness (PR39326)
Richard Biener
rguenther@suse.de
Wed Jan 15 14:03:00 GMT 2014
On Wed, 15 Jan 2014, Steven Bosscher wrote:
> On Wed, Jan 15, 2014 at 11:52 AM, Richard Biener wrote:
> > I can split off a df_analyze_1 and have a df_analyze () doing what
> > it does now and a df_analyze_loop () combining df_set_blocks ()
> > and df_analyze () for example.
>
> df_analyze_loop sounds good to me.
Like the following. I've kept the sub-CFG postorder compute
routines in df-core.c as they are quite special and don't
match the get_loop_body_in_XXX_order ones we have in cfgloop.c.
Bootstrap and regtest running on x86_64-unknown-linux-gnu
(succeeded with the hackish patch).
Ok for trunk?
Thanks,
Richard.
2014-01-15 Richard Biener <rguenther@suse.de>
PR rtl-optimization/38518
* df.h (df_analyze_loop): Declare.
* df-core.c: Include cfgloop.h.
(df_analyze_1): Split out main part of df_analyze.
(df_analyze): Adjust.
(loop_inverted_post_order_compute): New function.
(loop_post_order_compute): Likewise.
(df_analyze_loop): New function avoiding whole-function
postorder computes.
* loop-invariant.c (find_defs): Use df_analyze_loop.
(find_invariants): Adjust.
* loop-iv.c (iv_analysis_loop_init): Use df_analyze_loop.
Index: gcc/df.h
===================================================================
*** gcc/df.h.orig 2014-01-15 14:04:21.175544448 +0100
--- gcc/df.h 2014-01-15 14:06:59.851533523 +0100
*************** extern void df_set_blocks (bitmap);
*** 900,906 ****
extern void df_remove_problem (struct dataflow *);
extern void df_finish_pass (bool);
extern void df_analyze_problem (struct dataflow *, bitmap, int *, int);
! extern void df_analyze (void);
extern int df_get_n_blocks (enum df_flow_dir);
extern int *df_get_postorder (enum df_flow_dir);
extern void df_simple_dataflow (enum df_flow_dir, df_init_function,
--- 900,907 ----
extern void df_remove_problem (struct dataflow *);
extern void df_finish_pass (bool);
extern void df_analyze_problem (struct dataflow *, bitmap, int *, int);
! extern void df_analyze ();
! extern void df_analyze_loop (struct loop *);
extern int df_get_n_blocks (enum df_flow_dir);
extern int *df_get_postorder (enum df_flow_dir);
extern void df_simple_dataflow (enum df_flow_dir, df_init_function,
Index: gcc/df-core.c
===================================================================
*** gcc/df-core.c.orig 2014-01-15 14:04:21.188544447 +0100
--- gcc/df-core.c 2014-01-15 14:48:25.089362417 +0100
*************** are write-only operations.
*** 393,398 ****
--- 393,399 ----
#include "df.h"
#include "tree-pass.h"
#include "params.h"
+ #include "cfgloop.h"
static void *df_get_bb_info (struct dataflow *, unsigned int);
static void df_set_bb_info (struct dataflow *, unsigned int, void *);
*************** df_analyze_problem (struct dataflow *dfl
*** 1225,1247 ****
}
! /* Analyze dataflow info for the basic blocks specified by the bitmap
! BLOCKS, or for the whole CFG if BLOCKS is zero. */
! void
! df_analyze (void)
{
- bitmap current_all_blocks = BITMAP_ALLOC (&df_bitmap_obstack);
- bool everything;
int i;
- free (df->postorder);
- free (df->postorder_inverted);
- df->postorder = XNEWVEC (int, last_basic_block_for_fn (cfun));
- df->postorder_inverted = XNEWVEC (int, last_basic_block_for_fn (cfun));
- df->n_blocks = post_order_compute (df->postorder, true, true);
- df->n_blocks_inverted = inverted_post_order_compute (df->postorder_inverted);
-
/* These should be the same. */
gcc_assert (df->n_blocks == df->n_blocks_inverted);
--- 1226,1238 ----
}
! /* Analyze dataflow info. */
! static void
! df_analyze_1 (void)
{
int i;
/* These should be the same. */
gcc_assert (df->n_blocks == df->n_blocks_inverted);
*************** df_analyze (void)
*** 1258,1263 ****
--- 1249,1299 ----
#endif
df_verify ();
+ /* Skip over the DF_SCAN problem. */
+ for (i = 1; i < df->num_problems_defined; i++)
+ {
+ struct dataflow *dflow = df->problems_in_order[i];
+ if (dflow->solutions_dirty)
+ {
+ if (dflow->problem->dir == DF_FORWARD)
+ df_analyze_problem (dflow,
+ df->blocks_to_analyze,
+ df->postorder_inverted,
+ df->n_blocks_inverted);
+ else
+ df_analyze_problem (dflow,
+ df->blocks_to_analyze,
+ df->postorder,
+ df->n_blocks);
+ }
+ }
+
+ if (!df->analyze_subset)
+ {
+ BITMAP_FREE (df->blocks_to_analyze);
+ df->blocks_to_analyze = NULL;
+ }
+
+ #ifdef DF_DEBUG_CFG
+ df_set_clean_cfg ();
+ #endif
+ }
+
+ /* Analyze dataflow info. */
+
+ void
+ df_analyze (void)
+ {
+ bitmap current_all_blocks = BITMAP_ALLOC (&df_bitmap_obstack);
+ int i;
+
+ free (df->postorder);
+ free (df->postorder_inverted);
+ df->postorder = XNEWVEC (int, last_basic_block_for_fn (cfun));
+ df->postorder_inverted = XNEWVEC (int, last_basic_block_for_fn (cfun));
+ df->n_blocks = post_order_compute (df->postorder, true, true);
+ df->n_blocks_inverted = inverted_post_order_compute (df->postorder_inverted);
+
for (i = 0; i < df->n_blocks; i++)
bitmap_set_bit (current_all_blocks, df->postorder[i]);
*************** df_analyze (void)
*** 1272,1321 ****
sets. */
if (df->analyze_subset)
{
- everything = false;
bitmap_and_into (df->blocks_to_analyze, current_all_blocks);
df->n_blocks = df_prune_to_subcfg (df->postorder,
df->n_blocks, df->blocks_to_analyze);
df->n_blocks_inverted = df_prune_to_subcfg (df->postorder_inverted,
! df->n_blocks_inverted,
! df->blocks_to_analyze);
BITMAP_FREE (current_all_blocks);
}
else
{
- everything = true;
df->blocks_to_analyze = current_all_blocks;
current_all_blocks = NULL;
}
! /* Skip over the DF_SCAN problem. */
! for (i = 1; i < df->num_problems_defined; i++)
{
! struct dataflow *dflow = df->problems_in_order[i];
! if (dflow->solutions_dirty)
! {
! if (dflow->problem->dir == DF_FORWARD)
! df_analyze_problem (dflow,
! df->blocks_to_analyze,
! df->postorder_inverted,
! df->n_blocks_inverted);
! else
! df_analyze_problem (dflow,
! df->blocks_to_analyze,
! df->postorder,
! df->n_blocks);
! }
}
! if (everything)
{
! BITMAP_FREE (df->blocks_to_analyze);
! df->blocks_to_analyze = NULL;
}
! #ifdef DF_DEBUG_CFG
! df_set_clean_cfg ();
! #endif
}
--- 1308,1484 ----
sets. */
if (df->analyze_subset)
{
bitmap_and_into (df->blocks_to_analyze, current_all_blocks);
df->n_blocks = df_prune_to_subcfg (df->postorder,
df->n_blocks, df->blocks_to_analyze);
df->n_blocks_inverted = df_prune_to_subcfg (df->postorder_inverted,
! df->n_blocks_inverted,
! df->blocks_to_analyze);
BITMAP_FREE (current_all_blocks);
}
else
{
df->blocks_to_analyze = current_all_blocks;
current_all_blocks = NULL;
}
! df_analyze_1 ();
! }
!
! /* Compute the reverse top sort order of the sub-CFG specified by LOOP.
! Returns the number of blocks which is always loop->num_nodes. */
!
! static int
! loop_post_order_compute (int *post_order, struct loop *loop)
! {
! edge_iterator *stack;
! int sp;
! int post_order_num = 0;
! bitmap visited;
!
! /* Allocate stack for back-tracking up CFG. */
! stack = XNEWVEC (edge_iterator, loop->num_nodes + 1);
! sp = 0;
!
! /* Allocate bitmap to track nodes that have been visited. */
! visited = BITMAP_ALLOC (NULL);
!
! /* Push the first edge on to the stack. */
! stack[sp++] = ei_start (loop_preheader_edge (loop)->src->succs);
!
! while (sp)
{
! edge_iterator ei;
! basic_block src;
! basic_block dest;
!
! /* Look at the edge on the top of the stack. */
! ei = stack[sp - 1];
! src = ei_edge (ei)->src;
! dest = ei_edge (ei)->dest;
!
! /* Check if the edge destination has been visited yet and mark it
! if not so. */
! if (flow_bb_inside_loop_p (loop, dest)
! && bitmap_set_bit (visited, dest->index))
! {
! if (EDGE_COUNT (dest->succs) > 0)
! /* Since the DEST node has been visited for the first
! time, check its successors. */
! stack[sp++] = ei_start (dest->succs);
! else
! post_order[post_order_num++] = dest->index;
! }
! else
! {
! if (ei_one_before_end_p (ei)
! && src != loop_preheader_edge (loop)->src)
! post_order[post_order_num++] = src->index;
!
! if (!ei_one_before_end_p (ei))
! ei_next (&stack[sp - 1]);
! else
! sp--;
! }
}
! free (stack);
! BITMAP_FREE (visited);
!
! return post_order_num;
! }
!
! /* Compute the reverse top sort order of the inverted sub-CFG specified
! by LOOP. Returns the number of blocks which is always loop->num_nodes. */
!
! static int
! loop_inverted_post_order_compute (int *post_order, struct loop *loop)
! {
! basic_block bb;
! edge_iterator *stack;
! int sp;
! int post_order_num = 0;
! bitmap visited;
!
! /* Allocate stack for back-tracking up CFG. */
! stack = XNEWVEC (edge_iterator, loop->num_nodes + 1);
! sp = 0;
!
! /* Allocate bitmap to track nodes that have been visited. */
! visited = BITMAP_ALLOC (NULL);
!
! /* Put all latches into the initial work list. In theory we'd want
! to start from loop exits but then we'd have the special case of
! endless loops. It doesn't really matter for DF iteration order and
! handling latches last is probably even better. */
! stack[sp++] = ei_start (loop->header->preds);
! bitmap_set_bit (visited, loop->header->index);
!
! /* The inverted traversal loop. */
! while (sp)
{
! edge_iterator ei;
! basic_block pred;
!
! /* Look at the edge on the top of the stack. */
! ei = stack[sp - 1];
! bb = ei_edge (ei)->dest;
! pred = ei_edge (ei)->src;
!
! /* Check if the predecessor has been visited yet and mark it
! if not so. */
! if (flow_bb_inside_loop_p (loop, pred)
! && bitmap_set_bit (visited, pred->index))
! {
! if (EDGE_COUNT (pred->preds) > 0)
! /* Since the predecessor node has been visited for the first
! time, check its predecessors. */
! stack[sp++] = ei_start (pred->preds);
! else
! post_order[post_order_num++] = pred->index;
! }
! else
! {
! if (flow_bb_inside_loop_p (loop, bb)
! && ei_one_before_end_p (ei))
! post_order[post_order_num++] = bb->index;
!
! if (!ei_one_before_end_p (ei))
! ei_next (&stack[sp - 1]);
! else
! sp--;
! }
}
! free (stack);
! BITMAP_FREE (visited);
! return post_order_num;
! }
!
!
! /* Analyze dataflow info for the basic blocks contained in LOOP. */
!
! void
! df_analyze_loop (struct loop *loop)
! {
! free (df->postorder);
! free (df->postorder_inverted);
!
! df->postorder = XNEWVEC (int, loop->num_nodes);
! df->postorder_inverted = XNEWVEC (int, loop->num_nodes);
! df->n_blocks = loop_post_order_compute (df->postorder, loop);
! df->n_blocks_inverted
! = loop_inverted_post_order_compute (df->postorder_inverted, loop);
! gcc_assert ((unsigned) df->n_blocks == loop->num_nodes);
! gcc_assert ((unsigned) df->n_blocks_inverted == loop->num_nodes);
!
! bitmap blocks = BITMAP_ALLOC (&df_bitmap_obstack);
! for (int i = 0; i < df->n_blocks; ++i)
! bitmap_set_bit (blocks, df->postorder[i]);
! df_set_blocks (blocks);
! BITMAP_FREE (blocks);
!
! df_analyze_1 ();
}
Index: gcc/loop-invariant.c
===================================================================
*** gcc/loop-invariant.c.orig 2014-01-15 14:04:21.200544446 +0100
--- gcc/loop-invariant.c 2014-01-15 14:54:15.047338323 +0100
*************** may_assign_reg_p (rtx x)
*** 652,665 ****
BODY. */
static void
! find_defs (struct loop *loop, basic_block *body)
{
- unsigned i;
- bitmap blocks = BITMAP_ALLOC (NULL);
-
- for (i = 0; i < loop->num_nodes; i++)
- bitmap_set_bit (blocks, body[i]->index);
-
if (dump_file)
{
fprintf (dump_file,
--- 652,659 ----
BODY. */
static void
! find_defs (struct loop *loop)
{
if (dump_file)
{
fprintf (dump_file,
*************** find_defs (struct loop *loop, basic_bloc
*** 670,678 ****
df_remove_problem (df_chain);
df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN);
- df_set_blocks (blocks);
df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
! df_analyze ();
check_invariant_table_size ();
if (dump_file)
--- 664,671 ----
df_remove_problem (df_chain);
df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN);
df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
! df_analyze_loop (loop);
check_invariant_table_size ();
if (dump_file)
*************** find_defs (struct loop *loop, basic_bloc
*** 682,689 ****
"*****ending processing of loop %d ******\n",
loop->num);
}
-
- BITMAP_FREE (blocks);
}
/* Creates a new invariant for definition DEF in INSN, depending on invariants
--- 675,680 ----
*************** find_invariants (struct loop *loop)
*** 1005,1011 ****
compute_always_reached (loop, body, may_exit, always_reached);
compute_always_reached (loop, body, has_exit, always_executed);
! find_defs (loop, body);
find_invariants_body (loop, body, always_reached, always_executed);
merge_identical_invariants ();
--- 996,1002 ----
compute_always_reached (loop, body, may_exit, always_reached);
compute_always_reached (loop, body, has_exit, always_executed);
! find_defs (loop);
find_invariants_body (loop, body, always_reached, always_executed);
merge_identical_invariants ();
Index: gcc/loop-iv.c
===================================================================
*** gcc/loop-iv.c.orig 2014-01-15 14:04:21.200544446 +0100
--- gcc/loop-iv.c 2014-01-15 14:08:27.429527493 +0100
*************** clear_iv_info (void)
*** 278,287 ****
void
iv_analysis_loop_init (struct loop *loop)
{
- basic_block *body = get_loop_body_in_dom_order (loop), bb;
- bitmap blocks = BITMAP_ALLOC (NULL);
- unsigned i;
-
current_loop = loop;
/* Clear the information from the analysis of the previous loop. */
--- 278,283 ----
*************** iv_analysis_loop_init (struct loop *loop
*** 294,304 ****
else
clear_iv_info ();
- for (i = 0; i < loop->num_nodes; i++)
- {
- bb = body[i];
- bitmap_set_bit (blocks, bb->index);
- }
/* Get rid of the ud chains before processing the rescans. Then add
the problem back. */
df_remove_problem (df_chain);
--- 290,295 ----
*************** iv_analysis_loop_init (struct loop *loop
*** 306,319 ****
df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
df_chain_add_problem (DF_UD_CHAIN);
df_note_add_problem ();
! df_set_blocks (blocks);
! df_analyze ();
if (dump_file)
df_dump_region (dump_file);
check_iv_ref_table_size ();
- BITMAP_FREE (blocks);
- free (body);
}
/* Finds the definition of REG that dominates loop latch and stores
--- 297,307 ----
df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
df_chain_add_problem (DF_UD_CHAIN);
df_note_add_problem ();
! df_analyze_loop (loop);
if (dump_file)
df_dump_region (dump_file);
check_iv_ref_table_size ();
}
/* Finds the definition of REG that dominates loop latch and stores
More information about the Gcc-patches
mailing list