-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[MLIR][OpenMP] Clause-based OpenMP operation definition #92523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-mlir-openmp @llvm/pr-subscribers-flang-openmp Author: Sergio Afonso (skatrak) ChangesThis patch updates There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the Patch is 106.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92523.diff 11 Files Affected:
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
index 244cee1dd635b..bd0d44f932981 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
@@ -39,6 +39,10 @@ struct AllocateClauseOps {
llvm::SmallVector<Value> allocatorVars, allocateVars;
};
+struct CancelDirectiveNameClauseOps {
+ ClauseCancellationConstructTypeAttr cancelDirectiveNameAttr;
+};
+
struct CollapseClauseOps {
llvm::SmallVector<Value> loopLBVar, loopUBVar, loopStepVar;
};
@@ -48,6 +52,10 @@ struct CopyprivateClauseOps {
llvm::SmallVector<Attribute> copyprivateFuncs;
};
+struct CriticalNameClauseOps {
+ StringAttr criticalNameAttr;
+};
+
struct DependClauseOps {
llvm::SmallVector<Attribute> dependTypeAttrs;
llvm::SmallVector<Value> dependVars;
@@ -84,6 +92,7 @@ struct GrainsizeClauseOps {
struct HasDeviceAddrClauseOps {
llvm::SmallVector<Value> hasDeviceAddrVars;
};
+
struct HintClauseOps {
IntegerAttr hintAttr;
};
@@ -117,10 +126,6 @@ struct MergeableClauseOps {
UnitAttr mergeableAttr;
};
-struct NameClauseOps {
- StringAttr nameAttr;
-};
-
struct NogroupClauseOps {
UnitAttr nogroupAttr;
};
@@ -209,8 +214,12 @@ struct UntiedClauseOps {
UnitAttr untiedAttr;
};
-struct UseDeviceClauseOps {
- llvm::SmallVector<Value> useDevicePtrVars, useDeviceAddrVars;
+struct UseDeviceAddrClauseOps {
+ llvm::SmallVector<Value> useDeviceAddrVars;
+};
+
+struct UseDevicePtrClauseOps {
+ llvm::SmallVector<Value> useDevicePtrVars;
};
//===----------------------------------------------------------------------===//
@@ -225,7 +234,13 @@ template <typename... Mixins>
struct Clauses : public Mixins... {};
} // namespace detail
-using CriticalClauseOps = detail::Clauses<HintClauseOps, NameClauseOps>;
+using CancelClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps, IfClauseOps>;
+
+using CancellationPointClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps>;
+
+using CriticalClauseOps = detail::Clauses<CriticalNameClauseOps, HintClauseOps>;
// TODO `indirect` clause.
using DeclareTargetClauseOps = detail::Clauses<DeviceTypeClauseOps>;
@@ -264,10 +279,11 @@ using TargetClauseOps =
detail::Clauses<AllocateClauseOps, DependClauseOps, DeviceClauseOps,
HasDeviceAddrClauseOps, IfClauseOps, InReductionClauseOps,
IsDevicePtrClauseOps, MapClauseOps, NowaitClauseOps,
- PrivateClauseOps, ReductionClauseOps, ThreadLimitClauseOps>;
+ PrivateClauseOps, ThreadLimitClauseOps>;
-using TargetDataClauseOps = detail::Clauses<DeviceClauseOps, IfClauseOps,
- MapClauseOps, UseDeviceClauseOps>;
+using TargetDataClauseOps =
+ detail::Clauses<DeviceClauseOps, IfClauseOps, MapClauseOps,
+ UseDeviceAddrClauseOps, UseDevicePtrClauseOps>;
using TargetEnterExitUpdateDataClauseOps =
detail::Clauses<DependClauseOps, DeviceClauseOps, IfClauseOps, MapClauseOps,
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 0a688635e69da..49eedfeba2ee0 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -16,7 +16,7 @@
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td"
-include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td"
+include "mlir/Dialect/OpenMP/OpenMPClauses.td"
include "mlir/Dialect/OpenMP/OpenMPOpBase.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
@@ -126,26 +126,25 @@ def PrivateClauseOp : OpenMP_Op<"private", [IsolatedFromAbove]> {
//===----------------------------------------------------------------------===//
def ParallelOp : OpenMP_Op<"parallel", [
- AutomaticAllocationScope, AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface]> {
+ AttrSizedOperandSegments, AutomaticAllocationScope,
+ DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
+ RecursiveMemoryEffects
+ ], [
+ // TODO: Sort clauses alphabetically.
+ OpenMP_IfClause, OpenMP_NumThreadsClause, OpenMP_AllocateClause,
+ OpenMP_ReductionClause, OpenMP_ProcBindClause, OpenMP_PrivateClause
+ ], singleRegion = true> {
let summary = "parallel construct";
let description = [{
The parallel construct includes a region of code which is to be executed
by a team of threads.
- The optional $if_expr_var parameter specifies a boolean result of a
+ The optional `if_expr` parameter specifies a boolean result of a
conditional check. If this value is 1 or is not provided then the parallel
region runs as normal, if it is 0 then the parallel region is executed with
one thread.
- The optional $num_threads_var parameter specifies the number of threads which
- should be used to execute the parallel region.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
Reductions can be performed in a parallel construct by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -158,37 +157,21 @@ def ParallelOp : OpenMP_Op<"parallel", [
into the final value, which is available in the accumulator after all the
threads complete.
- The optional $proc_bind_val attribute controls the thread affinity for the execution
- of the parallel region.
-
- The optional byref attribute controls whether reduction arguments are passed by
- reference or by value.
- }];
-
- let arguments = (ins Optional<I1>:$if_expr_var,
- Optional<IntLikeType>:$num_threads_var,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- OptionalAttr<ProcBindKindAttr>:$proc_bind_val,
- Variadic<AnyType>:$private_vars,
- OptionalAttr<SymbolRefArrayAttr>:$privatizers,
- UnitAttr:$byref);
-
- let regions = (region AnyRegion:$region);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes)>,
OpBuilder<(ins CArg<"const ParallelClauseOps &">:$clauses)>
];
- let extraClassDeclaration = [{
- /// Returns the number of reduction variables.
- unsigned getNumReductionVars() { return getReductionVars().size(); }
- }];
+
+ // TODO: Use default assembly format inherited from OpenMP_Op after printing
+ // and parsing of the parallel region is not intermingled with printing and
+ // parsing of reduction and private clauses.
let assemblyFormat = [{
oilist(
- `if` `(` $if_expr_var `:` type($if_expr_var) `)`
+ `if` `(` $if_expr `)`
| `num_threads` `(` $num_threads_var `:` type($num_threads_var) `)`
| `allocate` `(`
custom<AllocateAndAllocator>(
@@ -201,6 +184,7 @@ def ParallelOp : OpenMP_Op<"parallel", [
$reductions, $private_vars, type($private_vars),
$privatizers) attr-dict
}];
+
let hasVerifier = 1;
}
@@ -220,63 +204,27 @@ def TerminatorOp : OpenMP_Op<"terminator", [Terminator, Pure]> {
// 2.7 teams Construct
//===----------------------------------------------------------------------===//
def TeamsOp : OpenMP_Op<"teams", [
- AttrSizedOperandSegments, RecursiveMemoryEffects,
- ReductionClauseInterface]> {
+ AttrSizedOperandSegments, RecursiveMemoryEffects
+ ], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_NumTeamsClause, OpenMP_IfClause, OpenMP_ThreadLimitClause,
+ OpenMP_AllocateClause, OpenMP_ReductionClause
+ ], singleRegion = true> {
let summary = "teams construct";
let description = [{
The teams construct defines a region of code that triggers the creation of a
league of teams. Once created, the number of teams remains constant for the
duration of its code region.
- The optional $num_teams_upper and $num_teams_lower specify the limit on the
- number of teams to be created. If only the upper bound is specified, it acts
- as if the lower bound was set to the same value. It is not supported to set
- $num_teams_lower if $num_teams_upper is not specified. They define a closed
- range, where both the lower and upper bounds are included.
-
- If the $if_expr is present and it evaluates to `false`, the number of teams
+ If the `if_expr` is present and it evaluates to `false`, the number of teams
created is one.
-
- The optional $thread_limit specifies the limit on the number of threads.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of
- values that specify the memory allocator to be used to obtain storage for
- private values.
- }];
-
- let arguments = (ins Optional<AnyInteger>:$num_teams_lower,
- Optional<AnyInteger>:$num_teams_upper,
- Optional<I1>:$if_expr,
- Optional<AnyInteger>:$thread_limit,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions);
-
- let regions = (region AnyRegion:$region);
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const TeamsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(
- `num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to`
- $num_teams_upper `:` type($num_teams_upper) `)`
- | `if` `(` $if_expr `)`
- | `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
- | `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
}
@@ -284,19 +232,22 @@ def TeamsOp : OpenMP_Op<"teams", [
// 2.8.1 Sections Construct
//===----------------------------------------------------------------------===//
-def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">]> {
+def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">],
+ singleRegion = true> {
let summary = "section directive";
let description = [{
A section operation encloses a region which represents one section in a
sections construct. A section op should always be surrounded by an
`omp.sections` operation.
}];
- let regions = (region AnyRegion:$region);
let assemblyFormat = "$region attr-dict";
}
-def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
- ReductionClauseInterface]> {
+def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_ReductionClause, OpenMP_AllocateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "sections construct";
let description = [{
The sections construct is a non-iterative worksharing construct that
@@ -317,38 +268,17 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
into the final value, which is available in the accumulator after all the
sections complete.
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the end of the construct.
- }];
- let arguments = (ins Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- UnitAttr:$nowait);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
+ // Override region definition.
let regions = (region SizedRegion<1>:$region);
let builders = [
OpBuilder<(ins CArg<"const SectionsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist( `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- | `nowait` $nowait
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
let hasRegionVerifier = 1;
}
@@ -357,45 +287,23 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
// 2.8.2 Single Construct
//===----------------------------------------------------------------------===//
-def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
+def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ OpenMP_AllocateClause, OpenMP_CopyprivateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "single directive";
let description = [{
The single construct specifies that the associated structured block is
executed by only one of the threads in the team (not necessarily the
master thread), in the context of its implicit task. The other threads
in the team, which do not execute the block, wait at an implicit barrier
- at the end of the single construct unless a nowait clause is specified.
-
- If copyprivate variables and functions are specified, then each thread
- variable is updated with the variable value of the thread that executed
- the single region, using the specified copy functions.
- }];
-
- let arguments = (ins Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$copyprivate_vars,
- OptionalAttr<SymbolRefArrayAttr>:$copyprivate_funcs,
- UnitAttr:$nowait);
-
- let regions = (region AnyRegion:$region);
+ at the end of the single construct.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const SingleClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(`allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- |`nowait` $nowait
- |`copyprivate` `(`
- custom<CopyPrivateVarList>(
- $copyprivate_vars, type($copyprivate_vars), $copyprivate_funcs
- ) `)`
- ) $region attr-dict
- }];
let hasVerifier = 1;
}
@@ -403,9 +311,11 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
// Loop Nest
//===----------------------------------------------------------------------===//
-def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
- AllTypesMatch<["lowerBound", "upperBound", "step"]>,
- RecursiveMemoryEffects]> {
+def LoopNestOp : OpenMP_Op<"loop_nest", [
+ RecursiveMemoryEffects, SameVariadicOperandSize
+ ], [
+ OpenMP_CollapseClause
+ ], singleRegion = true> {
let summary = "rectangular loop nest";
let description = [{
This operation represents a collapsed rectangular loop nest. For each
@@ -442,29 +352,24 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
non-perfectly nested loops.
}];
- let arguments = (ins Variadic<IntLikeType>:$lowerBound,
- Variadic<IntLikeType>:$upperBound,
- Variadic<IntLikeType>:$step,
- UnitAttr:$inclusive);
+ let arguments = !con(clausesArgs, (ins UnitAttr:$inclusive));
let builders = [
OpBuilder<(ins CArg<"const LoopNestClauseOps &">:$clauses)>
];
- let regions = (region AnyRegion:$region);
-
let extraClassDeclaration = [{
- /// Returns the number of loops in the loop nest.
- unsigned getNumLoops() { return getLowerBound().size(); }
-
/// Returns the induction variables of the loop nest.
ArrayRef<BlockArgument> getIVs() { return getRegion().getArguments(); }
/// Fills a list of wrapper operations around this loop nest. Wrappers
/// in the resulting vector will be sorted from innermost to outermost.
void gatherWrappers(SmallVectorImpl<LoopWrapperInterface> &wrappers);
- }];
+ }] # clausesExtraClassDeclaration;
+ // Disable inherited clause-based declarative assembly format and instead
+ // enable using the custom parser-printer implemented in C++.
+ let assemblyFormat = ?;
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
@@ -473,10 +378,15 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
// 2.9.2 Workshare Loop Construct
//===----------------------------------------------------------------------===//
-def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface,
- SingleBlockImplicitTerminator<"TerminatorOp">]> {
+def WsloopOp : OpenMP_Op<"wsloop", [
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp">
+ ], [
+ // TODO: Complete clause list (allocate, private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_LinearClause, OpenMP_ReductionClause, OpenMP_ScheduleClause,
+ OpenMP_NowaitClause, OpenMP_OrderedClause, OpenMP_OrderClause
+ ], singleRegion = true> {
let summary = "worksharing-loop construct";
let description = [{
The worksharing-loop construct specifies that the iterations of the loop(s)
@@ -501,11 +411,6 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
}
```
- The `linear_step_vars` operand additionally specifies the step for each
- associated linear operand. Note that the `linear_vars` and
- `linear_step_vars` variadic lists should contain the same number of
- elements.
-
Reductions can be performed in a worksharing-loop by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -516,55 +421,18 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
iteration into the final value, which is available in the accumulator after
the loop completes.
- The optional `schedule_val` attribute specifies the loop schedule for this
- loop, determining how the loop is distributed across the parallel threads.
- The optional `schedule_chunk_var` associated with this determines further
- controls this distribution.
-
- Collapsed loops are represented by the worksharing-loop having a list of
- indices, bounds and steps where the size of the list is equal to the
- collapse value.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the e...
[truncated]
|
@llvm/pr-subscribers-mlir-llvm Author: Sergio Afonso (skatrak) ChangesThis patch updates There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the Patch is 106.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92523.diff 11 Files Affected:
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
index 244cee1dd635b..bd0d44f932981 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
@@ -39,6 +39,10 @@ struct AllocateClauseOps {
llvm::SmallVector<Value> allocatorVars, allocateVars;
};
+struct CancelDirectiveNameClauseOps {
+ ClauseCancellationConstructTypeAttr cancelDirectiveNameAttr;
+};
+
struct CollapseClauseOps {
llvm::SmallVector<Value> loopLBVar, loopUBVar, loopStepVar;
};
@@ -48,6 +52,10 @@ struct CopyprivateClauseOps {
llvm::SmallVector<Attribute> copyprivateFuncs;
};
+struct CriticalNameClauseOps {
+ StringAttr criticalNameAttr;
+};
+
struct DependClauseOps {
llvm::SmallVector<Attribute> dependTypeAttrs;
llvm::SmallVector<Value> dependVars;
@@ -84,6 +92,7 @@ struct GrainsizeClauseOps {
struct HasDeviceAddrClauseOps {
llvm::SmallVector<Value> hasDeviceAddrVars;
};
+
struct HintClauseOps {
IntegerAttr hintAttr;
};
@@ -117,10 +126,6 @@ struct MergeableClauseOps {
UnitAttr mergeableAttr;
};
-struct NameClauseOps {
- StringAttr nameAttr;
-};
-
struct NogroupClauseOps {
UnitAttr nogroupAttr;
};
@@ -209,8 +214,12 @@ struct UntiedClauseOps {
UnitAttr untiedAttr;
};
-struct UseDeviceClauseOps {
- llvm::SmallVector<Value> useDevicePtrVars, useDeviceAddrVars;
+struct UseDeviceAddrClauseOps {
+ llvm::SmallVector<Value> useDeviceAddrVars;
+};
+
+struct UseDevicePtrClauseOps {
+ llvm::SmallVector<Value> useDevicePtrVars;
};
//===----------------------------------------------------------------------===//
@@ -225,7 +234,13 @@ template <typename... Mixins>
struct Clauses : public Mixins... {};
} // namespace detail
-using CriticalClauseOps = detail::Clauses<HintClauseOps, NameClauseOps>;
+using CancelClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps, IfClauseOps>;
+
+using CancellationPointClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps>;
+
+using CriticalClauseOps = detail::Clauses<CriticalNameClauseOps, HintClauseOps>;
// TODO `indirect` clause.
using DeclareTargetClauseOps = detail::Clauses<DeviceTypeClauseOps>;
@@ -264,10 +279,11 @@ using TargetClauseOps =
detail::Clauses<AllocateClauseOps, DependClauseOps, DeviceClauseOps,
HasDeviceAddrClauseOps, IfClauseOps, InReductionClauseOps,
IsDevicePtrClauseOps, MapClauseOps, NowaitClauseOps,
- PrivateClauseOps, ReductionClauseOps, ThreadLimitClauseOps>;
+ PrivateClauseOps, ThreadLimitClauseOps>;
-using TargetDataClauseOps = detail::Clauses<DeviceClauseOps, IfClauseOps,
- MapClauseOps, UseDeviceClauseOps>;
+using TargetDataClauseOps =
+ detail::Clauses<DeviceClauseOps, IfClauseOps, MapClauseOps,
+ UseDeviceAddrClauseOps, UseDevicePtrClauseOps>;
using TargetEnterExitUpdateDataClauseOps =
detail::Clauses<DependClauseOps, DeviceClauseOps, IfClauseOps, MapClauseOps,
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 0a688635e69da..49eedfeba2ee0 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -16,7 +16,7 @@
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td"
-include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td"
+include "mlir/Dialect/OpenMP/OpenMPClauses.td"
include "mlir/Dialect/OpenMP/OpenMPOpBase.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
@@ -126,26 +126,25 @@ def PrivateClauseOp : OpenMP_Op<"private", [IsolatedFromAbove]> {
//===----------------------------------------------------------------------===//
def ParallelOp : OpenMP_Op<"parallel", [
- AutomaticAllocationScope, AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface]> {
+ AttrSizedOperandSegments, AutomaticAllocationScope,
+ DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
+ RecursiveMemoryEffects
+ ], [
+ // TODO: Sort clauses alphabetically.
+ OpenMP_IfClause, OpenMP_NumThreadsClause, OpenMP_AllocateClause,
+ OpenMP_ReductionClause, OpenMP_ProcBindClause, OpenMP_PrivateClause
+ ], singleRegion = true> {
let summary = "parallel construct";
let description = [{
The parallel construct includes a region of code which is to be executed
by a team of threads.
- The optional $if_expr_var parameter specifies a boolean result of a
+ The optional `if_expr` parameter specifies a boolean result of a
conditional check. If this value is 1 or is not provided then the parallel
region runs as normal, if it is 0 then the parallel region is executed with
one thread.
- The optional $num_threads_var parameter specifies the number of threads which
- should be used to execute the parallel region.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
Reductions can be performed in a parallel construct by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -158,37 +157,21 @@ def ParallelOp : OpenMP_Op<"parallel", [
into the final value, which is available in the accumulator after all the
threads complete.
- The optional $proc_bind_val attribute controls the thread affinity for the execution
- of the parallel region.
-
- The optional byref attribute controls whether reduction arguments are passed by
- reference or by value.
- }];
-
- let arguments = (ins Optional<I1>:$if_expr_var,
- Optional<IntLikeType>:$num_threads_var,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- OptionalAttr<ProcBindKindAttr>:$proc_bind_val,
- Variadic<AnyType>:$private_vars,
- OptionalAttr<SymbolRefArrayAttr>:$privatizers,
- UnitAttr:$byref);
-
- let regions = (region AnyRegion:$region);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes)>,
OpBuilder<(ins CArg<"const ParallelClauseOps &">:$clauses)>
];
- let extraClassDeclaration = [{
- /// Returns the number of reduction variables.
- unsigned getNumReductionVars() { return getReductionVars().size(); }
- }];
+
+ // TODO: Use default assembly format inherited from OpenMP_Op after printing
+ // and parsing of the parallel region is not intermingled with printing and
+ // parsing of reduction and private clauses.
let assemblyFormat = [{
oilist(
- `if` `(` $if_expr_var `:` type($if_expr_var) `)`
+ `if` `(` $if_expr `)`
| `num_threads` `(` $num_threads_var `:` type($num_threads_var) `)`
| `allocate` `(`
custom<AllocateAndAllocator>(
@@ -201,6 +184,7 @@ def ParallelOp : OpenMP_Op<"parallel", [
$reductions, $private_vars, type($private_vars),
$privatizers) attr-dict
}];
+
let hasVerifier = 1;
}
@@ -220,63 +204,27 @@ def TerminatorOp : OpenMP_Op<"terminator", [Terminator, Pure]> {
// 2.7 teams Construct
//===----------------------------------------------------------------------===//
def TeamsOp : OpenMP_Op<"teams", [
- AttrSizedOperandSegments, RecursiveMemoryEffects,
- ReductionClauseInterface]> {
+ AttrSizedOperandSegments, RecursiveMemoryEffects
+ ], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_NumTeamsClause, OpenMP_IfClause, OpenMP_ThreadLimitClause,
+ OpenMP_AllocateClause, OpenMP_ReductionClause
+ ], singleRegion = true> {
let summary = "teams construct";
let description = [{
The teams construct defines a region of code that triggers the creation of a
league of teams. Once created, the number of teams remains constant for the
duration of its code region.
- The optional $num_teams_upper and $num_teams_lower specify the limit on the
- number of teams to be created. If only the upper bound is specified, it acts
- as if the lower bound was set to the same value. It is not supported to set
- $num_teams_lower if $num_teams_upper is not specified. They define a closed
- range, where both the lower and upper bounds are included.
-
- If the $if_expr is present and it evaluates to `false`, the number of teams
+ If the `if_expr` is present and it evaluates to `false`, the number of teams
created is one.
-
- The optional $thread_limit specifies the limit on the number of threads.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of
- values that specify the memory allocator to be used to obtain storage for
- private values.
- }];
-
- let arguments = (ins Optional<AnyInteger>:$num_teams_lower,
- Optional<AnyInteger>:$num_teams_upper,
- Optional<I1>:$if_expr,
- Optional<AnyInteger>:$thread_limit,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions);
-
- let regions = (region AnyRegion:$region);
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const TeamsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(
- `num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to`
- $num_teams_upper `:` type($num_teams_upper) `)`
- | `if` `(` $if_expr `)`
- | `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
- | `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
}
@@ -284,19 +232,22 @@ def TeamsOp : OpenMP_Op<"teams", [
// 2.8.1 Sections Construct
//===----------------------------------------------------------------------===//
-def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">]> {
+def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">],
+ singleRegion = true> {
let summary = "section directive";
let description = [{
A section operation encloses a region which represents one section in a
sections construct. A section op should always be surrounded by an
`omp.sections` operation.
}];
- let regions = (region AnyRegion:$region);
let assemblyFormat = "$region attr-dict";
}
-def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
- ReductionClauseInterface]> {
+def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_ReductionClause, OpenMP_AllocateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "sections construct";
let description = [{
The sections construct is a non-iterative worksharing construct that
@@ -317,38 +268,17 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
into the final value, which is available in the accumulator after all the
sections complete.
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the end of the construct.
- }];
- let arguments = (ins Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- UnitAttr:$nowait);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
+ // Override region definition.
let regions = (region SizedRegion<1>:$region);
let builders = [
OpBuilder<(ins CArg<"const SectionsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist( `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- | `nowait` $nowait
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
let hasRegionVerifier = 1;
}
@@ -357,45 +287,23 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
// 2.8.2 Single Construct
//===----------------------------------------------------------------------===//
-def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
+def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ OpenMP_AllocateClause, OpenMP_CopyprivateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "single directive";
let description = [{
The single construct specifies that the associated structured block is
executed by only one of the threads in the team (not necessarily the
master thread), in the context of its implicit task. The other threads
in the team, which do not execute the block, wait at an implicit barrier
- at the end of the single construct unless a nowait clause is specified.
-
- If copyprivate variables and functions are specified, then each thread
- variable is updated with the variable value of the thread that executed
- the single region, using the specified copy functions.
- }];
-
- let arguments = (ins Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$copyprivate_vars,
- OptionalAttr<SymbolRefArrayAttr>:$copyprivate_funcs,
- UnitAttr:$nowait);
-
- let regions = (region AnyRegion:$region);
+ at the end of the single construct.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const SingleClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(`allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- |`nowait` $nowait
- |`copyprivate` `(`
- custom<CopyPrivateVarList>(
- $copyprivate_vars, type($copyprivate_vars), $copyprivate_funcs
- ) `)`
- ) $region attr-dict
- }];
let hasVerifier = 1;
}
@@ -403,9 +311,11 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
// Loop Nest
//===----------------------------------------------------------------------===//
-def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
- AllTypesMatch<["lowerBound", "upperBound", "step"]>,
- RecursiveMemoryEffects]> {
+def LoopNestOp : OpenMP_Op<"loop_nest", [
+ RecursiveMemoryEffects, SameVariadicOperandSize
+ ], [
+ OpenMP_CollapseClause
+ ], singleRegion = true> {
let summary = "rectangular loop nest";
let description = [{
This operation represents a collapsed rectangular loop nest. For each
@@ -442,29 +352,24 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
non-perfectly nested loops.
}];
- let arguments = (ins Variadic<IntLikeType>:$lowerBound,
- Variadic<IntLikeType>:$upperBound,
- Variadic<IntLikeType>:$step,
- UnitAttr:$inclusive);
+ let arguments = !con(clausesArgs, (ins UnitAttr:$inclusive));
let builders = [
OpBuilder<(ins CArg<"const LoopNestClauseOps &">:$clauses)>
];
- let regions = (region AnyRegion:$region);
-
let extraClassDeclaration = [{
- /// Returns the number of loops in the loop nest.
- unsigned getNumLoops() { return getLowerBound().size(); }
-
/// Returns the induction variables of the loop nest.
ArrayRef<BlockArgument> getIVs() { return getRegion().getArguments(); }
/// Fills a list of wrapper operations around this loop nest. Wrappers
/// in the resulting vector will be sorted from innermost to outermost.
void gatherWrappers(SmallVectorImpl<LoopWrapperInterface> &wrappers);
- }];
+ }] # clausesExtraClassDeclaration;
+ // Disable inherited clause-based declarative assembly format and instead
+ // enable using the custom parser-printer implemented in C++.
+ let assemblyFormat = ?;
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
@@ -473,10 +378,15 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
// 2.9.2 Workshare Loop Construct
//===----------------------------------------------------------------------===//
-def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface,
- SingleBlockImplicitTerminator<"TerminatorOp">]> {
+def WsloopOp : OpenMP_Op<"wsloop", [
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp">
+ ], [
+ // TODO: Complete clause list (allocate, private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_LinearClause, OpenMP_ReductionClause, OpenMP_ScheduleClause,
+ OpenMP_NowaitClause, OpenMP_OrderedClause, OpenMP_OrderClause
+ ], singleRegion = true> {
let summary = "worksharing-loop construct";
let description = [{
The worksharing-loop construct specifies that the iterations of the loop(s)
@@ -501,11 +411,6 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
}
```
- The `linear_step_vars` operand additionally specifies the step for each
- associated linear operand. Note that the `linear_vars` and
- `linear_step_vars` variadic lists should contain the same number of
- elements.
-
Reductions can be performed in a worksharing-loop by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -516,55 +421,18 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
iteration into the final value, which is available in the accumulator after
the loop completes.
- The optional `schedule_val` attribute specifies the loop schedule for this
- loop, determining how the loop is distributed across the parallel threads.
- The optional `schedule_chunk_var` associated with this determines further
- controls this distribution.
-
- Collapsed loops are represented by the worksharing-loop having a list of
- indices, bounds and steps where the size of the list is equal to the
- collapse value.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the e...
[truncated]
|
@llvm/pr-subscribers-mlir Author: Sergio Afonso (skatrak) ChangesThis patch updates There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the Patch is 106.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92523.diff 11 Files Affected:
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
index 244cee1dd635b..bd0d44f932981 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
@@ -39,6 +39,10 @@ struct AllocateClauseOps {
llvm::SmallVector<Value> allocatorVars, allocateVars;
};
+struct CancelDirectiveNameClauseOps {
+ ClauseCancellationConstructTypeAttr cancelDirectiveNameAttr;
+};
+
struct CollapseClauseOps {
llvm::SmallVector<Value> loopLBVar, loopUBVar, loopStepVar;
};
@@ -48,6 +52,10 @@ struct CopyprivateClauseOps {
llvm::SmallVector<Attribute> copyprivateFuncs;
};
+struct CriticalNameClauseOps {
+ StringAttr criticalNameAttr;
+};
+
struct DependClauseOps {
llvm::SmallVector<Attribute> dependTypeAttrs;
llvm::SmallVector<Value> dependVars;
@@ -84,6 +92,7 @@ struct GrainsizeClauseOps {
struct HasDeviceAddrClauseOps {
llvm::SmallVector<Value> hasDeviceAddrVars;
};
+
struct HintClauseOps {
IntegerAttr hintAttr;
};
@@ -117,10 +126,6 @@ struct MergeableClauseOps {
UnitAttr mergeableAttr;
};
-struct NameClauseOps {
- StringAttr nameAttr;
-};
-
struct NogroupClauseOps {
UnitAttr nogroupAttr;
};
@@ -209,8 +214,12 @@ struct UntiedClauseOps {
UnitAttr untiedAttr;
};
-struct UseDeviceClauseOps {
- llvm::SmallVector<Value> useDevicePtrVars, useDeviceAddrVars;
+struct UseDeviceAddrClauseOps {
+ llvm::SmallVector<Value> useDeviceAddrVars;
+};
+
+struct UseDevicePtrClauseOps {
+ llvm::SmallVector<Value> useDevicePtrVars;
};
//===----------------------------------------------------------------------===//
@@ -225,7 +234,13 @@ template <typename... Mixins>
struct Clauses : public Mixins... {};
} // namespace detail
-using CriticalClauseOps = detail::Clauses<HintClauseOps, NameClauseOps>;
+using CancelClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps, IfClauseOps>;
+
+using CancellationPointClauseOps =
+ detail::Clauses<CancelDirectiveNameClauseOps>;
+
+using CriticalClauseOps = detail::Clauses<CriticalNameClauseOps, HintClauseOps>;
// TODO `indirect` clause.
using DeclareTargetClauseOps = detail::Clauses<DeviceTypeClauseOps>;
@@ -264,10 +279,11 @@ using TargetClauseOps =
detail::Clauses<AllocateClauseOps, DependClauseOps, DeviceClauseOps,
HasDeviceAddrClauseOps, IfClauseOps, InReductionClauseOps,
IsDevicePtrClauseOps, MapClauseOps, NowaitClauseOps,
- PrivateClauseOps, ReductionClauseOps, ThreadLimitClauseOps>;
+ PrivateClauseOps, ThreadLimitClauseOps>;
-using TargetDataClauseOps = detail::Clauses<DeviceClauseOps, IfClauseOps,
- MapClauseOps, UseDeviceClauseOps>;
+using TargetDataClauseOps =
+ detail::Clauses<DeviceClauseOps, IfClauseOps, MapClauseOps,
+ UseDeviceAddrClauseOps, UseDevicePtrClauseOps>;
using TargetEnterExitUpdateDataClauseOps =
detail::Clauses<DependClauseOps, DeviceClauseOps, IfClauseOps, MapClauseOps,
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 0a688635e69da..49eedfeba2ee0 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -16,7 +16,7 @@
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td"
-include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td"
+include "mlir/Dialect/OpenMP/OpenMPClauses.td"
include "mlir/Dialect/OpenMP/OpenMPOpBase.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
@@ -126,26 +126,25 @@ def PrivateClauseOp : OpenMP_Op<"private", [IsolatedFromAbove]> {
//===----------------------------------------------------------------------===//
def ParallelOp : OpenMP_Op<"parallel", [
- AutomaticAllocationScope, AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface]> {
+ AttrSizedOperandSegments, AutomaticAllocationScope,
+ DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
+ RecursiveMemoryEffects
+ ], [
+ // TODO: Sort clauses alphabetically.
+ OpenMP_IfClause, OpenMP_NumThreadsClause, OpenMP_AllocateClause,
+ OpenMP_ReductionClause, OpenMP_ProcBindClause, OpenMP_PrivateClause
+ ], singleRegion = true> {
let summary = "parallel construct";
let description = [{
The parallel construct includes a region of code which is to be executed
by a team of threads.
- The optional $if_expr_var parameter specifies a boolean result of a
+ The optional `if_expr` parameter specifies a boolean result of a
conditional check. If this value is 1 or is not provided then the parallel
region runs as normal, if it is 0 then the parallel region is executed with
one thread.
- The optional $num_threads_var parameter specifies the number of threads which
- should be used to execute the parallel region.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
Reductions can be performed in a parallel construct by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -158,37 +157,21 @@ def ParallelOp : OpenMP_Op<"parallel", [
into the final value, which is available in the accumulator after all the
threads complete.
- The optional $proc_bind_val attribute controls the thread affinity for the execution
- of the parallel region.
-
- The optional byref attribute controls whether reduction arguments are passed by
- reference or by value.
- }];
-
- let arguments = (ins Optional<I1>:$if_expr_var,
- Optional<IntLikeType>:$num_threads_var,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- OptionalAttr<ProcBindKindAttr>:$proc_bind_val,
- Variadic<AnyType>:$private_vars,
- OptionalAttr<SymbolRefArrayAttr>:$privatizers,
- UnitAttr:$byref);
-
- let regions = (region AnyRegion:$region);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes)>,
OpBuilder<(ins CArg<"const ParallelClauseOps &">:$clauses)>
];
- let extraClassDeclaration = [{
- /// Returns the number of reduction variables.
- unsigned getNumReductionVars() { return getReductionVars().size(); }
- }];
+
+ // TODO: Use default assembly format inherited from OpenMP_Op after printing
+ // and parsing of the parallel region is not intermingled with printing and
+ // parsing of reduction and private clauses.
let assemblyFormat = [{
oilist(
- `if` `(` $if_expr_var `:` type($if_expr_var) `)`
+ `if` `(` $if_expr `)`
| `num_threads` `(` $num_threads_var `:` type($num_threads_var) `)`
| `allocate` `(`
custom<AllocateAndAllocator>(
@@ -201,6 +184,7 @@ def ParallelOp : OpenMP_Op<"parallel", [
$reductions, $private_vars, type($private_vars),
$privatizers) attr-dict
}];
+
let hasVerifier = 1;
}
@@ -220,63 +204,27 @@ def TerminatorOp : OpenMP_Op<"terminator", [Terminator, Pure]> {
// 2.7 teams Construct
//===----------------------------------------------------------------------===//
def TeamsOp : OpenMP_Op<"teams", [
- AttrSizedOperandSegments, RecursiveMemoryEffects,
- ReductionClauseInterface]> {
+ AttrSizedOperandSegments, RecursiveMemoryEffects
+ ], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_NumTeamsClause, OpenMP_IfClause, OpenMP_ThreadLimitClause,
+ OpenMP_AllocateClause, OpenMP_ReductionClause
+ ], singleRegion = true> {
let summary = "teams construct";
let description = [{
The teams construct defines a region of code that triggers the creation of a
league of teams. Once created, the number of teams remains constant for the
duration of its code region.
- The optional $num_teams_upper and $num_teams_lower specify the limit on the
- number of teams to be created. If only the upper bound is specified, it acts
- as if the lower bound was set to the same value. It is not supported to set
- $num_teams_lower if $num_teams_upper is not specified. They define a closed
- range, where both the lower and upper bounds are included.
-
- If the $if_expr is present and it evaluates to `false`, the number of teams
+ If the `if_expr` is present and it evaluates to `false`, the number of teams
created is one.
-
- The optional $thread_limit specifies the limit on the number of threads.
-
- The $allocators_vars and $allocate_vars parameters are a variadic list of
- values that specify the memory allocator to be used to obtain storage for
- private values.
- }];
-
- let arguments = (ins Optional<AnyInteger>:$num_teams_lower,
- Optional<AnyInteger>:$num_teams_upper,
- Optional<I1>:$if_expr,
- Optional<AnyInteger>:$thread_limit,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions);
-
- let regions = (region AnyRegion:$region);
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const TeamsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(
- `num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to`
- $num_teams_upper `:` type($num_teams_upper) `)`
- | `if` `(` $if_expr `)`
- | `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
- | `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
}
@@ -284,19 +232,22 @@ def TeamsOp : OpenMP_Op<"teams", [
// 2.8.1 Sections Construct
//===----------------------------------------------------------------------===//
-def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">]> {
+def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">],
+ singleRegion = true> {
let summary = "section directive";
let description = [{
A section operation encloses a region which represents one section in a
sections construct. A section op should always be surrounded by an
`omp.sections` operation.
}];
- let regions = (region AnyRegion:$region);
let assemblyFormat = "$region attr-dict";
}
-def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
- ReductionClauseInterface]> {
+def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_ReductionClause, OpenMP_AllocateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "sections construct";
let description = [{
The sections construct is a non-iterative worksharing construct that
@@ -317,38 +268,17 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
into the final value, which is available in the accumulator after all the
sections complete.
- The $allocators_vars and $allocate_vars parameters are a variadic list of values
- that specify the memory allocator to be used to obtain storage for private values.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the end of the construct.
- }];
- let arguments = (ins Variadic<OpenMP_PointerLikeType>:$reduction_vars,
- OptionalAttr<SymbolRefArrayAttr>:$reductions,
- Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- UnitAttr:$nowait);
+ The optional `byref` attribute controls whether reduction arguments are
+ passed by reference or by value.
+ }] # clausesDescription;
+ // Override region definition.
let regions = (region SizedRegion<1>:$region);
let builders = [
OpBuilder<(ins CArg<"const SectionsClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist( `reduction` `(`
- custom<ReductionVarList>(
- $reduction_vars, type($reduction_vars), $reductions
- ) `)`
- | `allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- | `nowait` $nowait
- ) $region attr-dict
- }];
-
let hasVerifier = 1;
let hasRegionVerifier = 1;
}
@@ -357,45 +287,23 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
// 2.8.2 Single Construct
//===----------------------------------------------------------------------===//
-def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
+def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments], [
+ // TODO: Complete clause list (private).
+ OpenMP_AllocateClause, OpenMP_CopyprivateClause, OpenMP_NowaitClause
+ ], singleRegion = true> {
let summary = "single directive";
let description = [{
The single construct specifies that the associated structured block is
executed by only one of the threads in the team (not necessarily the
master thread), in the context of its implicit task. The other threads
in the team, which do not execute the block, wait at an implicit barrier
- at the end of the single construct unless a nowait clause is specified.
-
- If copyprivate variables and functions are specified, then each thread
- variable is updated with the variable value of the thread that executed
- the single region, using the specified copy functions.
- }];
-
- let arguments = (ins Variadic<AnyType>:$allocate_vars,
- Variadic<AnyType>:$allocators_vars,
- Variadic<OpenMP_PointerLikeType>:$copyprivate_vars,
- OptionalAttr<SymbolRefArrayAttr>:$copyprivate_funcs,
- UnitAttr:$nowait);
-
- let regions = (region AnyRegion:$region);
+ at the end of the single construct.
+ }] # clausesDescription;
let builders = [
OpBuilder<(ins CArg<"const SingleClauseOps &">:$clauses)>
];
- let assemblyFormat = [{
- oilist(`allocate` `(`
- custom<AllocateAndAllocator>(
- $allocate_vars, type($allocate_vars),
- $allocators_vars, type($allocators_vars)
- ) `)`
- |`nowait` $nowait
- |`copyprivate` `(`
- custom<CopyPrivateVarList>(
- $copyprivate_vars, type($copyprivate_vars), $copyprivate_funcs
- ) `)`
- ) $region attr-dict
- }];
let hasVerifier = 1;
}
@@ -403,9 +311,11 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
// Loop Nest
//===----------------------------------------------------------------------===//
-def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
- AllTypesMatch<["lowerBound", "upperBound", "step"]>,
- RecursiveMemoryEffects]> {
+def LoopNestOp : OpenMP_Op<"loop_nest", [
+ RecursiveMemoryEffects, SameVariadicOperandSize
+ ], [
+ OpenMP_CollapseClause
+ ], singleRegion = true> {
let summary = "rectangular loop nest";
let description = [{
This operation represents a collapsed rectangular loop nest. For each
@@ -442,29 +352,24 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
non-perfectly nested loops.
}];
- let arguments = (ins Variadic<IntLikeType>:$lowerBound,
- Variadic<IntLikeType>:$upperBound,
- Variadic<IntLikeType>:$step,
- UnitAttr:$inclusive);
+ let arguments = !con(clausesArgs, (ins UnitAttr:$inclusive));
let builders = [
OpBuilder<(ins CArg<"const LoopNestClauseOps &">:$clauses)>
];
- let regions = (region AnyRegion:$region);
-
let extraClassDeclaration = [{
- /// Returns the number of loops in the loop nest.
- unsigned getNumLoops() { return getLowerBound().size(); }
-
/// Returns the induction variables of the loop nest.
ArrayRef<BlockArgument> getIVs() { return getRegion().getArguments(); }
/// Fills a list of wrapper operations around this loop nest. Wrappers
/// in the resulting vector will be sorted from innermost to outermost.
void gatherWrappers(SmallVectorImpl<LoopWrapperInterface> &wrappers);
- }];
+ }] # clausesExtraClassDeclaration;
+ // Disable inherited clause-based declarative assembly format and instead
+ // enable using the custom parser-printer implemented in C++.
+ let assemblyFormat = ?;
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
@@ -473,10 +378,15 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize,
// 2.9.2 Workshare Loop Construct
//===----------------------------------------------------------------------===//
-def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
- DeclareOpInterfaceMethods<LoopWrapperInterface>,
- RecursiveMemoryEffects, ReductionClauseInterface,
- SingleBlockImplicitTerminator<"TerminatorOp">]> {
+def WsloopOp : OpenMP_Op<"wsloop", [
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp">
+ ], [
+ // TODO: Complete clause list (allocate, private).
+ // TODO: Sort clauses alphabetically.
+ OpenMP_LinearClause, OpenMP_ReductionClause, OpenMP_ScheduleClause,
+ OpenMP_NowaitClause, OpenMP_OrderedClause, OpenMP_OrderClause
+ ], singleRegion = true> {
let summary = "worksharing-loop construct";
let description = [{
The worksharing-loop construct specifies that the iterations of the loop(s)
@@ -501,11 +411,6 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
}
```
- The `linear_step_vars` operand additionally specifies the step for each
- associated linear operand. Note that the `linear_vars` and
- `linear_step_vars` variadic lists should contain the same number of
- elements.
-
Reductions can be performed in a worksharing-loop by specifying reduction
accumulator variables in `reduction_vars` and symbols referring to reduction
declarations in the `reductions` attribute. Each reduction is identified
@@ -516,55 +421,18 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
iteration into the final value, which is available in the accumulator after
the loop completes.
- The optional `schedule_val` attribute specifies the loop schedule for this
- loop, determining how the loop is distributed across the parallel threads.
- The optional `schedule_chunk_var` associated with this determines further
- controls this distribution.
-
- Collapsed loops are represented by the worksharing-loop having a list of
- indices, bounds and steps where the size of the list is equal to the
- collapse value.
-
- The `nowait` attribute, when present, signifies that there should be no
- implicit barrier at the e...
[truncated]
|
e1aa6cb
to
7466061
Compare
6fb9989
to
b43c823
Compare
@tblah thanks for giving this a look. Basically the issue here with the reduction clause is that its description is currently different for each operation that accepts it. They are generally quite similar, just not the same. I think the clause is already consistent in terms of how it's represented but what it means is slightly different depending on the operation, hence the variations in their way of describing it. If you look at the It would be great to agree on a generic description for that clause that would work for all ops, so that it makes sense while reading the generated documentation and also being centralized into the clause definition rather than each operation. I created a gist here with the whole list of descriptions that currently exist for |
Thanks for taking the time to create the gist. Some thoughts
I guess fixing byref is on me (#92244). Unfortunately I can't work on this immediately so I won't hold up this PR for it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but please wait for another reviewer
Edit: and CI is red
7466061
to
1496299
Compare
b43c823
to
2a089ad
Compare
Quick update about reduction clause descriptions @tblah: I updated the previous PR on the stack (#92521) to add a shared description that basically incorporates all of the information that was spread across the various operations using it. I updated the description of Also, it's expected that this PR breaks buildbots because of some small reordering of operation arguments and assembly format normalization. The next PR in the stack (#92524) addresses this. |
Thank you for the heads-up, that certainly helps. My plan is to update the PR stack after yours and one or two other PRs that conflict with this change land and hopefully by then all patches in this stack should be reviewed/approved to be merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with the patch. Thanks for the good work :)
1496299
to
0e0d66e
Compare
2a089ad
to
b0c7acd
Compare
This patch adds a new tablegen file for the OpenMP dialect containing the list of clauses currently supported.
0e0d66e
to
bd17957
Compare
This patch updates `OpenMP_Op` definitions to be based on the new set of `OpenMP_Clause` definitions, and to take advantage of clause-based automatically-generated argument lists, descriptions, assembly format and class declarations. There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen `OpenMP_Clause` definitions in the future. As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the `map` clause are updated, so that they are able to handle `map` clauses linked to entry block arguments as well as those which aren't. Printer and parser of reduction-related clauses are updated as well to add support for `byref` information to all operations, unifying the representation of reductions for all operations.
b0c7acd
to
f66b88b
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/157/builds/1431 Here is the relevant piece of the build log for the reference:
|
This patch updates `OpenMP_Op` definitions to be based on the new set of `OpenMP_Clause` definitions, and to take advantage of clause-based automatically-generated argument lists, descriptions, assembly format and class declarations. There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen `OpenMP_Clause` definitions in the future. As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the `map` clause are updated, so that they are able to handle `map` clauses linked to entry block arguments as well as those which aren't. This PR causes a build failure in the flang subproject. This is addressed by the next PR in the stack.
This patch updates `OpenMP_Op` definitions to be based on the new set of `OpenMP_Clause` definitions, and to take advantage of clause-based automatically-generated argument lists, descriptions, assembly format and class declarations. There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen `OpenMP_Clause` definitions in the future. As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed. The printer and parser functions for the `map` clause are updated, so that they are able to handle `map` clauses linked to entry block arguments as well as those which aren't. This PR causes a build failure in the flang subproject. This is addressed by the next PR in the stack.
This patch updates
OpenMP_Op
definitions to be based on the new set ofOpenMP_Clause
definitions, and to take advantage of clause-based automatically-generated argument lists, descriptions, assembly format and class declarations.There are also changes introduced to the clause operands structures to match the current set of tablegen clause definitions. These two are very closely linked and should be kept in sync. It would probably be a good idea to try generating clause operands structures from the tablegen
OpenMP_Clause
definitions in the future.As a result of this change, arguments for some operations have been reordered. This patch also addresses this by updating affected operation build calls and unit tests. Some other updates to tests related to the order of arguments in the resulting assembly format and others due to certain previous inconsistencies in the printing/parsing of clauses are addressed.
The printer and parser functions for the
map
clause are updated, so that they are able to handlemap
clauses linked to entry block arguments as well as those which aren't.