On Wed, Oct 28, 2020 at 02:20:29PM +0000, Kwok Cheung Yeung wrote:
> OpenMP 5.0 has a new feature for implicitly marking variables and functions
> that are referenced in the initializers of static variables and functions
> that are already marked 'declare target'. Support was added in the commit
> 'openmp: Implement discovery of implicit declare target to clauses'
> (dc703151d4f4560e647649506d5b4ceb0ee11e90). However, this does not work with
> non-constant C++ initializers, where the initializers can contain references
> to other (non-constant) variables and function calls.
> 
> The C++ front-end stores the initialization information in the
> static_aggregates list (with the variable decl in the TREE_VALUE of an entry
> and the initialization in TREE_PURPOSE) rather than in
> TREE_INITIAL(var_decl). I have added an extra function in omp-offload.cpp to
> walk the variable initialiser trees in static_aggregates, and added a call
> to it from the FE shortly before the initializations are emitted. I have
> also added a testcase to ensure that the implicitly marked
> variables/functions can be referenced in offloaded code.
I'm actually not sure how this can work correctly.
Let's say we have 
int foo () { return 1; }
int bar () { return 2; }
int baz () { return 3; }
int qux () { return 4; }
int a = foo ();
int b = bar ();
int c = baz ();
int *d = &c;
int e = qux ();
int f = e + 1;
int *g = &f;
#pragma omp declare target to (b, d, g)
So, for the implicit declare target discovery, a is not declare target to,
nor is foo, and everything else is; b, d, g explicitly, c because it is
referenced in initializer of b, f because it is mentioned in initializer of
g and e because it is mentioned in initializer of f.
Haven't checked if the new function you've added is called before or after
analyze_function calls omp_discover_implicit_declare_target, but I don't
really see how it can work when it is not inside of that function, so that
discovery of new static vars that are implicitly declare target to doesn't
result in marking of its dynamic initializers too.  Perhaps we need a
langhook for that.  But if it is a separate function, either it is called
before the other discovery and will ignore static initializers for vars
that will only be marked as implicit declare target to later, or it is done
afterwards, but then it would really need to duplicate everything what the
other function does, otherwise it woiuldn't discover everything.

Anyway, that is one thing, the other is even if the implicit declare target
discovery handles those correctly, the question is what should we do
afterwards.  Because the C++ FE normally creates a single function that
performs the dynamic initialization of the TUs variables.  But that function
shouldn't be really declare target to, it initializes not only (explicit or
implicit) declare target to variables, but also host only variables.
So we'll probably need to create next to that host only TU constructor
also a device only constructor function that will only initialize the
declare target to variables.

        Jakub

Reply via email to