[cfe-dev] Implementing OpenMP function variants

Finkel, Hal J. via cfe-dev cfe-dev at lists.llvm.org
Tue Dec 17 04:25:30 PST 2019


On 12/13/19 9:08 AM, Hal Finkel 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.


Another question that has come up in the review is this: are there 
potential issues with introducing additional cases where FoundDecl != Decl.

  -Hal


>
> 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.
>
> 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



More information about the cfe-dev mailing list