\pagebreak
\section{Metadirective Directive}
\label{sec:metadirective}

A \code{metadirective} directive provides a mechanism to select a directive in
a \code{when} clause to be used, depending upon one or more contexts:  
implementation, available devices and the present enclosing construct. 
The directive in a \code{default} clause is used when a directive of the 
\code{when} clause is not selected.

In the \code{when} clause the \plc{context selector} (or just \plc{selector}) defines traits that are
evaluated for selection of the directive that follows the selector. 
This "selectable" directive is called a \plc{directive variant}.
Traits are grouped by \plc{construct}, \plc{implementation} and 
\plc{device} \plc{sets} to be used by a selector of the same name.

In the first example the architecture trait \plc{arch} of the 
\plc{device} selector set specifies that if an \plc{nvptx} (NVIDIA) architecture is
active in the OpenMP context, then the \code{teams}~\code{loop} 
\plc{directive variant} is selected as the directive; otherwise, the \code{parallel}~\code{loop}
\plc{directive variant} of the \code{default} clause is selected as the directive.
That is, if a \plc{device} of \plc{nvptx} architecture is supported by the implementation within
the enclosing \code{target} construct, its \plc{directive variant} is selected.
The architecture names, such as \plc{nvptx}, are implementation defined.
Also, note that \plc{device} as used in a \code{target} construct specifies
a device number, while \plc{device}, as used in the \code{metadirective}
directive as selector set, has traits of \plc{kind}, \plc{isa} and \plc{arch}.



\cexample[5.0]{metadirective}{1}

\ffreeexample[5.0]{metadirective}{1}

%\pagebreak
In the second example, the \plc{implementation} selector set is specified
in the \code{when} clause to distinguish between AMD and NVIDIA platforms. 
Additionally, specific architectures are specified with the \plc{device} 
selector set.

In the code, different \code{teams} constructs are employed as determined
by the \code{metadirective} directive.
The number of teams is restricted by a \code{num\_teams} clause
and a thread limit is also set by a \code{thread\_limit} clause for 
\plc{vendor} AMD and NVIDIA platforms and specific architecture
traits.  Otherwise, just the \code{teams} construct is used without
any clauses, as prescribed by the \code{default} clause.


\cexample[5.0]{metadirective}{2}

\ffreeexample[5.0]{metadirective}{2}

\clearpage

%\pagebreak
In the third example, a \plc{construct} selector set is specified in the \code{when} clause.  
Here, a \code{metadirective} directive is used within a function that is also
compiled as a function for a target device as directed by the \code{declare}~\code{target} directive.
The \plc{target} directive name of the \code{construct} selector ensures that the
\code{distribute}~\code{parallel}~\code{for/do} construct is employed for the target compilation.
Otherwise, for the host-compiled version the \code{parallel}~\code{for/do}~\code{simd} construct is used.

In the first call to the \plc{exp\_pi\_diff()} routine the context is a
\code{target}~\code{teams} construct and the \code{distribute}~\code{parallel}~\code{for/do}
construct version of the function is invoked,
while in the second call the \code{parallel}~\code{for/do}~\code{simd} construct version is used.

%%%%%%%%
This case illustrates an important point for users that may want to hoist the 
\code{target} directive out of a function that contains the usual 
\code{target}~\code{teams}~\code{distribute}~\code{parallel}~\code{for/do} construct
(for providing alternate constructs through the \code{metadirective} directive as here).
While this combined construct can be decomposed into a \code{target} and
\code{teams distribute parallel for/do} constructs, the OpenMP 5.0 specification has the restriction:
``If a \code{teams} construct is nested within a \code{target} construct, that \code{target} construct must
contain no statements, declarations or directives outside of the \code{teams} construct''.
So, the \code{teams} construct must immediately follow the \code{target} construct without any intervening
code statements (which includes function calls).  
Since the \code{target} construct alone cannot be hoisted out of a function, 
the \code{target}~\code{teams} construct has been hoisted out of the function, and the 
\code{distribute}~\code{parallel}~\code{for/do} construct is used
as the \plc{variant} directive of the \code{metadirective} directive within the function.
%%%%%%%%

\cexample[5.0]{metadirective}{3}

\ffreeexample[5.0]{metadirective}{3}
