[cfe-dev] Implementing OpenMP function variants

Doerfert, Johannes via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 18 12:02:59 PST 2019


On 12/18, John McCall wrote:
> On 18 Dec 2019, at 14:25, Doerfert, Johannes wrote:
> > On 12/18, John McCall wrote:
> >> 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?
> >
> > In 5.1, `begin/end declare variant` multi-version a function basically
> > the same way as `__attribute__((target(...)))` does. The condition can
> > be more than only a target though. (I mispoke earlier, it can include
> > call site context information). So we have multiple versions of a
> > function, let's say "sin", and depending on the compilation target,
> > e.g., are we compiling for nvptx or not, ans call site context, e.g.,
> > are we syntacitally inside a parallel region, we pick on of them. The
> > prototype for this reuses almost all of the multi-version code that
> > enables the target attribute as it seemed to be the natural fit.
> 
> I see.  And that’s still totally statically selected at use time, right?

Yes, as of OpenMP TR8 (Nov this year). But (to me) it is fairly certain
we'll also get an dynamic dispatch version too, maybe even this year (for
OpenMP 5.1).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20191218/a0b7b9c7/attachment.sig>


More information about the cfe-dev mailing list