On Mon, Sep 14, 2009 at 3:18 AM, Gary Funck <g...@intrepid.com> wrote: > > Recently, we have been working on upgrading GCC/UPC (see > http://gccupc.org) to the GCC trunk. Previously, > we've sync'ed with the latest stable release, but > now we want to stay more current. > > When built with GCC versions 4.0 through 4.3, we used > the gimplify language hook, LANG_HOOKS_GIMPLIFY_EXPR, > to rewrite trees that refer to UPC constructs and UPC > shared variable references - converting them into > non-UPC, gimplified, tree structures. This worked > well, though we did need to extend the language hook > to include a gimplify test predicate and fallback > so that we can rewrite modify_expr's involving UPC > shared variables as the target: > > int > upc_gimplify_expr (tree *expr_p, > gimple_seq *pre_p, gimple_seq *post_p, > bool (* gimple_test_f) (tree), > int fallback) > > Working with the latest GCC 4.5 snapshot, we have run > into a problem that leads me to believe that the current > approach will no longer work with the 4.5/trunk > version of GCC. > > In prior GCC versions, the gimplify pass was called > before the call graph pass. This meant that we could > safely employ the gimplify language hook to perform > the rewrites, which may emit inlined runtime calls. > > An example UPC-related rewrite is to transform > UPC shared variable references into runtime calls. > This program: > > shared int x; > shared int y; > > int main() > { > x = y; > } > > might be translated into something like: > > int main() > { > int y_tmp = upc_get_int(upc_shared_addr(&y)); > upc_put_int(upc_shared_addr(&x), &y_tmp); > } > > The definitions of the runtime functions upc_put_int() > and upc_get_int() are found in a pre-included header > file (the UPC driver adds a -include switch on the > command line). > > Depending upon optimization level and compile time > switches - calls to the UPC runtime functions can > be implemented as either inlined function calls or > conventional calls to pre-compiled library routines. > At optimization levels above -O0, most of the UPC > runtime is inlined, by default. > > With the new/current organization of the > compilation/call graph passes, we end up with the > surprising result that the inlined runtime function > definitions "disappear" before UPC's gimplify pass > can refer to them. That's because the call graph > pass noticed that the inline runtime functions were > declared, but not referenced (yet). The gimplify pass > is then run against the remaining function bodies, > but the UPC runtime functions are no longer available. > > One workaround for this issue might be to mark the > runtime functions, in a fashion similar to ctors/dtors > so that the call graph pass won't eliminate them. > I'm unsure if that will get the inlining aspects of > those routines right, and it might retain unused > function definitions in the form of compiled > non-inlined code. > > GOMP appears to use a "lowering" pass that runs after > the call graph and gimplify passes. It calls runtime > routines via builtin function definitions, ensuring > that the function definitions won't go away. However, > it looks to me as if GOMP does not inline those > runtime functions? > > OBJC implements some post-processing in the > finish_file() hook routine, which in turn calls > objc_finish_file(). That may be a reasonable place > to relocate UPC's tree rewrites, but that leads to > a few questions: > > Can gimplify_expr() be safely called on the same tree > more than once? The question comes up because the > simplest thing is to retain the current infrastructure > where UPC rewrites occur in the gimplify language > hook. The second gimplify pass will redo some > work, calling out to the UPC language hook again, > but since all UPC constructs have been rewritten and > gimplified, there will be no additional work done, > besides the traversal. > > How about an alternative approach that implements a > custom tree-walk inside finish_file() (that is similar > in structure to that implemented in omp-low.c). > Is this rewrite routine allowed to selectively > gimplify parts of the tree and/or to create temp > variables managed by the code in gimplify.c? > > Is the description above, of the interactions > between the cgraph, gimplify and lowering passes > correct? > > What approach would you recommend for the > implementation of UPC tree re-writes that will > support calls to the runtime (that are inlined, > if applicable)?
Without reading all the details of your mail I suggest that you perform a custom walk over the function bodies right before the frontend calls cgraph_finalize_compilation_unit () that performs the necessary lowering (and function creation) to GENERIC. The C++ frontend already does this during its genericize phase to transform frontend specific trees to middle-end GENERIC trees. Richard. > thanks, > > - Gary >