[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