This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Toplev.c reorganization


Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> writes:

> Hello,
>
> after discussing it with Honza Hubicka, I have written the following
> attempt to reorganize toplev.c. It has the following goals:
>
> 1) Make it easier to change order of passes, by building/updating
>    automatically the requiered structures and verifying prerequisites.
>    The final state should be that any ordering of passes would either
>    work or say you why it is impossible.
> 2) Decrease the number of unnecessary rebuilds of structures, by keeping
>    track of those that are up-to-date.
> 3) Perhaps also make things better organized.

I like all these goals, and your approach is also quite interesting.
I'd like to see something like this make it into 3.4.

That said, I think this patch tries to do too much all at once, and
the .def files you introduce are a terrible mess.  A more incremental
approach would be a good idea.  To start with, how about we make it so
that the highest-level interface to any given optimizer pass -- the
one called by rest_of_compilation -- always has the signature

 void name_of_pass (tree decl, FILE *dump_file);

and that function is responsible for everything which can be
considered logically part of that pass, but not for the timevar
pushes/pops, the generation of the dump file, calling garbage
collection, or deciding whether or not the optimization is going to be
done.  So, for example,

  if (optimize > 0 && flag_loop_optimize)
    {
      int do_unroll, do_prefetch;

      timevar_push (TV_LOOP);
      delete_dead_jumptables ();
      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
      open_dump_file (DFI_loop, decl);
      /* CFG is no longer maintained up-to-date.  */
      free_bb_for_insn ();

      do_unroll = flag_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
      do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
      if (flag_rerun_loop_opt)
        {
          cleanup_barriers ();

          /* We only want to perform unrolling once.  */
          loop_optimize (insns, rtl_dump_file, do_unroll);
          do_unroll = 0;

          /* The first call to loop_optimize makes some instructions
             trivially dead.  We delete those instructions now in the
             hope that doing so will make the heuristics in loop work
             better and possibly speed up compilation.  */
          delete_trivially_dead_insns (insns, max_reg_num ());

          /* The regscan pass is currently necessary as the alias
                  analysis code depends on this information.  */
          reg_scan (insns, max_reg_num (), 1);
        }
      cleanup_barriers ();
      loop_optimize (insns, rtl_dump_file, do_unroll | LOOP_BCT | do_prefetch);

      /* Loop can create trivially dead instructions.  */
      delete_trivially_dead_insns (insns, max_reg_num ());
      close_dump_file (DFI_loop, print_rtl, insns);
      timevar_pop (TV_LOOP);
      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);

      ggc_collect ();
    }

would become

/* in loop.c */
void
loop_optimize_pass (decl, dump_file)
    tree decl ATTRIBUTE_UNUSED;
    FILE *dump_file;
{
  int do_unroll, do_prefetch;
  rtx insns = get_insns ();

  delete_dead_jumptables ();
  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
  /* CFG is no longer maintained up-to-date.  */
  free_bb_for_insn ();

  do_unroll = flag_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
  do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
  if (flag_rerun_loop_opt)
    {
      cleanup_barriers ();

      /* We only want to perform unrolling once.  */
      loop_optimize (insns, dump_file, do_unroll);
      do_unroll = 0;

      /* The first call to loop_optimize makes some instructions
         trivially dead.  We delete those instructions now in the
         hope that doing so will make the heuristics in loop work
         better and possibly speed up compilation.  */
      delete_trivially_dead_insns (insns, max_reg_num ());

      /* The regscan pass is currently necessary as the alias
              analysis code depends on this information.  */
      reg_scan (insns, max_reg_num (), 1);
    }
  cleanup_barriers ();
  loop_optimize (insns, dump_file, do_unroll | LOOP_BCT | do_prefetch);

  /* Loop can create trivially dead instructions.  */
  delete_trivially_dead_insns (insns, max_reg_num ());
  find_basic_blocks (insns, max_reg_num (), dump_file);
}

/* rest_of_compilation */
  if (optimize > 0 && flag_loop_optimize)
    {
      timevar_push (TV_LOOP);
      open_dump_file (DFI_loop, decl);
      loop_optimize_pass (decl, rtl_dump_file);
      close_dump_file (DFI_loop, print_rtl, get_insns ());
      timevar_pop (TV_LOOP);
      ggc_collect ();
    }

This produces a rest_of_compilation that's a nice simple chain of
tests and calls to optimizer passes, all with the same interface.
That can then be macroized very easily.  And then, with a more rigid
interface enforced between toplev.c and the individual optimizer
passes, we ought to be able to do your structure monitoring stuff
without making quite so much of a mess.

zw


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]