[cfe-dev] Implementing OpenMP function variants

John McCall via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 18 09:31:15 PST 2019


On 18 Dec 2019, at 11:16, Doerfert, Johannes wrote:
> On 12/18, John McCall wrote:
>> On 13 Dec 2019, at 10:08, Finkel, Hal J. wrote:
>>> Richard, John, et al.,
>>>
>>> Let me top-post here quickly to add that this question comes 
>>> directly
>>> from a disagreement about the application of Clang's design 
>>> principle of
>>> keeping the AST faithful to the source code (and I suspect that such 
>>> a
>>> question may be of wider interest to the community).
>>>
>>> Johannes has summarized the OpenMP language semantics below (thanks,
>>> Johannes!).
>>>
>>> The relevant review thread is here: https://reviews.llvm.org/D71241
>>>
>>> Alexey's position is that, because the source code contains what 
>>> appears
>>> to be a call to the base() function, the AST should always reflect 
>>> that
>>> fact by having getCallee() return a reference to base(), and we 
>>> should
>>> lower the call to the selected variant using logic in CodeGen. Some
>>> other member function should be used by AST-level tools to retrieve 
>>> the
>>> actually-called variant. This has the benefit that the primary AST
>>> representation is independent of the compilation target and other
>>> relevant OpenMP context.
>>>
>>> My position is that, like other cases where we perform overload
>>> resolution and specializaton selection (including host/device 
>>> overloads
>>> in CUDA), we should resolve the variant selected in Sema, and
>>> getCallee() should return a reference to the function that will 
>>> actually
>>> be called (even if that function has a different name from the name 
>>> used
>>> syntactically to form the call expression). This will ensure that
>>> static-analysis tools see the correct call-site <-> callee 
>>> relationship.
>>> We should, I think, also keep a reference to the original OpenMP 
>>> base
>>> function in the AST, but some other member function should be used 
>>> to
>>> retrieve it.
>>>
>>> We say that we keep Clang's AST faithful to the source code, but how 
>>> to
>>> best apply that philosophy in this case is now under debate.
>>
>> Is it always immediately decidable when parsing a reference to a 
>> function
>> which variant should be used, or is it sometimes dynamic or at least
>> delayed?
>
> For now, which means OpenMP 5.0 and TR8, it is conceptually 
> immediately
> decidable. It only depends on compilation parameters, e.g., the target
> triple, and the lexical context.
>
>> How is this expected to interact with C++ overloading?  Can you
>> independently declare variants of each overload?
>
> While the standard is not specific on this, I don't see why not.
>
> I tried to summarize what the standard says yesterday [0]:
>
> OpenMP basically says, if you have a call to a (base)function* that 
> has
> variants with contexts that match at the call site, call the variant
> with the highest score. The variants are specified by a 
> variant-func-id,
> which is a base language identifier or C++ template-id. For C++, the
> variant declaration is identified by *performing the base language
> lookup rules on the variant-func-id with arguments that correspond to
> the base function argument types*.
>
> * However you figured out that the base function is the one called in
>   the first place.
>
> [0] https://reviews.llvm.org/D71241#1788003
>
>> How does this interact with nested scopes?  If all variants are 
>> unacceptable
>> for the use context, is it like the declaration just doesn’t exist, 
>> and so
>> lookup continues to outer scopes?  Or is this impossible because 
>> there
>> always has to be a non-variant declaration in the current scope?
>
> The latter. As mentioned above, you first find the "normal" call 
> target
> and then apply the variant logic from there.
>
>
>> My immediate intuition is that, assuming the semantics are always 
>> static and
>> that there’s always a non-variant function, this should be handled 
>> as a sort
>> of second level of overload resolution.  The variant declarations 
>> should be
>> considered more-or-less independent functions; they are not 
>> redeclarations
>> of the original.  5.1-type variants should be hidden from lookup, so 
>> that
>> only the original function is found.  When we resolve a use of a 
>> declaration
>> with variants we then pick the appropriate variant and treat the 
>> declaration
>> as if it was using that originally.  The fact that we resolved it via 
>> a
>> variant should be recorded in the FoundDecl, which would now have an
>> additional possible state: we could have looked through a using 
>> declaration,
>> and we could have resolved a variant.  This shouldn’t be a problem 
>> for
>> FoundDecl.
>
> I think your assumptions are met.
>
> Is there a good reason to make 5.1-type variants different from
> multi-versions (as we have them)? They do not depend on the lexical 
> call
> context but only on the compilation parameters.

Are multi-versions yet another feature?  Do they interact with this one?

John.

>
>
>>>
>>> Thanks again,
>>>
>>> Hal
>>>
>>> On 12/12/19 11:28 PM, Doerfert, Johannes wrote:
>>>> Background:
>>>>
>>>> The prototype for OpenMPs 5.1 feature `begin/end declare variant`
>>>> caused
>>>> a discussion that seems to be stuck. I'll briefly outline the
>>>> semantics
>>>> of the OpenMP 5.0 `declare variant` and the `begin/end declare
>>>> variant`
>>>> here before I present the two competing designs on a very high
>>>> level. If
>>>> there is a need for more information, a summary of what was said, 
>>>> or
>>>> anything else, please feel free to ask for it.
>>>>
>>>> ---
>>>>
>>>> OpenMP 5.0 `declare variant` allows you to define a variant of a 
>>>> base
>>>> function that is called instead of the base function if the context
>>>> specified with the variant matches at a call site.
>>>>
>>>> As an example, the call to base below is replaced by a call to
>>>> special
>>>> if the code is compiled with a compiler that identifies as "llvm".
>>>>
>>>> ```
>>>> void special();
>>>>
>>>> #pragma omp declare variant(special)
>>>> match(implementation={vendor(llvm)})
>>>> void base();
>>>>
>>>> void test() {
>>>>    base();
>>>> }
>>>> ```
>>>>
>>>> Context selectors for the match clause can be specific to the 
>>>> target,
>>>> the implementation, or the context in which the call is executed,
>>>> e.g.,
>>>> syntactic inside a #omp parallel.
>>>>
>>>> ---
>>>>
>>>> OpenMP 5.1 `begin/end declare variant` is an extension of the 5.0
>>>> version that (1) makes the user specific mangling obsolete, and (2)
>>>> guards the code in between the begin/end if the context selector 
>>>> does
>>>> not match at compile time. The use case can be simplified to the 
>>>> code
>>>> below in which we want the `sin` call to resolve to the NVIDIA
>>>> specific
>>>> version if we are compiling for nvptx and to the one in math.h
>>>> otherwise. Note that the variant in the begin/end range has the 
>>>> same
>>>> name as the base it overloads.
>>>>
>>>> ```
>>>> #include "math.h"
>>>>
>>>> #pragma omp begin declare variant match(device={arch(nvptx)})
>>>> double sin(double s) { return __nv_sin(s); }
>>>> #pragma omp end declare variant
>>>>
>>>> double calc(double s) {
>>>>    return sin(sin(sin(s)));
>>>> }
>>>> ```
>>>>
>>>> ---
>>>>
>>>> Now that we are all OpenMP experts, we need to decide how/where to
>>>> implement this. Oversimplified, these are the options being
>>>> discussed:
>>>>
>>>> Proposal 1, CodeGen:
>>>>    Introduce aliases that redirect from one function to the other 
>>>> or
>>>>    replace the callee in the CodeGen.
>>>>
>>>> Proposal 2), SemaOverload:
>>>>    Use the multi-version overloading for the 5.1 feature and
>>>> introduce
>>>>    another level of overload resolution for the 5.0 feature.
>>>>
>>>> ---
>>>>
>>>> Thanks in advance for your time and input,
>>>>    Johannes
>>>
>>> -- 
>>> Hal Finkel
>>> Lead, Compiler Technology and Programming Languages
>>> Leadership Computing Facility
>>> Argonne National Laboratory
>
> -- 
>
> Johannes Doerfert
> Researcher
>
> Argonne National Laboratory
> Lemont, IL 60439, USA
>
> jdoerfert at anl.gov


More information about the cfe-dev mailing list