On Tue, Dec 10, 2013 at 11:59:16PM -0700, Jeff Law wrote:
> On 12/10/13 23:35, Bin.Cheng wrote:
> >I know little about GC, so when ggc_collect may be called (between two
> >passes)? If so, I have to call free_affine_expand_cache just after the
> >calling to tree_to_affine_combination_expand in SCEV because it's an
> >analyzer and as you pointed out, the analyzing result is used by
> >different optimizers.  The pointer map would be maintained between
> >different passes if it's not instantly freed.
> The garbage collector only runs between passes.  If you have roots
> in static storage, then  you'll need to decorate them so the garbage
> collector scans them.
> 
> There's a fairly extensive discussion of the garbage collector in
> the GCC internals manual.

It isn't that easy, pointer_map isn't a data structure recognized by the
garbage collector at all (plus, as I've said before, the code is inserting
XNEW allocated structures into the pointer_map, which isn't GC friendly
either, but making them GC allocated might increase garbage unnecessarily,
as all the structs are short lived).

I've looked through scev_{initialize,finalize} callers, and almost all
passes initialize it and finalize within the same pass, it is only the loop
optimizations:
          NEXT_PASS (pass_tree_loop_init);
          NEXT_PASS (pass_lim);
          NEXT_PASS (pass_copy_prop);
          NEXT_PASS (pass_dce_loop);
          NEXT_PASS (pass_tree_unswitch);
          NEXT_PASS (pass_scev_cprop);
          NEXT_PASS (pass_record_bounds);
          NEXT_PASS (pass_check_data_deps);
          NEXT_PASS (pass_loop_distribution);
          NEXT_PASS (pass_copy_prop);
          NEXT_PASS (pass_graphite);
          PUSH_INSERT_PASSES_WITHIN (pass_graphite)
              NEXT_PASS (pass_graphite_transforms);
              NEXT_PASS (pass_lim);
              NEXT_PASS (pass_copy_prop);
              NEXT_PASS (pass_dce_loop);
          POP_INSERT_PASSES ()
          NEXT_PASS (pass_iv_canon);
          NEXT_PASS (pass_parallelize_loops);
          NEXT_PASS (pass_if_conversion);
          /* pass_vectorize must immediately follow pass_if_conversion.
             Please do not add any other passes in between.  */
          NEXT_PASS (pass_vectorize);
          PUSH_INSERT_PASSES_WITHIN (pass_vectorize)
              NEXT_PASS (pass_dce_loop);
          POP_INSERT_PASSES ()
          NEXT_PASS (pass_predcom);
          NEXT_PASS (pass_complete_unroll);
          NEXT_PASS (pass_slp_vectorize);
          NEXT_PASS (pass_loop_prefetch);
          NEXT_PASS (pass_iv_optimize);
          NEXT_PASS (pass_lim);
          NEXT_PASS (pass_tree_loop_done);
where scev is live in between the passes, and unfortunately there
is no call that each pass calls that you could easily add the free_affine.*
call to (except for execute_function_todo but you'd need to invent another
TODO_* flag for it and the question is how you'd ensure it will be handled
for the non-loop specific passes that are just run in between these
passes (say pass_copy_prop, would we need pass_copy_prop_loop?).

Perhaps you could replace in tree-affine.c and all it's users
{,struct} pointer_map_t * with
struct GTY((user)) affine_expand_cache {
  pointer_map_t *cache;
};
and write custom gt_ggc_mx (affine_expand_cache *) function that would
would either pointer_map_traverse the cache and for each cache entry
call gt_ggc_mx on the embedded trees in the structures, or drop the cache
(dunno if the cache is really just a cache and it doesn't matter if it is
dropped any time, or if it can affect code generation).  There are also PCH
related functions that need to be defined, though I guess you could just
assert there that the cache is NULL and not walk anything.

        Jakub

Reply via email to