Il 07/10/2012 19:18, Steven Bosscher ha scritto:
> Hello,
> 
> The attached patch adds a DF changeable flag to compute a subset of
> reaching definitions that are also live at the program points they
> reach. This is an idea I discussed with Paolo many years ago already,
> but until today it hadn't really ever been close to the top of my todo
> list, but trying to compile the test case for PR54146 with -fweb
> finally changed that :-)
> 
> The idea is to prune the DF_RD_OUT set of each basic block by
> registers live in DF_LR_OUT. I've implemented this pruning with the
> same approach as the sparse formulation of RD dataflow, expanding the
> regs in DF_LR_OUT to the corresponding set of DEFs and using that set
> to mask out dead DEFs in DF_RD_OUT. This is a convenient formulation
> because DF_LR is already expressed in terms of regnos (like
> sparse_kill & friends), and the formulation also works fine for the
> dense formulation, of course.
> 
> The effect on compile time for a set of cc1-i files is negligible (not
> measurable, anyway), but for crazy large test cases like PR54146 this
> patch is the difference between triggering out-of-memory or completing
> the pass (at least -fweb, probably also the other affected passes).
> 
> Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?

Ok.

I wonder if we actually need the non-pruned version anywhere...

Paolo

> df_rd_pruned.diff
> 
>       * bitmap.h (bitmap_and_into): Update prototype.
>       * bitmap.c (bitmap_and_into): Return true if the target bitmap
>       changed, false otherwise.
> 
>       * df.h (df_dump_insn_problem_function): New function type.
>       (struct df_problem): Add two functions, to dump just before and
>       just after an insn.
>       (DF_RD_PRUNE_DEAD_DEFS): New changable flag.
>       (df_dump_insn_top, df_dump_insn_bottom): New prototypes.
>       * df-core (df_dump_region): Use dump_bb.
>       (df_dump_bb_problem_data): New function.
>       (df_dump_top, df_dump_bottom): Rewrite using df_dump_bb_problem_data.
>       (df_dump_insn_problem_data): New function.
>       (df_dump_insn_top, df_dump_insn_bottom): New functions.
>       * df-scan.c (problem_SCAN): Add NULL fields for new members.
>       * df-problems.c (df_rd_local_compute): Ignore hard registers if
>       DF_NO_HARD_REGS is in effect.
>       (df_rd_transfer_function): If DF_RD_PRUNE_DEAD_DEFS is in effect,
>       prune reaching defs using the LR problem.
>       (df_rd_start_dump): Fix dumping of DEFs map.
>       (df_rd_dump_defs_set): New function.
>       (df_rd_top_dump, df_rd_bottom_dump): Use it.
>       (problem_RD): Add NULL fields for new members.
>       (problem_LR, problem_LIVE): Likewise.
>       (df_chain_bb_dump): New function.
>       (df_chain_top_dump): Dump only for artificial DEFs and USEs,
>       using df_chain_bb_dump.
>       (df_chain_bottom_dump): Likewise.
>       (df_chain_insn_top_dump, df_chain_insn_bottom_dump): New functions.
>       (problem_CHAIN): Add them as new members.
>       (problem_WORD_LR, problem_NOTE): Add NULL fields for new members.
>       (problem_MD): Likewise.
>       * cfgrtl.c (rtl_dump_bb): Use df_dump_insn_top and df_dump_insn_bottom.
>       (print_rtl_with_bb): Likewise.
> 
>       * dce.c (init_dce): Use DF_RD_PRUNE_DEAD_DEFS.
>       * loop-invariant.c (find_defs): Likewise.
>       * loop-iv.c (iv_analysis_loop_init): Likewise.
>       * ree.c (find_and_remove_re): Likewise.
>       * web.c (web_main): Likewise.
> 
> Index: bitmap.h
> ===================================================================
> --- bitmap.h  (revision 192106)
> +++ bitmap.h  (working copy)
> @@ -224,7 +224,7 @@ extern unsigned long bitmap_count_bits (const_bitm
>     are three operand versions that to not destroy the source bitmaps.
>     The operations supported are &, & ~, |, ^.  */
>  extern void bitmap_and (bitmap, const_bitmap, const_bitmap);
> -extern void bitmap_and_into (bitmap, const_bitmap);
> +extern bool bitmap_and_into (bitmap, const_bitmap);
>  extern bool bitmap_and_compl (bitmap, const_bitmap, const_bitmap);
>  extern bool bitmap_and_compl_into (bitmap, const_bitmap);
>  #define bitmap_compl_and(DST, A, B) bitmap_and_compl (DST, B, A)
> Index: bitmap.c
> ===================================================================
> --- bitmap.c  (revision 192106)
> +++ bitmap.c  (working copy)
> @@ -916,17 +916,18 @@ bitmap_and (bitmap dst, const_bitmap a, const_bitm
>      dst->indx = dst->current->indx;
>  }
>  
> -/* A &= B.  */
> +/* A &= B.  Return true if A changed.  */
>  
> -void
> +bool
>  bitmap_and_into (bitmap a, const_bitmap b)
>  {
>    bitmap_element *a_elt = a->first;
>    const bitmap_element *b_elt = b->first;
>    bitmap_element *next;
> +  bool changed = false;
>  
>    if (a == b)
> -    return;
> +    return false;
>  
>    while (a_elt && b_elt)
>      {
> @@ -935,6 +936,7 @@ bitmap_and_into (bitmap a, const_bitmap b)
>         next = a_elt->next;
>         bitmap_element_free (a, a_elt);
>         a_elt = next;
> +       changed = true;
>       }
>        else if (b_elt->indx < a_elt->indx)
>       b_elt = b_elt->next;
> @@ -947,7 +949,8 @@ bitmap_and_into (bitmap a, const_bitmap b)
>         for (ix = 0; ix < BITMAP_ELEMENT_WORDS; ix++)
>           {
>             BITMAP_WORD r = a_elt->bits[ix] & b_elt->bits[ix];
> -
> +           if (a_elt->bits[ix] != r)
> +             changed = true;
>             a_elt->bits[ix] = r;
>             ior |= r;
>           }
> @@ -958,9 +961,17 @@ bitmap_and_into (bitmap a, const_bitmap b)
>         b_elt = b_elt->next;
>       }
>      }
> -  bitmap_elt_clear_from (a, a_elt);
> +
> +  if (a_elt)
> +    {
> +      changed = true;
> +      bitmap_elt_clear_from (a, a_elt);
> +    }
> +
>    gcc_checking_assert (!a->current == !a->first
>                      && (!a->current || a->indx == a->current->indx));
> +
> +  return changed;
>  }
>  
>  
> Index: df.h
> ===================================================================
> --- df.h      (revision 192106)
> +++ df.h      (working copy)
> @@ -239,6 +239,9 @@ typedef void (*df_dump_problem_function) (FILE *);
>  /* Function to dump top or bottom of basic block results to FILE.  */
>  typedef void (*df_dump_bb_problem_function) (basic_block, FILE *);
>  
> +/* Function to dump before or after an insn to FILE.  */
> +typedef void (*df_dump_insn_problem_function) (const_rtx, FILE *);
> +
>  /* Function to dump top or bottom of basic block results to FILE.  */
>  typedef void (*df_verify_solution_start) (void);
>  
> @@ -268,6 +271,8 @@ struct df_problem {
>    df_dump_problem_function dump_start_fun;
>    df_dump_bb_problem_function dump_top_fun;
>    df_dump_bb_problem_function dump_bottom_fun;
> +  df_dump_insn_problem_function dump_insn_top_fun;
> +  df_dump_insn_problem_function dump_insn_bottom_fun;
>    df_verify_solution_start verify_start_fun;
>    df_verify_solution_end verify_end_fun;
>    struct df_problem *dependent_problem;
> @@ -463,7 +468,12 @@ enum df_changeable_flags
>    rescans to be batched.  */
>    DF_DEFER_INSN_RESCAN    = 1 << 5,
>  
> -  DF_VERIFY_SCHEDULED     = 1 << 6
> +  /* Compute the reaching defs problem as "live and reaching defs" (LR&RD).
> +     A DEF is reaching and live at insn I if DEF reaches I and REGNO(DEF)
> +     is in LR_IN of the basic block containing I.  */
> +  DF_RD_PRUNE_DEAD_DEFS   = 1 << 6,
> +
> +  DF_VERIFY_SCHEDULED     = 1 << 7
>  };
>  
>  /* Two of these structures are inline in df, one for the uses and one
> @@ -773,7 +783,9 @@ struct df_scan_bb_info
>  
>  
>  /* Reaching definitions.  All bitmaps are indexed by the id field of
> -   the ref except sparse_kill which is indexed by regno.  */
> +   the ref except sparse_kill which is indexed by regno.  For the
> +   LR&RD problem, the kill set is not complete: It does not contain
> +   DEFs killed because the set register has died in the LR set.  */
>  struct df_rd_bb_info
>  {
>    /* Local sets to describe the basic blocks.   */
> @@ -918,6 +930,8 @@ extern void df_dump_region (FILE *);
>  extern void df_dump_start (FILE *);
>  extern void df_dump_top (basic_block, FILE *);
>  extern void df_dump_bottom (basic_block, FILE *);
> +extern void df_dump_insn_top (const_rtx, FILE *);
> +extern void df_dump_insn_bottom (const_rtx, FILE *);
>  extern void df_refs_chain_dump (df_ref *, bool, FILE *);
>  extern void df_regs_chain_dump (df_ref,  FILE *);
>  extern void df_insn_debug (rtx, bool, FILE *);
> Index: df-core.c
> ===================================================================
> --- df-core.c (revision 192106)
> +++ df-core.c (working copy)
> @@ -1994,10 +1994,7 @@ df_dump_region (FILE *file)
>        EXECUTE_IF_SET_IN_BITMAP (df->blocks_to_analyze, 0, bb_index, bi)
>       {
>         basic_block bb = BASIC_BLOCK (bb_index);
> -
> -       df_print_bb_index (bb, file);
> -       df_dump_top (bb, file);
> -       df_dump_bottom (bb, file);
> +       dump_bb (file, bb, 0, TDF_DETAILS);
>       }
>        fprintf (file, "\n");
>      }
> @@ -2035,10 +2032,9 @@ df_dump_start (FILE *file)
>  }
>  
>  
> -/* Dump the top of the block information for BB.  */
> -
> -void
> -df_dump_top (basic_block bb, FILE *file)
> +/* Dump the top or bottom of the block information for BB.  */
> +static void
> +df_dump_bb_problem_data (basic_block bb, FILE *file, bool top)
>  {
>    int i;
>  
> @@ -2050,19 +2046,40 @@ df_dump_start (FILE *file)
>        struct dataflow *dflow = df->problems_in_order[i];
>        if (dflow->computed)
>       {
> -       df_dump_bb_problem_function bbfun = dflow->problem->dump_top_fun;
> +       df_dump_bb_problem_function bbfun;
> +
> +       if (top)
> +         bbfun = dflow->problem->dump_top_fun;
> +       else
> +         bbfun = dflow->problem->dump_bottom_fun;
> +
>         if (bbfun)
>           bbfun (bb, file);
>       }
>      }
>  }
>  
> +/* Dump the top of the block information for BB.  */
>  
> +void
> +df_dump_top (basic_block bb, FILE *file)
> +{
> +  df_dump_bb_problem_data (bb, file, /*top=*/true);
> +}
> +
>  /* Dump the bottom of the block information for BB.  */
>  
>  void
>  df_dump_bottom (basic_block bb, FILE *file)
>  {
> +  df_dump_bb_problem_data (bb, file, /*top=*/false);
> +}
> +
> +
> +/* Dump information about INSN just before or after dumping INSN itself.  */
> +static void
> +df_dump_insn_problem_data (const_rtx insn, FILE *file, bool top)
> +{
>    int i;
>  
>    if (!df || !file)
> @@ -2073,14 +2090,36 @@ df_dump_bottom (basic_block bb, FILE *file)
>        struct dataflow *dflow = df->problems_in_order[i];
>        if (dflow->computed)
>       {
> -       df_dump_bb_problem_function bbfun = dflow->problem->dump_bottom_fun;
> -       if (bbfun)
> -         bbfun (bb, file);
> +       df_dump_insn_problem_function insnfun;
> +
> +       if (top)
> +         insnfun = dflow->problem->dump_insn_top_fun;
> +       else
> +         insnfun = dflow->problem->dump_insn_bottom_fun;
> +
> +       if (insnfun)
> +         insnfun (insn, file);
>       }
>      }
>  }
>  
> +/* Dump information about INSN before dumping INSN itself.  */
>  
> +void
> +df_dump_insn_top (const_rtx insn, FILE *file)
> +{
> +  df_dump_insn_problem_data (insn,  file, /*top=*/true);
> +}
> +
> +/* Dump information about INSN after dumping INSN itself.  */
> +
> +void
> +df_dump_insn_bottom (const_rtx insn, FILE *file)
> +{
> +  df_dump_insn_problem_data (insn,  file, /*top=*/false);
> +}
> +
> +
>  static void
>  df_ref_dump (df_ref ref, FILE *file)
>  {
> Index: df-scan.c
> ===================================================================
> --- df-scan.c (revision 192106)
> +++ df-scan.c (working copy)
> @@ -510,6 +510,8 @@ static struct df_problem problem_SCAN =
>    df_scan_start_dump,         /* Debugging.  */
>    df_scan_start_block,        /* Debugging start block.  */
>    NULL,                       /* Debugging end block.  */
> +  NULL,                       /* Debugging start insn.  */
> +  NULL,                       /* Debugging end insn.  */
>    NULL,                       /* Incremental solution verify start.  */
>    NULL,                       /* Incremental solution verify end.  */
>    NULL,                       /* Dependent problem.  */
> Index: df-problems.c
> ===================================================================
> --- df-problems.c     (revision 192106)
> +++ df-problems.c     (working copy)
> @@ -152,6 +152,17 @@ df_print_bb_index (basic_block bb, FILE *file)
>     pseudo reaches.  In and out bitvectors are built for each basic
>     block.  The id field in the ref is used to index into these sets.
>     See df.h for details.
> +
> +   If the DF_RD_PRUNE_DEAD_DEFS changable flag is set, only DEFs reaching
> +   existing uses are included in the global reaching DEFs set, or in other
> +   words only DEFs that are still live.  This is a kind of pruned version
> +   of the traditional reaching definitions problem that is much less
> +   complex to compute and produces enough information to compute UD-chains.
> +   In this context, live must be interpreted in the DF_LR sense: Uses that
> +   are upward exposed but maybe not initialized on all paths through the
> +   CFG.  For a USE that is not reached by a DEF on all paths, we still want
> +   to make those DEFs that do reach the USE visible, and pruning based on
> +   DF_LIVE would make that impossible.
>     
> ----------------------------------------------------------------------------*/
>  
>  /* This problem plays a large number of games for the sake of
> @@ -239,8 +250,7 @@ df_rd_alloc (bitmap all_blocks)
>    df_grow_bb_info (df_rd);
>  
>    /* Because of the clustering of all use sites for the same pseudo,
> -     we have to process all of the blocks before doing the
> -     analysis.  */
> +     we have to process all of the blocks before doing the analysis.  */
>  
>    EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
>      {
> @@ -450,12 +460,16 @@ df_rd_local_compute (bitmap all_blocks)
>    /* Set up the knockout bit vectors to be applied across EH_EDGES.  */
>    EXECUTE_IF_SET_IN_BITMAP (regs_invalidated_by_call_regset, 0, regno, bi)
>      {
> -      if (DF_DEFS_COUNT (regno) > DF_SPARSE_THRESHOLD)
> -     bitmap_set_bit (sparse_invalidated, regno);
> -      else
> -     bitmap_set_range (dense_invalidated,
> -                       DF_DEFS_BEGIN (regno),
> -                       DF_DEFS_COUNT (regno));
> +      if (! HARD_REGISTER_NUM_P (regno)
> +       || !(df->changeable_flags & DF_NO_HARD_REGS))
> +     {
> +       if (DF_DEFS_COUNT (regno) > DF_SPARSE_THRESHOLD)
> +         bitmap_set_bit (sparse_invalidated, regno);
> +       else
> +         bitmap_set_range (dense_invalidated,
> +                           DF_DEFS_BEGIN (regno),
> +                           DF_DEFS_COUNT (regno));
> +     }
>      }
>  
>    bitmap_clear (&seen_in_block);
> @@ -534,13 +548,13 @@ df_rd_transfer_function (int bb_index)
>    bitmap gen = &bb_info->gen;
>    bitmap kill = &bb_info->kill;
>    bitmap sparse_kill = &bb_info->sparse_kill;
> +  bool changed = false;
>  
>    if (bitmap_empty_p (sparse_kill))
> -    return  bitmap_ior_and_compl (out, gen, in, kill);
> +    changed = bitmap_ior_and_compl (out, gen, in, kill);
>    else
>      {
>        struct df_rd_problem_data *problem_data;
> -      bool changed = false;
>        bitmap_head tmp;
>  
>        /* Note that TMP is _not_ a temporary bitmap if we end up replacing
> @@ -564,14 +578,34 @@ df_rd_transfer_function (int bb_index)
>         bb_info->out = tmp;
>       }
>        else
> -       bitmap_clear (&tmp);
> -      return changed;
> +     bitmap_clear (&tmp);
>      }
> +
> +  if (df->changeable_flags & DF_RD_PRUNE_DEAD_DEFS)
> +    {
> +      /* Create a mask of DEFs for all registers live at the end of this
> +      basic block, and mask out DEFs of registers that are not live.
> +      Computing the mask looks costly, but the benefit of the pruning
> +      outweighs the cost.  */
> +      struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index);
> +      bitmap regs_live_out = &df_lr_get_bb_info (bb_index)->out;
> +      bitmap live_defs = BITMAP_ALLOC (&df_bitmap_obstack);
> +      unsigned int regno;
> +      bitmap_iterator bi;
> +
> +      EXECUTE_IF_SET_IN_BITMAP (regs_live_out, 0, regno, bi)
> +     bitmap_set_range (live_defs,
> +                       DF_DEFS_BEGIN (regno),
> +                       DF_DEFS_COUNT (regno));
> +      changed |= bitmap_and_into (&bb_info->out, live_defs);
> +      BITMAP_FREE (live_defs);
> +    }
> +
> +  return changed;
>  }
>  
> +/* Free all storage associated with the problem.  */
>  
> -/* Free all storage associated with the problem.  */
> -
>  static void
>  df_rd_free (void)
>  {
> @@ -604,23 +638,66 @@ df_rd_start_dump (FILE *file)
>    if (!df_rd->block_info)
>      return;
>  
> -  fprintf (file, ";; Reaching defs:\n\n");
> +  fprintf (file, ";; Reaching defs:\n");
>  
> -  fprintf (file, "  sparse invalidated \t");
> +  fprintf (file, ";;  sparse invalidated \t");
>    dump_bitmap (file, &problem_data->sparse_invalidated_by_call);
> -  fprintf (file, "  dense invalidated \t");
> +  fprintf (file, ";;  dense invalidated \t");
>    dump_bitmap (file, &problem_data->dense_invalidated_by_call);
>  
> +  fprintf (file, ";;  reg->defs[] map:\t");
>    for (regno = 0; regno < m; regno++)
>      if (DF_DEFS_COUNT (regno))
>        fprintf (file, "%d[%d,%d] ", regno,
>              DF_DEFS_BEGIN (regno),
> -            DF_DEFS_COUNT (regno));
> +            DF_DEFS_BEGIN (regno) + DF_DEFS_COUNT (regno) - 1);
>    fprintf (file, "\n");
> +}
>  
> +
> +static void
> +df_rd_dump_defs_set (bitmap defs_set, const char *prefix, FILE *file)
> +{
> +  bitmap_head tmp;
> +  unsigned int regno;
> +  unsigned int m = DF_REG_SIZE(df);
> +  bool first_reg = true;
> +
> +  fprintf (file, "%s\t(%d) ", prefix, (int) bitmap_count_bits (defs_set));
> +
> +  bitmap_initialize (&tmp, &df_bitmap_obstack);
> +  for (regno = 0; regno < m; regno++)
> +    {
> +      if (HARD_REGISTER_NUM_P (regno)
> +       && (df->changeable_flags & DF_NO_HARD_REGS))
> +     continue;
> +      bitmap_set_range (&tmp, DF_DEFS_BEGIN (regno), DF_DEFS_COUNT (regno));
> +      bitmap_and_into (&tmp, defs_set);
> +      if (! bitmap_empty_p (&tmp))
> +     {
> +       bitmap_iterator bi;
> +       unsigned int ix;
> +       bool first_def = true;
> +
> +       if (! first_reg)
> +         fprintf (file, ",");
> +       first_reg = false;
> +
> +       fprintf (file, "%u[", regno);
> +       EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, ix, bi)
> +         {
> +           fprintf (file, "%s%u", first_def ? "" : ",", ix);
> +           first_def = false;
> +         }
> +       fprintf (file, "]");
> +     }
> +      bitmap_clear (&tmp);
> +    }
> +
> +  fprintf (file, "\n");
> +  bitmap_clear (&tmp);
>  }
>  
> -
>  /* Debugging info at top of bb.  */
>  
>  static void
> @@ -630,16 +707,13 @@ df_rd_top_dump (basic_block bb, FILE *file)
>    if (!bb_info)
>      return;
>  
> -  fprintf (file, ";; rd  in  \t(%d)\n", (int) bitmap_count_bits 
> (&bb_info->in));
> -  dump_bitmap (file, &bb_info->in);
> -  fprintf (file, ";; rd  gen \t(%d)\n", (int) bitmap_count_bits 
> (&bb_info->gen));
> -  dump_bitmap (file, &bb_info->gen);
> -  fprintf (file, ";; rd  kill\t(%d)\n", (int) bitmap_count_bits 
> (&bb_info->kill));
> -  dump_bitmap (file, &bb_info->kill);
> +  df_rd_dump_defs_set (&bb_info->in, ";; rd  in  ", file);
> +  df_rd_dump_defs_set (&bb_info->gen, ";; rd  gen ", file);
> +  df_rd_dump_defs_set (&bb_info->kill, ";; rd  kill", file);
>  }
>  
>  
> -/* Debugging info at top of bb.  */
> +/* Debugging info at bottom of bb.  */
>  
>  static void
>  df_rd_bottom_dump (basic_block bb, FILE *file)
> @@ -648,8 +722,7 @@ df_rd_bottom_dump (basic_block bb, FILE *file)
>    if (!bb_info)
>      return;
>  
> -  fprintf (file, ";; rd  out \t(%d)\n", (int) bitmap_count_bits 
> (&bb_info->out));
> -  dump_bitmap (file, &bb_info->out);
> +  df_rd_dump_defs_set (&bb_info->out, ";; rd  out ", file);
>  }
>  
>  /* All of the information associated with every instance of the problem.  */
> @@ -673,6 +746,8 @@ static struct df_problem problem_RD =
>    df_rd_start_dump,           /* Debugging.  */
>    df_rd_top_dump,             /* Debugging start block.  */
>    df_rd_bottom_dump,          /* Debugging end block.  */
> +  NULL,                       /* Debugging start insn.  */
> +  NULL,                       /* Debugging end insn.  */
>    NULL,                       /* Incremental solution verify start.  */
>    NULL,                       /* Incremental solution verify end.  */
>    NULL,                       /* Dependent problem.  */
> @@ -1209,6 +1284,8 @@ static struct df_problem problem_LR =
>    NULL,                       /* Debugging.  */
>    df_lr_top_dump,             /* Debugging start block.  */
>    df_lr_bottom_dump,          /* Debugging end block.  */
> +  NULL,                       /* Debugging start insn.  */
> +  NULL,                       /* Debugging end insn.  */
>    df_lr_verify_solution_start,/* Incremental solution verify start.  */
>    df_lr_verify_solution_end,  /* Incremental solution verify end.  */
>    NULL,                       /* Dependent problem.  */
> @@ -1738,6 +1815,8 @@ static struct df_problem problem_LIVE =
>    NULL,                         /* Debugging.  */
>    df_live_top_dump,             /* Debugging start block.  */
>    df_live_bottom_dump,          /* Debugging end block.  */
> +  NULL,                         /* Debugging start insn.  */
> +  NULL,                         /* Debugging end insn.  */
>    df_live_verify_solution_start,/* Incremental solution verify start.  */
>    df_live_verify_solution_end,  /* Incremental solution verify end.  */
>    &problem_LR,                  /* Dependent problem.  */
> @@ -2140,112 +2219,142 @@ df_chain_free (void)
>  /* Debugging info.  */
>  
>  static void
> -df_chain_top_dump (basic_block bb, FILE *file)
> +df_chain_bb_dump (basic_block bb, FILE *file, bool top)
>  {
> +  /* Artificials are only hard regs.  */
> +  if (df->changeable_flags & DF_NO_HARD_REGS)
> +    return;
> +  if (df_chain_problem_p (DF_UD_CHAIN))
> +    {
> +      fprintf (file,
> +            ";;  UD chains for artificial uses at %s\n",
> +            top ? "top" : "bottom");
> +      df_ref *use_rec = df_get_artificial_uses (bb->index);
> +      if (*use_rec)
> +     {
> +       while (*use_rec)
> +         {
> +           df_ref use = *use_rec;
> +           if ((top && (DF_REF_FLAGS (use) & DF_REF_AT_TOP))
> +               || (!top && !(DF_REF_FLAGS (use) & DF_REF_AT_TOP)))
> +             {
> +               fprintf (file, ";;   reg %d ", DF_REF_REGNO (use));
> +               df_chain_dump (DF_REF_CHAIN (use), file);
> +               fprintf (file, "\n");
> +             }
> +           use_rec++;
> +         }
> +     }
> +    }
>    if (df_chain_problem_p (DF_DU_CHAIN))
>      {
> -      rtx insn;
> +      fprintf (file,
> +            ";;  DU chains for artificial defs at %s\n",
> +            top ? "top" : "bottom");
>        df_ref *def_rec = df_get_artificial_defs (bb->index);
>        if (*def_rec)
>       {
> -
> -       fprintf (file, ";;  DU chains for artificial defs\n");
>         while (*def_rec)
>           {
>             df_ref def = *def_rec;
> -           fprintf (file, ";;   reg %d ", DF_REF_REGNO (def));
> -           df_chain_dump (DF_REF_CHAIN (def), file);
> -           fprintf (file, "\n");
> -           def_rec++;
> -         }
> -     }
>  
> -      FOR_BB_INSNS (bb, insn)
> -     {
> -       if (INSN_P (insn))
> -         {
> -           struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
> -           def_rec = DF_INSN_INFO_DEFS (insn_info);
> -           if (*def_rec)
> +           if ((top && (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
> +               || (!top && !(DF_REF_FLAGS (def) & DF_REF_AT_TOP)))
>               {
> -               fprintf (file, ";;   DU chains for insn luid %d uid %d\n",
> -                        DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
> -
> -               while (*def_rec)
> -                 {
> -                   df_ref def = *def_rec;
> -                   fprintf (file, ";;      reg %d ", DF_REF_REGNO (def));
> -                   if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
> -                     fprintf (file, "read/write ");
> -                   df_chain_dump (DF_REF_CHAIN (def), file);
> -                   fprintf (file, "\n");
> -                   def_rec++;
> -                 }
> +               fprintf (file, ";;   reg %d ", DF_REF_REGNO (def));
> +               df_chain_dump (DF_REF_CHAIN (def), file);
> +               fprintf (file, "\n");
>               }
> +           def_rec++;
>           }
>       }
>      }
>  }
>  
> +static void
> +df_chain_top_dump (basic_block bb, FILE *file)
> +{
> +  df_chain_bb_dump (bb, file, /*top=*/true);
> +}
>  
>  static void
>  df_chain_bottom_dump (basic_block bb, FILE *file)
>  {
> -  if (df_chain_problem_p (DF_UD_CHAIN))
> +  df_chain_bb_dump (bb, file, /*top=*/false);
> +}
> +
> +static void
> +df_chain_insn_top_dump (const_rtx insn, FILE *file)
> +{
> +  if (df_chain_problem_p (DF_UD_CHAIN) && INSN_P (insn))
>      {
> -      rtx insn;
> -      df_ref *use_rec = df_get_artificial_uses (bb->index);
> -
> -      if (*use_rec)
> +      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
> +      df_ref *use_rec = DF_INSN_INFO_USES (insn_info);
> +      df_ref *eq_use_rec = DF_INSN_INFO_EQ_USES (insn_info);
> +      fprintf (file, ";;   UD chains for insn luid %d uid %d\n",
> +            DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
> +      if (*use_rec || *eq_use_rec)
>       {
> -       fprintf (file, ";;  UD chains for artificial uses\n");
>         while (*use_rec)
>           {
>             df_ref use = *use_rec;
> -           fprintf (file, ";;   reg %d ", DF_REF_REGNO (use));
> -           df_chain_dump (DF_REF_CHAIN (use), file);
> -           fprintf (file, "\n");
> +           if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
> +               || !(df->changeable_flags & DF_NO_HARD_REGS))
> +             {
> +               fprintf (file, ";;      reg %d ", DF_REF_REGNO (use));
> +               if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
> +                 fprintf (file, "read/write ");
> +               df_chain_dump (DF_REF_CHAIN (use), file);
> +               fprintf (file, "\n");
> +             }
>             use_rec++;
>           }
> +       while (*eq_use_rec)
> +         {
> +           df_ref use = *eq_use_rec;
> +           if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
> +               || !(df->changeable_flags & DF_NO_HARD_REGS))
> +             {
> +               fprintf (file, ";;   eq_note reg %d ", DF_REF_REGNO (use));
> +               df_chain_dump (DF_REF_CHAIN (use), file);
> +               fprintf (file, "\n");
> +             }
> +           eq_use_rec++;
> +         }
>       }
> +    }
> +}
>  
> -      FOR_BB_INSNS (bb, insn)
> +static void
> +df_chain_insn_bottom_dump (const_rtx insn, FILE *file)
> +{
> +  if (df_chain_problem_p (DF_DU_CHAIN) && INSN_P (insn))
> +    {
> +      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
> +      df_ref *def_rec = DF_INSN_INFO_DEFS (insn_info);
> +      fprintf (file, ";;   DU chains for insn luid %d uid %d\n",
> +            DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
> +      if (*def_rec)
>       {
> -       if (INSN_P (insn))
> +       while (*def_rec)
>           {
> -           struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
> -           df_ref *eq_use_rec = DF_INSN_INFO_EQ_USES (insn_info);
> -           use_rec = DF_INSN_INFO_USES (insn_info);
> -           if (*use_rec || *eq_use_rec)
> +           df_ref def = *def_rec;
> +           if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (def))
> +               || !(df->changeable_flags & DF_NO_HARD_REGS))
>               {
> -               fprintf (file, ";;   UD chains for insn luid %d uid %d\n",
> -                        DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
> -
> -               while (*use_rec)
> -                 {
> -                   df_ref use = *use_rec;
> -                   fprintf (file, ";;      reg %d ", DF_REF_REGNO (use));
> -                   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
> -                     fprintf (file, "read/write ");
> -                   df_chain_dump (DF_REF_CHAIN (use), file);
> -                   fprintf (file, "\n");
> -                   use_rec++;
> -                 }
> -               while (*eq_use_rec)
> -                 {
> -                   df_ref use = *eq_use_rec;
> -                   fprintf (file, ";;   eq_note reg %d ", DF_REF_REGNO 
> (use));
> -                   df_chain_dump (DF_REF_CHAIN (use), file);
> -                   fprintf (file, "\n");
> -                   eq_use_rec++;
> -                 }
> +               fprintf (file, ";;      reg %d ", DF_REF_REGNO (def));
> +               if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
> +                 fprintf (file, "read/write ");
> +               df_chain_dump (DF_REF_CHAIN (def), file);
> +               fprintf (file, "\n");
>               }
> +           def_rec++;
>           }
>       }
> +      fprintf (file, "\n");
>      }
>  }
>  
> -
>  static struct df_problem problem_CHAIN =
>  {
>    DF_CHAIN,                   /* Problem id.  */
> @@ -2265,6 +2374,8 @@ static struct df_problem problem_CHAIN =
>    NULL,                       /* Debugging.  */
>    df_chain_top_dump,          /* Debugging start block.  */
>    df_chain_bottom_dump,       /* Debugging end block.  */
> +  df_chain_insn_top_dump,     /* Debugging start insn.  */
> +  df_chain_insn_bottom_dump,  /* Debugging end insn.  */
>    NULL,                       /* Incremental solution verify start.  */
>    NULL,                       /* Incremental solution verify end.  */
>    &problem_RD,                /* Dependent problem.  */
> @@ -2643,9 +2754,11 @@ static struct df_problem problem_WORD_LR =
>    NULL,                            /* Debugging.  */
>    df_word_lr_top_dump,             /* Debugging start block.  */
>    df_word_lr_bottom_dump,          /* Debugging end block.  */
> +  NULL,                            /* Debugging start insn.  */
> +  NULL,                            /* Debugging end insn.  */
>    NULL,                            /* Incremental solution verify start.  */
>    NULL,                            /* Incremental solution verify end.  */
> -  NULL,                       /* Dependent problem.  */
> +  NULL,                            /* Dependent problem.  */
>    sizeof (struct df_word_lr_bb_info),/* Size of entry of block_info array.  
> */
>    TV_DF_WORD_LR,                   /* Timing variable.  */
>    false                            /* Reset blocks on dropping out of 
> blocks_to_analyze.  */
> @@ -3330,6 +3443,8 @@ static struct df_problem problem_NOTE =
>    NULL,                       /* Debugging.  */
>    NULL,                       /* Debugging start block.  */
>    NULL,                       /* Debugging end block.  */
> +  NULL,                       /* Debugging start insn.  */
> +  NULL,                       /* Debugging end insn.  */
>    NULL,                       /* Incremental solution verify start.  */
>    NULL,                       /* Incremental solution verify end.  */
>    &problem_LR,                /* Dependent problem.  */
> @@ -4382,6 +4497,8 @@ static struct df_problem problem_MD =
>    NULL,                       /* Debugging.  */
>    df_md_top_dump,             /* Debugging start block.  */
>    df_md_bottom_dump,          /* Debugging end block.  */
> +  NULL,                       /* Debugging start insn.  */
> +  NULL,                       /* Debugging end insn.  */
>    NULL,                            /* Incremental solution verify start.  */
>    NULL,                            /* Incremental solution verify end.  */
>    NULL,                       /* Dependent problem.  */
> Index: cfgrtl.c
> ===================================================================
> --- cfgrtl.c  (revision 192106)
> +++ cfgrtl.c  (working copy)
> @@ -1856,11 +1856,14 @@ rtl_dump_bb (FILE *outf, basic_block bb, int inden
>      for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
>        insn = NEXT_INSN (insn))
>        {
> +     if (flags & TDF_DETAILS)
> +       df_dump_insn_top (insn, outf);
>       if (! (flags & TDF_SLIM))
>         print_rtl_single (outf, insn);
>       else
>         dump_insn_slim (outf, insn);
> -
> +     if (flags & TDF_DETAILS)
> +       df_dump_insn_bottom (insn, outf);
>        }
>  
>    if (df && (flags & TDF_DETAILS))
> @@ -1941,10 +1944,14 @@ print_rtl_with_bb (FILE *outf, const_rtx rtx_first
>               fprintf (outf, ";; Insn is in multiple basic blocks\n");
>           }
>  
> +       if (flags & TDF_DETAILS)
> +         df_dump_insn_top (tmp_rtx, outf);
>         if (! (flags & TDF_SLIM))
>           print_rtl_single (outf, tmp_rtx);
>         else
>           dump_insn_slim (outf, tmp_rtx);
> +       if (flags & TDF_DETAILS)
> +         df_dump_insn_bottom (tmp_rtx, outf);
>  
>         if (flags & TDF_BLOCKS)
>           {
> Index: dce.c
> ===================================================================
> --- dce.c     (revision 192106)
> +++ dce.c     (working copy)
> @@ -704,7 +704,10 @@ init_dce (bool fast)
>    if (!df_in_progress)
>      {
>        if (!fast)
> -     df_chain_add_problem (DF_UD_CHAIN);
> +     {
> +       df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
> +       df_chain_add_problem (DF_UD_CHAIN);
> +     }
>        df_analyze ();
>      }
>  
> Index: loop-invariant.c
> ===================================================================
> --- loop-invariant.c  (revision 192106)
> +++ loop-invariant.c  (working copy)
> @@ -659,20 +659,28 @@
>    for (i = 0; i < loop->num_nodes; i++)
>      bitmap_set_bit (blocks, body[i]->index);
>  
> +  if (dump_file)
> +    {
> +      fprintf (dump_file,
> +            "*****starting processing of loop %d ******\n",
> +            loop->num);
> +    }
> +
>    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)
>      {
>        df_dump_region (dump_file);
> -      fprintf (dump_file, "*****starting processing of loop  ******\n");
> -      print_rtl_with_bb (dump_file, get_insns (), dump_flags);
> -      fprintf (dump_file, "*****ending processing of loop  ******\n");
> +      fprintf (dump_file,
> +            "*****ending processing of loop %d ******\n",
> +            loop->num);
>      }
> -  check_invariant_table_size ();
>  
>    BITMAP_FREE (blocks);
>  }
> Index: loop-iv.c
> ===================================================================
> --- loop-iv.c (revision 192106)
> +++ loop-iv.c (working copy)
> @@ -293,6 +293,7 @@ iv_analysis_loop_init (struct loop *loop)
>       the problem back.  */
>    df_remove_problem (df_chain);
>    df_process_deferred_rescans ();
> +  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
>    df_chain_add_problem (DF_UD_CHAIN);
>    df_note_add_problem ();
>    df_set_blocks (blocks);
> Index: ree.c
> ===================================================================
> --- ree.c     (revision 192106)
> +++ ree.c     (working copy)
> @@ -868,6 +868,7 @@ find_and_remove_re (void)
>  
>    /* Construct DU chain to get all reaching definitions of each
>       extension instruction.  */
> +  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
>    df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
>    df_analyze ();
>    df_set_flags (DF_DEFER_INSN_RESCAN);
> Index: web.c
> ===================================================================
> --- web.c     (revision 192106)
> +++ web.c     (working copy)
> @@ -313,6 +313,7 @@ web_main (void)
>    rtx insn;
>  
>    df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES);
> +  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
>    df_chain_add_problem (DF_UD_CHAIN);
>    df_analyze ();
>    df_set_flags (DF_DEFER_INSN_RESCAN);


Reply via email to