Files
gps/tools/local/circt/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
T
2026-07-12 11:01:51 +03:00

299 lines
13 KiB
TableGen

//===- OpenMPOpBase.td - OpenMP dialect shared definitions -*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains shared definitions for the OpenMP dialect.
//
//===----------------------------------------------------------------------===//
#ifndef OPENMP_OP_BASE
#define OPENMP_OP_BASE
include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td"
include "mlir/Dialect/OpenMP/OpenMPDialect.td"
include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td"
include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td"
include "mlir/IR/OpBase.td"
//===----------------------------------------------------------------------===//
// OpenMP dialect type constraints.
//===----------------------------------------------------------------------===//
class OpenMP_Type<string name, string typeMnemonic> :
TypeDef<OpenMP_Dialect, name> {
let mnemonic = typeMnemonic;
}
// Type which can be constraint accepting standard integers and indices.
def IntLikeType : AnyTypeOf<[AnyInteger, Index]>;
def OpenMP_PointerLikeType : TypeAlias<OpenMP_PointerLikeTypeInterface,
"OpenMP-compatible variable type">;
def OpenMP_MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> {
let summary = "Type for representing omp map clause bounds information";
}
def OpenMP_AffinityEntryType
: OpenMP_Type<"AffinityEntry", "affinity_entry_ty"> {
let summary = "Type for representing omp affinity clause locator information";
let parameters = (ins "Type":$addrType, "Type":$lenType);
let assemblyFormat = "`<` $addrType `,` $lenType `>`";
}
def OpenMP_IteratedType : OpenMP_Type<"Iterated", "iterated"> {
let summary = "OpenMP iterator-produced list handle";
let parameters = (ins "Type":$elementType);
let assemblyFormat = "`<` $elementType `>`";
}
//===---------------------------------------------------------------------===//
// OpenMP Canonical Loop Info Type
//===---------------------------------------------------------------------===//
def CanonicalLoopInfoType : OpenMP_Type<"CanonicalLoopInfo", "cli"> {
let summary = "Type for representing a reference to a canonical loop";
let description = [{
A variable of type CanonicalLoopInfo refers to an OpenMP-compatible
canonical loop in the same function. Values of this type are not
available at runtime and therefore cannot be used by the program itself,
i.e. an opaque type. It is similar to the transform dialect's
`!transform.interface` type, but instead of implementing an interface
for each transformation, the OpenMP dialect itself defines possible
operations on this type.
A value of type CanonicalLoopInfoType (in the following: CLI) value can be
1. created by omp.new_cli.
2. passed to omp.canonical_loop to associate the loop to that CLI. A CLI
can only be associated once.
3. passed to an omp loop transformation operation that modifies the loop
associated with the CLI. The CLI is the "applyee" and the operation is
the consumer. A CLI can only be consumed once.
4. passed to an omp loop transformation operation to associate the cli with
a result of that transformation. The CLI is the "generatee" and the
operation is the generator.
A CLI cannot
1. be returned from a function.
2. be passed to operations that are not specifically designed to take a
CanonicalLoopInfoType, including AnyType.
A CLI directly corresponds to an object of
OpenMPIRBuilder's CanonicalLoopInfo struct when lowering to LLVM-IR.
}];
}
//===----------------------------------------------------------------------===//
// Base classes for OpenMP dialect operations.
//===----------------------------------------------------------------------===//
// Base class for representing OpenMP clauses.
//
// Clauses are meant to be used in a mixin-style pattern to help define OpenMP
// operations in a scalable way, since often the same clause can be applied to
// multiple different operations.
//
// To keep the representation of clauses consistent across different operations,
// each clause must define a set of arguments (values and attributes) which will
// become input arguments of each OpenMP operation that accepts that clause.
//
// It is also recommended that an assembly format and description are defined
// for each clause wherever posible, to make sure they are always printed,
// parsed and described in the same way.
//
// Optionally, operation traits and extra class declarations might be attached
// to clauses, which will be forwarded to all operations that include them.
//
// An `OpenMP_Op` can inhibit the inheritance of `traits`, `arguments`,
// `description` and `extraClassDeclaration` fields from any given
// `OpenMP_Clause` by setting to 1 the corresponding "skip" template argument
// bit. Additionally, the `skipAssemblyFormat` bit inhibits the inheritance of
// fields used to populate `OpenMP_Op`'s `assemblyFormat` (i.e.
// `reqAssemblyFormat` and `optAssemblyFormat`).
class OpenMP_Clause<bit skipTraits, bit skipArguments, bit skipAssemblyFormat,
bit skipDescription, bit skipExtraClassDeclaration> {
bit ignoreTraits = skipTraits;
list<Trait> traits = [];
bit ignoreArgs = skipArguments;
dag arguments;
bit ignoreAsmFormat = skipAssemblyFormat;
string reqAssemblyFormat = "";
string optAssemblyFormat = "";
bit ignoreDesc = skipDescription;
string description = "";
bit ignoreExtraDecl = skipExtraClassDeclaration;
string extraClassDeclaration = "";
}
// Base class for representing OpenMP operations.
//
// This is a subclass of the builtin `Op` for the OpenMP dialect. By default,
// some of its fields are initialized according to the list of OpenMP clauses
// passed as template argument:
// - `traits`: It is a union of the traits list passed as template argument
// and those inherited from the `traits` field of all clauses.
// - `arguments`: They are a concatenation of clause-inherited arguments. They
// are saved to a `clausesArgs` field to allow overriding the arguments
// field in the definition of the operation and still being able to include
// those inherited from clauses.
// - `assemblyFormat`: It is a concatenation of the `reqAssemblyFormat`
// followed by an `oilist()` containing the `optAssemblyFormat` of all
// clauses. The format string is completed with $region (if `singleRegion =
// true`) followed by `attr-dict`. This field remains uninitialized if no
// non-empty `{req,opt}AssemblyFormat` strings are inherited from clauses.
// The `clausesAssemblyFormat` field holds all the format string except for
// "$region attr-dict", and the `clauses{Req,Opt}AssemblyFormat` fields
// hold the required and optional parts of the format string separately, so
// that an operation overriding `assemblyFormat` can still benefit from the
// auto-generated format for its clauses.
// - `description`: This is still required to be defined by the operation.
// However, a `clausesDescription` field is provided containing a
// concatenation of descriptions of all clauses, to be appended to the
// operation's `description` field.
// - `extraClassDeclaration`: It contains a concatenation of the
// `extraClassDeclaration` of all clauses. This string is also stored in
// `clausesExtraClassDeclaration`, so that an operation overriding this
// field can append the clause-inherited ones as well.
//
// The `regions` field will contain a single `AnyRegion:$region` element if the
// `singleRegion` bit template argument is set to 1. Otherwise, it will be
// empty.
class OpenMP_Op<string mnemonic, list<Trait> traits = [],
list<OpenMP_Clause> clauses = [], bit singleRegion = false> :
Op<OpenMP_Dialect, mnemonic,
// The resulting operation's traits list will be the concatenation of
// explicit operation traits and all traits attached to the clauses of the
// operation. Repetitions are skipped.
!listconcat(traits,
!listremove(
!foldl([]<Trait>,
!foreach(clause,
!filter(fClause, clauses, !not(fClause.ignoreTraits)),
clause.traits),
acc, traitList, !listconcat(acc, !listremove(traitList, acc))),
traits
)
)> {
list<OpenMP_Clause> clauseList = clauses;
// Aggregate `arguments` fields of all clauses into a single dag, to be used
// by operations to populate their `arguments` field.
defvar argsFilteredClauses =
!filter(clause, clauses, !not(clause.ignoreArgs));
dag clausesArgs =
!foldl((ins), !foreach(clause, argsFilteredClauses, clause.arguments),
acc, argList, !con(acc, argList));
// Create assembly format string by concatenating format strings separately
// for required and optional clauses. Then, required clauses format strings
// are joined with spaces in between. Optional clauses format strings are
// wrapped into an unsorted list of optional values and separated by "|"
// characters.
// Required clauses.
defvar asmFormatFilteredReqClauses =
!filter(clause, clauses, !not(!or(clause.ignoreAsmFormat,
!empty(clause.reqAssemblyFormat))));
defvar asmFormatReqClauseStrings =
!foreach(clause, asmFormatFilteredReqClauses, clause.reqAssemblyFormat);
string clausesReqAssemblyFormat = !interleave(asmFormatReqClauseStrings, " ");
// Optional clauses.
defvar asmFormatFilteredOptClauses =
!filter(clause, clauses, !not(!or(clause.ignoreAsmFormat,
!empty(clause.optAssemblyFormat))));
defvar asmFormatOptClauseStrings =
!foreach(clause, asmFormatFilteredOptClauses, clause.optAssemblyFormat);
string clausesOptAssemblyFormat = !interleave(asmFormatOptClauseStrings, "|");
string clausesAssemblyFormat =
!if(!empty(asmFormatReqClauseStrings), "", clausesReqAssemblyFormat # " ") #
!if(!empty(asmFormatOptClauseStrings), "",
"oilist(" # clausesOptAssemblyFormat # ")");
// Put together descriptions of all clauses into a single string.
defvar descFilteredClauses =
!filter(clause, clauses, !not(clause.ignoreDesc));
string clausesDescription =
!interleave(!foreach(clause, descFilteredClauses, clause.description), "");
// Aggregate `extraClassDeclaration` of all clauses that define it.
defvar extraDeclFilteredClauses =
!filter(clause, clauses, !not(clause.ignoreExtraDecl));
string clausesExtraClassDeclaration =
!interleave(!foreach(clause, extraDeclFilteredClauses,
clause.extraClassDeclaration), "\n");
// The default arguments, assembly format and extra class declarations for
// OpenMP operations are those defined by their args and clauses.
let arguments = clausesArgs;
let assemblyFormat =
!if(!empty(clausesAssemblyFormat), ?,
clausesAssemblyFormat # !if(singleRegion, " $region", "") #
" attr-dict");
let extraClassDeclaration = clausesExtraClassDeclaration;
// By default, the op will have zero regions. Setting `singleRegion = true`
// will result in a single region named `$region`.
let regions = !if(singleRegion, (region AnyRegion:$region), (region));
}
// Base class for OpenMP loop transformations (that either consume or generate
// loops)
//
// Doesn't actually create a C++ base class (only defines default values for
// tablegen classes that derive from this). Use LoopTransformationInterface
// instead for common operations.
class OpenMPTransform_Op<string mnemonic,
list<Trait> traits = [],
list<OpenMP_Clause> clauses = []> :
OpenMP_Op<mnemonic,
traits = !listconcat([DeclareOpInterfaceMethods<LoopTransformationInterface>], traits),
clauses = clauses> {
}
// Base clause for loop transformations using the standard syntax.
//
// omp.opname ($generatees) <- ($applyees) clause(...) clause(...) ... <attr-dicr>
// omp.opname ($applyees) clause(...) clause(...) ... <attr-dict>
//
// $generatees is optional and is assumed to be empty if omitted
class OpenMPTransformBase_Op<string mnemonic,
list<Trait> traits = [],
list<OpenMP_Clause> clauses = []> :
OpenMPTransform_Op<mnemonic,
traits = !listconcat(traits, [AttrSizedOperandSegments]),
clauses = clauses> {
let arguments = !con(
(ins Variadic<CanonicalLoopInfoType>:$generatees,
Variadic<CanonicalLoopInfoType>:$applyees
), clausesArgs);
let assemblyFormat = [{ custom<LoopTransformClis>($generatees, $applyees) }]
# clausesAssemblyFormat
# [{ attr-dict }];
}
#endif // OPENMP_OP_BASE