diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h index 386f9f3dcb689..e4955fec80b4f 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 allocatorVars, allocateVars; }; +struct CancelDirectiveNameClauseOps { + ClauseCancellationConstructTypeAttr cancelDirectiveNameAttr; +}; + struct CollapseClauseOps { llvm::SmallVector loopLBVar, loopUBVar, loopStepVar; }; @@ -48,6 +52,10 @@ struct CopyprivateClauseOps { llvm::SmallVector copyprivateFuncs; }; +struct CriticalNameClauseOps { + StringAttr criticalNameAttr; +}; + struct DependClauseOps { llvm::SmallVector dependTypeAttrs; llvm::SmallVector dependVars; @@ -84,6 +92,7 @@ struct GrainsizeClauseOps { struct HasDeviceAddrClauseOps { llvm::SmallVector hasDeviceAddrVars; }; + struct HintClauseOps { IntegerAttr hintAttr; }; @@ -118,10 +127,6 @@ struct MergeableClauseOps { UnitAttr mergeableAttr; }; -struct NameClauseOps { - StringAttr nameAttr; -}; - struct NogroupClauseOps { UnitAttr nogroupAttr; }; @@ -212,8 +217,12 @@ struct UntiedClauseOps { UnitAttr untiedAttr; }; -struct UseDeviceClauseOps { - llvm::SmallVector useDevicePtrVars, useDeviceAddrVars; +struct UseDeviceAddrClauseOps { + llvm::SmallVector useDeviceAddrVars; +}; + +struct UseDevicePtrClauseOps { + llvm::SmallVector useDevicePtrVars; }; //===----------------------------------------------------------------------===// @@ -228,7 +237,13 @@ template struct Clauses : public Mixins... {}; } // namespace detail -using CriticalClauseOps = detail::Clauses; +using CancelClauseOps = + detail::Clauses; + +using CancellationPointClauseOps = + detail::Clauses; + +using CriticalClauseOps = detail::Clauses; // TODO `indirect` clause. using DeclareTargetClauseOps = detail::Clauses; @@ -267,10 +282,11 @@ using TargetClauseOps = detail::Clauses; + PrivateClauseOps, ThreadLimitClauseOps>; -using TargetDataClauseOps = detail::Clauses; +using TargetDataClauseOps = + detail::Clauses; using TargetEnterExitUpdateDataClauseOps = detail::Clauses : OpenMP_Clause { + let arguments = (ins + Variadic:$aligned_vars, + OptionalAttr:$alignment_values + ); + + let assemblyFormat = [{ + `aligned` `(` custom($aligned_vars, type($aligned_vars), + $alignment_values) `)` + }]; + + let description = [{ + The `alignment_values` attribute additionally specifies alignment of each + corresponding aligned operand. Note that `aligned_vars` and + `alignment_values` should contain the same number of elements. + }]; +} + +def OpenMP_AlignedClause : OpenMP_AlignedClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [6.6] `allocate` clause +//===----------------------------------------------------------------------===// + +class OpenMP_AllocateClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$allocate_vars, + Variadic:$allocators_vars + ); + + let extraClassDeclaration = [{ + unsigned getNumAllocateVars() { return getAllocateVars().size(); } + unsigned getNumAllocatorsVars() { return getAllocatorsVars().size(); } + }]; + + let assemblyFormat = [{ + `allocate` `(` + custom($allocate_vars, type($allocate_vars), + $allocators_vars, type($allocators_vars)) `)` + }]; + + let description = [{ + 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. + }]; +} + +def OpenMP_AllocateClause : OpenMP_AllocateClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [16.1, 16.2] `cancel-directive-name` clause set +//===----------------------------------------------------------------------===// + +class OpenMP_CancelDirectiveNameClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + CancellationConstructTypeAttr:$cancellation_construct_type_val + ); + + let assemblyFormat = [{ + `cancellation_construct_type` `(` + custom($cancellation_construct_type_val) `)` + }]; + + // TODO: Add description. +} + +def OpenMP_CancelDirectiveNameClause : OpenMP_CancelDirectiveNameClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [4.4.3] `collapse` clause +//===----------------------------------------------------------------------===// + +class OpenMP_CollapseClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let traits = [ + AllTypesMatch<["lowerBound", "upperBound", "step"]> + ]; + + let arguments = (ins + Variadic:$lowerBound, + Variadic:$upperBound, + Variadic:$step + ); + + let extraClassDeclaration = [{ + /// Returns the number of loops in the loop nest. + unsigned getNumLoops() { return getLowerBound().size(); } + }]; + + // Description and formatting integrated in the `omp.loop_nest` operation, + // which is the only one currently accepting this clause. +} + +def OpenMP_CollapseClause : OpenMP_CollapseClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.7.2] `copyprivate` clause +//===----------------------------------------------------------------------===// + +class OpenMP_CopyprivateClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$copyprivate_vars, + OptionalAttr:$copyprivate_funcs + ); + + let assemblyFormat = [{ + `copyprivate` `(` + custom($copyprivate_vars, type($copyprivate_vars), + $copyprivate_funcs) `)` + }]; + + let description = [{ + 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. + }]; +} + +def OpenMP_CopyprivateClause : OpenMP_CopyprivateClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.2] `critical` `name` argument +//===----------------------------------------------------------------------===// + +class OpenMP_CriticalNameClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + SymbolNameAttr:$sym_name + ); + + let assemblyFormat = "$sym_name"; + + let description = [{ + The `sym_name` can be used in `omp.critical` constructs in the dialect. + }]; +} + +def OpenMP_CriticalNameClause : OpenMP_CriticalNameClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.9.5] `depend` clause +//===----------------------------------------------------------------------===// + +class OpenMP_DependClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$depends, + Variadic:$depend_vars + ); + + let assemblyFormat = [{ + `depend` `(` + custom($depend_vars, type($depend_vars), $depends) `)` + }]; + + let description = [{ + The `depends` and `depend_vars` arguments are variadic lists of values that + specify the dependencies of this particular task in relation to other tasks. + }]; +} + +def OpenMP_DependClause : OpenMP_DependClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [13.2] `device` clause +//===----------------------------------------------------------------------===// + +class OpenMP_DeviceClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$device + ); + + let assemblyFormat = [{ + `device` `(` $device `:` type($device) `)` + }]; + + let description = [{ + The optional `device` parameter specifies the device number for the target + region. + }]; +} + +def OpenMP_DeviceClause : OpenMP_DeviceClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [11.6.1] `dist_schedule` clause +//===----------------------------------------------------------------------===// + +class OpenMP_DistScheduleClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$dist_schedule_static, + Optional:$chunk_size + ); + + let assemblyFormat = [{ + `dist_schedule_static` $dist_schedule_static + | `chunk_size` `(` $chunk_size `:` type($chunk_size) `)` + }]; + + let description = [{ + The `dist_schedule_static` attribute specifies the schedule for this loop, + determining how the loop is distributed across the various teams. The + optional `chunk_size` associated with this determines further controls this + distribution. + }]; +} + +def OpenMP_DistScheduleClause : OpenMP_DistScheduleClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.9.6] `doacross` clause +//===----------------------------------------------------------------------===// + +class OpenMP_DoacrossClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$depend_type_val, + ConfinedAttr, [IntMinValue<0>]>:$num_loops_val, + Variadic:$depend_vec_vars + ); + + let assemblyFormat = [{ + ( `depend_type` `` $depend_type_val^ )? + ( `depend_vec` `(` $depend_vec_vars^ `:` type($depend_vec_vars) `)` )? + }]; + + let description = [{ + The `depend_type_val` attribute refers to either the DEPEND(SOURCE) clause + or the DEPEND(SINK: vec) clause. + + The `num_loops_val` attribute specifies the number of loops in the doacross + nest. + + The `depend_vec_vars` is a variadic list of operands that specifies the + index of the loop iterator in the doacross nest for the DEPEND(SOURCE) + clause or the index of the element of "vec" for the DEPEND(SINK: vec) + clause. It contains the operands in multiple "vec" when multiple + DEPEND(SINK: vec) clauses exist in one ORDERED directive. + }]; +} + +def OpenMP_DoacrossClause : OpenMP_DoacrossClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.3] `final` clause +//===----------------------------------------------------------------------===// + +class OpenMP_FinalClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$final_expr + ); + + let assemblyFormat = [{ + `final` `(` $final_expr `)` + }]; + + let description = [{ + When a `final` clause is present and the `final` clause expression evaluates + to `true`, the generated tasks will be final tasks. All task constructs + encountered during execution of a final task will generate final and + included tasks. The use of a variable in a `final` clause expression causes + an implicit reference to the variable in all enclosing constructs. + }]; +} + +def OpenMP_FinalClause : OpenMP_FinalClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.6.1] `grainsize` clause +//===----------------------------------------------------------------------===// + +class OpenMP_GrainsizeClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$grain_size + ); + + let assemblyFormat = [{ + `grain_size` `(` $grain_size `:` type($grain_size) `)` + }]; + + let description = [{ + If a `grainsize` clause is present, the number of logical loop iterations + assigned to each generated task is greater than or equal to the minimum of + the value of the grain-size expression and the number of logical loop + iterations, but less than two times the value of the grain-size expression. + }]; +} + +def OpenMP_GrainsizeClause : OpenMP_GrainsizeClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.9] `has_device_addr` clause +//===----------------------------------------------------------------------===// + +class OpenMP_HasDeviceAddrClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$has_device_addr + ); + + let assemblyFormat = [{ + `has_device_addr` `(` $has_device_addr `:` type($has_device_addr) `)` + }]; + + let description = [{ + The optional `has_device_addr` indicates that list items already have device + addresses, so they may be directly accessed from the target device. This + includes array sections. + }]; +} + +def OpenMP_HasDeviceAddrClause : OpenMP_HasDeviceAddrClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.1.2] `hint` clause +//===----------------------------------------------------------------------===// + +class OpenMP_HintClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + DefaultValuedOptionalAttr:$hint_val + ); + + let assemblyFormat = [{ + `hint` `(` custom($hint_val) `)` + }]; + + let description = [{ + `hint` is the value of hint (as specified in the hint clause). It is a + compile time constant. As the name suggests, this is just a hint for + optimization. + }]; +} + +def OpenMP_HintClause : OpenMP_HintClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [3.4] `if` clause +//===----------------------------------------------------------------------===// + +class OpenMP_IfClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$if_expr + ); + + let assemblyFormat = [{ + `if` `(` $if_expr `)` + }]; + + // Description varies depending on the operation. +} + +def OpenMP_IfClause : OpenMP_IfClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.5.10] `in_reduction` clause +//===----------------------------------------------------------------------===// + +class OpenMP_InReductionClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let traits = [ + ReductionClauseInterface + ]; + + let arguments = (ins + Variadic:$in_reduction_vars, + OptionalAttr:$in_reduction_vars_byref, + OptionalAttr:$in_reductions + ); + + let assemblyFormat = [{ + `in_reduction` `(` + custom($in_reduction_vars, type($in_reduction_vars), + $in_reduction_vars_byref, $in_reductions) `)` + }]; + + let extraClassDeclaration = [{ + /// Returns the reduction variables. + SmallVector getReductionVars() { + return SmallVector(getInReductionVars().begin(), + getInReductionVars().end()); + } + }]; + + // Description varies depending on the operation. +} + +def OpenMP_InReductionClause : OpenMP_InReductionClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.7] `is_device_ptr` clause +//===----------------------------------------------------------------------===// + +class OpenMP_IsDevicePtrClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$is_device_ptr + ); + + let assemblyFormat = [{ + `is_device_ptr` `(` $is_device_ptr `:` type($is_device_ptr) `)` + }]; + + let description = [{ + The optional `is_device_ptr` indicates list items are device pointers. + }]; +} + +def OpenMP_IsDevicePtrClause : OpenMP_IsDevicePtrClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.6] `linear` clause +//===----------------------------------------------------------------------===// + +class OpenMP_LinearClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$linear_vars, + Variadic:$linear_step_vars + ); + + let assemblyFormat = [{ + `linear` `(` + custom($linear_vars, type($linear_vars), + $linear_step_vars) `)` + }]; + + let description = [{ + 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. + }]; +} + +def OpenMP_LinearClause : OpenMP_LinearClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.8.3] `map` clause +//===----------------------------------------------------------------------===// + +class OpenMP_MapClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let traits = [ + MapClauseOwningOpInterface + ]; + + let arguments = (ins + Variadic:$map_operands + ); + + let assemblyFormat = [{ + `map_entries` `(` custom($map_operands, type($map_operands)) `)` + }]; + + let description = [{ + The optional `map_operands` maps data from the current task's data + environment to the device data environment. + }]; +} + +def OpenMP_MapClause : OpenMP_MapClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.8.1] `memory-order` clause set +//===----------------------------------------------------------------------===// + +class OpenMP_MemoryOrderClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$memory_order_val + ); + + let assemblyFormat = [{ + `memory_order` `(` custom($memory_order_val) `)` + }]; + + let description = [{ + `memory_order` indicates the memory ordering behavior of the construct. It + can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`. + }]; +} + +def OpenMP_MemoryOrderClause : OpenMP_MemoryOrderClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.2] `mergeable` clause +//===----------------------------------------------------------------------===// + +class OpenMP_MergeableClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$mergeable + ); + + let assemblyFormat = [{ + `mergeable` $mergeable + }]; + + let description = [{ + When the `mergeable` clause is present, the tasks generated by the construct + are "mergeable tasks". + }]; +} + +def OpenMP_MergeableClause : OpenMP_MergeableClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.7] `nogroup` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NogroupClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$nogroup + ); + + let assemblyFormat = [{ + `nogroup` $nogroup + }]; + + let description = [{ + By default, the taskloop construct executes as if it was enclosed in a + taskgroup construct with no statements or directives outside of the taskloop + construct. Thus, the taskloop construct creates an implicit taskgroup + region. If the `nogroup` clause is present, no implicit taskgroup region is + created. + }]; +} + +def OpenMP_NogroupClause : OpenMP_NogroupClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.4.1] `nontemporal` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NontemporalClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$nontemporal_vars + ); + + let assemblyFormat = [{ + `nontemporal` `(` $nontemporal_vars `:` type($nontemporal_vars) `)` + }]; + + let description = [{ + The optional `nontemporal` attribute specifies variables which have low + temporal locality across the iterations where they are accessed. + }]; +} + +def OpenMP_NontemporalClause : OpenMP_NontemporalClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.6] `nowait` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NowaitClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$nowait + ); + + let assemblyFormat = [{ + `nowait` $nowait + }]; + + let description = [{ + The optional `nowait` attribute, when present, eliminates the implicit + barrier at the end of the construct, so the parent operation can make + progress even if the child operation has not completed yet. + }]; +} + +def OpenMP_NowaitClause : OpenMP_NowaitClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.6.2] `num_tasks` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NumTasksClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$num_tasks + ); + + let assemblyFormat = [{ + `num_tasks` `(` $num_tasks `:` type($num_tasks) `)` + }]; + + let description = [{ + If `num_tasks` is specified, the taskloop construct creates as many tasks as + the minimum of the num-tasks expression and the number of logical loop + iterations. Each task must have at least one logical loop iteration. + }]; +} + +def OpenMP_NumTasksClause : OpenMP_NumTasksClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.2.1] `num_teams` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NumTeamsClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$num_teams_lower, + Optional:$num_teams_upper + ); + + let assemblyFormat = [{ + `num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to` + $num_teams_upper `:` type($num_teams_upper) `)` + }]; + + let description = [{ + The optional `num_teams_upper` and `num_teams_lower` arguments 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 allowed 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. + }]; +} + +def OpenMP_NumTeamsClause : OpenMP_NumTeamsClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.1.2] `num_threads` clause +//===----------------------------------------------------------------------===// + +class OpenMP_NumThreadsClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$num_threads_var + ); + + let assemblyFormat = [{ + `num_threads` `(` $num_threads_var `:` type($num_threads_var) `)` + }]; + + let description = [{ + The optional `num_threads_var` parameter specifies the number of threads + which should be used to execute the parallel region. + }]; +} + +def OpenMP_NumThreadsClause : OpenMP_NumThreadsClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.3] `order` clause +//===----------------------------------------------------------------------===// + +class OpenMP_OrderClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$order_val, + OptionalAttr:$order_mod + ); + + let assemblyFormat = [{ + `order` `(` custom($order_val, $order_mod) `)` + }]; + + let description = [{ + The optional `order` attribute specifies which order the iterations of the + associated loops are executed in. Currently the only option for this + attribute is "concurrent". + }]; +} + +def OpenMP_OrderClause : OpenMP_OrderClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [4.4.4] `ordered` clause +//===----------------------------------------------------------------------===// + +class OpenMP_OrderedClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + ConfinedAttr, [IntMinValue<0>]>:$ordered_val + ); + + let assemblyFormat = [{ + `ordered` `(` $ordered_val `)` + }]; + + let description = [{ + The optional `ordered_val` attribute specifies how many loops are associated + with the worksharing-loop construct. The value of zero refers to the ordered + clause specified without parameter. + }]; +} + +def OpenMP_OrderedClause : OpenMP_OrderedClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [15.10.3] `parallelization-level` clause set +//===----------------------------------------------------------------------===// + +class OpenMP_ParallelizationLevelClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$simd + ); + + let assemblyFormat = [{ + `simd` $simd + }]; + + let description = [{ + The `simd` attribute corresponds to the simd clause specified. If it is not + present, it behaves as if the threads clause is specified or no clause is + specified. + }]; +} + +def OpenMP_ParallelizationLevelClause : OpenMP_ParallelizationLevelClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.4] `priority` clause +//===----------------------------------------------------------------------===// + +class OpenMP_PriorityClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$priority + ); + + let assemblyFormat = [{ + `priority` `(` $priority `:` type($priority) `)` + }]; + + let description = [{ + The `priority` clause is a hint for the priority of the generated tasks. + The `priority` is a non-negative integer expression that provides a hint for + task execution order. Among all tasks ready to be executed, higher priority + tasks (those with a higher numerical value in the priority clause + expression) are recommended to execute before lower priority ones. The + default priority-value when no priority clause is specified should be + assumed to be zero (the lowest priority). + }]; +} + +def OpenMP_PriorityClause : OpenMP_PriorityClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.3, 5.4.4, 5.4.5] `private`, `firstprivate`, `lastprivate` clauses +//===----------------------------------------------------------------------===// + +class OpenMP_PrivateClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$private_vars, + OptionalAttr:$privatizers + ); + + let assemblyFormat = [{ + `private` `(` + custom($private_vars, type($private_vars), $privatizers) `)` + }]; + + // TODO: Add description. +} + +def OpenMP_PrivateClause : OpenMP_PrivateClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.1.4] `proc_bind` clause +//===----------------------------------------------------------------------===// + +class OpenMP_ProcBindClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$proc_bind_val + ); + + let assemblyFormat = [{ + `proc_bind` `(` custom($proc_bind_val) `)` + }]; + + let description = [{ + The optional `proc_bind_val` attribute controls the thread affinity for the + execution of the parallel region. + }]; +} + +def OpenMP_ProcBindClause : OpenMP_ProcBindClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.5.8] `reduction` clause +//===----------------------------------------------------------------------===// + +class OpenMP_ReductionClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let traits = [ + ReductionClauseInterface + ]; + + let arguments = (ins + Variadic:$reduction_vars, + OptionalAttr:$reduction_vars_byref, + OptionalAttr:$reductions + ); + + let assemblyFormat = [{ + `reduction` `(` + custom($reduction_vars, type($reduction_vars), + $reduction_vars_byref, $reductions) `)` + }]; + + let extraClassDeclaration = [{ + /// Returns the number of reduction variables. + unsigned getNumReductionVars() { return getReductionVars().size(); } + }]; + + // Description varies depending on the operation. + let description = [{ + Reductions can be performed by specifying reduction accumulator variables in + `reduction_vars`, symbols referring to reduction declarations in the + `reductions` attribute, and whether the reduction variable should be passed + into the reduction region by value or by reference in + `reduction_vars_byref`. Each reduction is identified by the accumulator it + uses and accumulators must not be repeated in the same reduction. A private + variable corresponding to the accumulator is used in place of the + accumulator inside the body of the operation. The reduction declaration + specifies how to combine the values from each iteration, section, team, + thread or simd lane defined by the operation's region into the final value, + which is available in the accumulator after they all complete. + }]; +} + +def OpenMP_ReductionClause : OpenMP_ReductionClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.4.2] `safelen` clause +//===----------------------------------------------------------------------===// + +class OpenMP_SafelenClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + ConfinedAttr, [IntPositive]>:$safelen + ); + + let assemblyFormat = [{ + `safelen` `(` $safelen `)` + }]; + + let description = [{ + The `safelen` clause specifies that no two concurrent iterations within a + SIMD chunk can have a distance in the logical iteration space that is + greater than or equal to the value given in the clause. + }]; +} + +def OpenMP_SafelenClause : OpenMP_SafelenClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [11.5.3] `schedule` clause +//===----------------------------------------------------------------------===// + +class OpenMP_ScheduleClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + OptionalAttr:$schedule_val, + Optional:$schedule_chunk_var, + OptionalAttr:$schedule_modifier, + UnitAttr:$simd_modifier + ); + + let assemblyFormat = [{ + `schedule` `(` + custom($schedule_val, $schedule_modifier, $simd_modifier, + $schedule_chunk_var, type($schedule_chunk_var)) `)` + }]; + + let description = [{ + 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. + }]; +} + +def OpenMP_ScheduleClause : OpenMP_ScheduleClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [10.4.3] `simdlen` clause +//===----------------------------------------------------------------------===// + +class OpenMP_SimdlenClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + ConfinedAttr, [IntPositive]>:$simdlen + ); + + let assemblyFormat = [{ + `simdlen` `(` $simdlen `)` + }]; + + let description = [{ + When a `simdlen` clause is present, the preferred number of iterations to be + executed concurrently is the value provided to the `simdlen` clause. + }]; +} + +def OpenMP_SimdlenClause : OpenMP_SimdlenClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.5.9] `task_reduction` clause +//===----------------------------------------------------------------------===// + +class OpenMP_TaskReductionClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let traits = [ + ReductionClauseInterface + ]; + + let arguments = (ins + Variadic:$task_reduction_vars, + OptionalAttr:$task_reduction_vars_byref, + OptionalAttr:$task_reductions + ); + + let assemblyFormat = [{ + `task_reduction` `(` + custom($task_reduction_vars, type($task_reduction_vars), + $task_reduction_vars_byref, $task_reductions) `)` + }]; + + let description = [{ + The `task_reduction` clause specifies a reduction among tasks. For each list + item, the number of copies is unspecified. Any copies associated with the + reduction are initialized before they are accessed by the tasks + participating in the reduction. After the end of the region, the original + list item contains the result of the reduction. Similarly to the `reduction` + clause, accumulator variables must be passed in `task_reduction_vars`, + symbols referring to reduction declarations in the `task_reductions` + attribute, and whether the reduction variable should be passed into the + reduction region by value or by reference in `task_reduction_vars_byref`. + }]; + + let extraClassDeclaration = [{ + /// Returns the reduction variables. + SmallVector getReductionVars() { + return SmallVector(getTaskReductionVars().begin(), + getTaskReductionVars().end()); + } + }]; +} + +def OpenMP_TaskReductionClause : OpenMP_TaskReductionClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [13.3] `thread_limit` clause +//===----------------------------------------------------------------------===// + +class OpenMP_ThreadLimitClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Optional:$thread_limit + ); + + let assemblyFormat = [{ + `thread_limit` `(` $thread_limit `:` type($thread_limit) `)` + }]; + + let description = [{ + The optional `thread_limit` specifies the limit on the number of threads. + }]; +} + +def OpenMP_ThreadLimitClause : OpenMP_ThreadLimitClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [12.1] `untied` clause +//===----------------------------------------------------------------------===// + +class OpenMP_UntiedClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + UnitAttr:$untied + ); + + let assemblyFormat = [{ + `untied` $untied + }]; + + let description = [{ + If the `untied` clause is present on a task construct, any thread in the + team can resume the task region after a suspension. The `untied` clause is + ignored if a `final` clause is present on the same task construct and the + `final_expr` evaluates to `true`, or if a task is an included task. + }]; +} + +def OpenMP_UntiedClause : OpenMP_UntiedClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.10] `use_device_addr` clause +//===----------------------------------------------------------------------===// + +class OpenMP_UseDeviceAddrClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$use_device_addr + ); + + let assemblyFormat = [{ + `use_device_addr` `(` $use_device_addr `:` type($use_device_addr) `)` + }]; + + let description = [{ + The optional `use_device_addr` specifies the address of the objects in the + device data environment. + }]; +} + +def OpenMP_UseDeviceAddrClause : OpenMP_UseDeviceAddrClauseSkip<>; + +//===----------------------------------------------------------------------===// +// V5.2: [5.4.8] `use_device_ptr` clause +//===----------------------------------------------------------------------===// + +class OpenMP_UseDevicePtrClauseSkip< + bit traits = false, bit arguments = false, bit assemblyFormat = false, + bit description = false, bit extraClassDeclaration = false + > : OpenMP_Clause { + let arguments = (ins + Variadic:$use_device_ptr + ); + + let assemblyFormat = [{ + `use_device_ptr` `(` $use_device_ptr `:` type($use_device_ptr) `)` + }]; + + let description = [{ + The optional `use_device_ptr` specifies the device pointers to the + corresponding list items in the device data environment. + }]; +} + +def OpenMP_UseDevicePtrClause : OpenMP_UseDevicePtrClauseSkip<>; + +#endif // OPENMP_CLAUSES diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index bba8a29a5599a..99e14cd1b7b48 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -17,7 +17,7 @@ include "mlir/Dialect/LLVMIR/LLVMOpBase.td" include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td" include "mlir/Dialect/OpenACCMPCommon/Interfaces/OpenACCMPOpsInterfaces.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,69 +126,38 @@ def PrivateClauseOp : OpenMP_Op<"private", [IsolatedFromAbove, RecipeInterface]> // 2.6 parallel Construct //===----------------------------------------------------------------------===// -def ParallelOp : OpenMP_Op<"parallel", [ - AutomaticAllocationScope, AttrSizedOperandSegments, - DeclareOpInterfaceMethods, - DeclareOpInterfaceMethods, - RecursiveMemoryEffects, ReductionClauseInterface]> { +def ParallelOp : OpenMP_Op<"parallel", traits = [ + AttrSizedOperandSegments, AutomaticAllocationScope, + DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, + RecursiveMemoryEffects + ], clauses = [ + // 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`, symbols referring to reduction - declarations in the `reductions` attribute, and whether the reduction - variable should be passed into the reduction region by value or by reference - in `reduction_vars_byref`. Each reduction is identified by the accumulator - it uses and accumulators must not be repeated in the same reduction. The - reduction declaration specifies how to combine the values from each thread - 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. - }]; - - let arguments = (ins Optional:$if_expr_var, - Optional:$num_threads_var, - Variadic:$allocate_vars, - Variadic:$allocators_vars, - Variadic:$reduction_vars, - OptionalAttr:$reduction_vars_byref, - OptionalAttr:$reductions, - OptionalAttr:$proc_bind_val, - Variadic:$private_vars, - OptionalAttr:$privatizers); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"ArrayRef", "{}">:$attributes)>, OpBuilder<(ins CArg<"const ParallelClauseOps &">:$clauses)> ]; - let extraClassDeclaration = [{ - unsigned getNumAllocateVars() { return getAllocateVars().size(); } - - unsigned getNumAllocatorsVars() { return getAllocatorsVars().size(); } - /// Returns the number of reduction variables. - unsigned getNumReductionVars() { return getReductionVars().size(); } - }]; + // TODO: Use default assembly format inherited from OpenMP_Op once 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( @@ -200,6 +169,7 @@ def ParallelOp : OpenMP_Op<"parallel", [ $reduction_vars_byref, $reductions, $private_vars, type($private_vars), $privatizers) attr-dict }]; + let hasVerifier = 1; } @@ -218,65 +188,28 @@ def TerminatorOp : OpenMP_Op<"terminator", [Terminator, Pure]> { //===----------------------------------------------------------------------===// // 2.7 teams Construct //===----------------------------------------------------------------------===// -def TeamsOp : OpenMP_Op<"teams", [ - AttrSizedOperandSegments, RecursiveMemoryEffects, - ReductionClauseInterface]> { +def TeamsOp : OpenMP_Op<"teams", traits = [ + AttrSizedOperandSegments, RecursiveMemoryEffects + ], clauses = [ + // 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:$num_teams_lower, - Optional:$num_teams_upper, - Optional:$if_expr, - Optional:$thread_limit, - Variadic:$allocate_vars, - Variadic:$allocators_vars, - Variadic:$reduction_vars, - OptionalAttr:$reduction_vars_byref, - OptionalAttr:$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( - $reduction_vars, type($reduction_vars), $reduction_vars_byref, - $reductions ) `)` - | `allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - ) $region attr-dict - }]; - let hasVerifier = 1; } @@ -284,19 +217,24 @@ 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", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // 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 @@ -304,51 +242,15 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments, distributed among and executed by the threads in a team. Each `omp.section` is executed once by one of the threads in the team in the context of its implicit task. + }] # clausesDescription; - Reductions can be performed in a sections construct by specifying reduction - accumulator variables in `reduction_vars` and symbols referring to reduction - declarations in the `reductions` attribute. Each reduction is identified - by the accumulator it uses and accumulators must not be repeated in the same - reduction. The reduction declaration specifies how to combine the values - from each section into the final value, which is available in the - accumulator after all the sections complete. True values in - reduction_vars_byref indicate that the reduction variable should be passed - by reference. - - 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:$reduction_vars, - OptionalAttr:$reduction_vars_byref, - OptionalAttr:$reductions, - Variadic:$allocate_vars, - Variadic:$allocators_vars, - UnitAttr:$nowait); - + // Override region definition. let regions = (region SizedRegion<1>:$region); let builders = [ OpBuilder<(ins CArg<"const SectionsClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist( `reduction` `(` - custom( - $reduction_vars, type($reduction_vars), $reduction_vars_byref, - $reductions - ) `)` - | `allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - | `nowait` $nowait - ) $region attr-dict - }]; - let hasVerifier = 1; let hasRegionVerifier = 1; } @@ -357,45 +259,25 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments, // 2.8.2 Single Construct //===----------------------------------------------------------------------===// -def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> { +def SingleOp : OpenMP_Op<"single", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // 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:$allocate_vars, - Variadic:$allocators_vars, - Variadic:$copyprivate_vars, - OptionalAttr:$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( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - |`nowait` $nowait - |`copyprivate` `(` - custom( - $copyprivate_vars, type($copyprivate_vars), $copyprivate_funcs - ) `)` - ) $region attr-dict - }]; let hasVerifier = 1; } @@ -403,9 +285,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", traits = [ + RecursiveMemoryEffects, SameVariadicOperandSize + ], clauses = [ + OpenMP_CollapseClause + ], singleRegion = true> { let summary = "rectangular loop nest"; let description = [{ This operation represents a collapsed rectangular loop nest. For each @@ -442,29 +326,24 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize, non-perfectly nested loops. }]; - let arguments = (ins Variadic:$lowerBound, - Variadic:$upperBound, - Variadic:$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 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 &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 +352,15 @@ def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize, // 2.9.2 Workshare Loop Construct //===----------------------------------------------------------------------===// -def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, - DeclareOpInterfaceMethods, - RecursiveMemoryEffects, ReductionClauseInterface, - SingleBlockImplicitTerminator<"TerminatorOp">]> { +def WsloopOp : OpenMP_Op<"wsloop", traits = [ + AttrSizedOperandSegments, DeclareOpInterfaceMethods, + RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp"> + ], clauses = [ + // 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) @@ -500,70 +384,16 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, omp.terminator } ``` - - 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`, symbols referring to reduction - declarations in the `reductions` attribute, and whether the reduction - variable should be passed by reference or value in `reduction_vars_byref`. - Each reduction is identified by the accumulator it uses and accumulators - must not be repeated in the same reduction. A private variable corresponding - to the accumulator is used in place of the accumulator inside the body of - the worksharing-loop. The reduction declaration specifies how to combine the - values from each 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 end of the loop. - - The optional `ordered_val` attribute specifies how many loops are associated - with the worksharing-loop construct. The value of zero refers to the ordered - clause specified without parameter. - - The optional `order` attribute specifies which order the iterations of the - associate loops are executed in. Currently the only option for this - attribute is "concurrent". - }]; - - let arguments = (ins Variadic:$linear_vars, - Variadic:$linear_step_vars, - Variadic:$reduction_vars, - OptionalAttr:$reduction_vars_byref, - OptionalAttr:$reductions, - OptionalAttr:$schedule_val, - Optional:$schedule_chunk_var, - OptionalAttr:$schedule_modifier, - UnitAttr:$simd_modifier, - UnitAttr:$nowait, - ConfinedAttr, [IntMinValue<0>]>:$ordered_val, - OptionalAttr:$order_val, - OptionalAttr:$order_mod); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"ArrayRef", "{}">:$attributes)>, OpBuilder<(ins CArg<"const WsloopClauseOps &">:$clauses)> ]; - let regions = (region AnyRegion:$region); - - let extraClassDeclaration = [{ - /// Returns the number of reduction variables. - unsigned getNumReductionVars() { return getReductionVars().size(); } - }]; - let hasCustomAssemblyFormat = 1; + // TODO: Use default assembly format inherited from OpenMP_Op once printing + // and parsing of the workshare loop region is not intermingled with printing + // and parsing of reduction clauses. let assemblyFormat = [{ oilist(`linear` `(` custom($linear_vars, type($linear_vars), @@ -578,6 +408,7 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, ) custom($region, $reduction_vars, type($reduction_vars), $reduction_vars_byref, $reductions) attr-dict }]; + let hasVerifier = 1; } @@ -585,11 +416,15 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, // Simd construct [2.9.3.1] //===----------------------------------------------------------------------===// -def SimdOp : OpenMP_Op<"simd", [AttrSizedOperandSegments, - DeclareOpInterfaceMethods, - RecursiveMemoryEffects, - SingleBlockImplicitTerminator<"TerminatorOp">]> { - let summary = "simd construct"; +def SimdOp : OpenMP_Op<"simd", traits = [ + AttrSizedOperandSegments, DeclareOpInterfaceMethods, + RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp"> + ], clauses = [ + // TODO: Complete clause list (linear, private, reduction). + OpenMP_AlignedClause, OpenMP_IfClause, OpenMP_NontemporalClause, + OpenMP_OrderClause, OpenMP_SafelenClause, OpenMP_SimdlenClause + ], singleRegion = true> { + let summary = "simd construct"; let description = [{ The simd construct can be applied to a loop to indicate that the loop can be transformed into a SIMD loop (that is, multiple iterations of the loop can @@ -599,27 +434,6 @@ def SimdOp : OpenMP_Op<"simd", [AttrSizedOperandSegments, operation and a terminator. The operation must be another compatible loop wrapper or an `omp.loop_nest`. - The `alignment_values` attribute additionally specifies alignment of each - corresponding aligned operand. Note that `$aligned_vars` and - `alignment_values` should contain the same number of elements. - - When an if clause is present and evaluates to false, the preferred number of - iterations to be executed concurrently is one, regardless of whether - a simdlen clause is specified. - - The optional `nontemporal` attribute specifies variables which have low - temporal locality across the iterations where they are accessed. - - The optional `order` attribute specifies which order the iterations of the - associate loops are executed in. Currently the only option for this - attribute is "concurrent". - - When a simdlen clause is present, the preferred number of iterations to be - executed concurrently is the value provided to the simdlen clause. - - The safelen clause specifies that no two concurrent iterations within a - SIMD chunk can have a distance in the logical iteration space that is - greater than or equal to the value given in the clause. ``` omp.simd { omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) { @@ -632,38 +446,16 @@ def SimdOp : OpenMP_Op<"simd", [AttrSizedOperandSegments, omp.terminator } ``` - }]; - // TODO: Add other clauses - let arguments = (ins Variadic:$aligned_vars, - OptionalAttr:$alignment_values, - Optional:$if_expr, - Variadic:$nontemporal_vars, - OptionalAttr:$order_val, - OptionalAttr:$order_mod, - ConfinedAttr, [IntPositive]>:$simdlen, - ConfinedAttr, [IntPositive]>:$safelen - ); - - let regions = (region AnyRegion:$region); + When an if clause is present and evaluates to false, the preferred number of + iterations to be executed concurrently is one, regardless of whether + a simdlen clause is specified. + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const SimdClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`aligned` `(` - custom($aligned_vars, type($aligned_vars), - $alignment_values) `)` - |`if` `(` $if_expr `)` - |`nontemporal` `(` $nontemporal_vars `:` type($nontemporal_vars) `)` - |`order` `(` custom($order_val, $order_mod) `)` - |`simdlen` `(` $simdlen `)` - |`safelen` `(` $safelen `)` - ) $region attr-dict - }]; - - let hasCustomAssemblyFormat = 1; let hasVerifier = 1; } @@ -685,16 +477,20 @@ def YieldOp : OpenMP_Op<"yield", OpBuilder<(ins), [{ build($_builder, $_state, {}); }]> ]; - let assemblyFormat = [{ ( `(` $results^ `:` type($results) `)` )? attr-dict}]; + let assemblyFormat = "( `(` $results^ `:` type($results) `)` )? attr-dict"; } //===----------------------------------------------------------------------===// // Distribute construct [2.9.4.1] //===----------------------------------------------------------------------===// -def DistributeOp : OpenMP_Op<"distribute", [AttrSizedOperandSegments, - DeclareOpInterfaceMethods, - RecursiveMemoryEffects, - SingleBlockImplicitTerminator<"TerminatorOp">]> { +def DistributeOp : OpenMP_Op<"distribute", traits = [ + AttrSizedOperandSegments, DeclareOpInterfaceMethods, + RecursiveMemoryEffects, SingleBlockImplicitTerminator<"TerminatorOp"> + ], clauses = [ + // TODO: Complete clause list (private). + // TODO: Sort clauses alphabetically. + OpenMP_DistScheduleClause, OpenMP_AllocateClause, OpenMP_OrderClause + ], singleRegion = true> { let summary = "distribute construct"; let description = [{ The distribute construct specifies that the iterations of one or more loops @@ -715,11 +511,6 @@ def DistributeOp : OpenMP_Op<"distribute", [AttrSizedOperandSegments, operation and a terminator. The operation must be another compatible loop wrapper or an `omp.loop_nest`. - The `dist_schedule_static` attribute specifies the schedule for this - loop, determining how the loop is distributed across the parallel threads. - The optional `schedule_chunk` associated with this determines further - controls this distribution. - ```mlir omp.distribute { omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) { @@ -732,34 +523,12 @@ def DistributeOp : OpenMP_Op<"distribute", [AttrSizedOperandSegments, omp.terminator } ``` - // TODO: private_var, firstprivate_var, lastprivate_var, collapse - }]; - let arguments = (ins - UnitAttr:$dist_schedule_static, - Optional:$chunk_size, - Variadic:$allocate_vars, - Variadic:$allocators_vars, - OptionalAttr:$order_val, - OptionalAttr:$order_mod); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const DistributeClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`dist_schedule_static` $dist_schedule_static - |`chunk_size` `(` $chunk_size `:` type($chunk_size) `)` - |`order` `(` custom($order_val, $order_mod) `)` - |`allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - ) $region attr-dict - }]; - let hasVerifier = 1; } @@ -767,9 +536,16 @@ def DistributeOp : OpenMP_Op<"distribute", [AttrSizedOperandSegments, // 2.10.1 task Construct //===----------------------------------------------------------------------===// -def TaskOp : OpenMP_Op<"task", [AttrSizedOperandSegments, - OutlineableOpenMPOpInterface, AutomaticAllocationScope, - ReductionClauseInterface]> { +def TaskOp : OpenMP_Op<"task", traits = [ + AttrSizedOperandSegments, AutomaticAllocationScope, + OutlineableOpenMPOpInterface + ], clauses = [ + // TODO: Complete clause list (affinity, detach, private). + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_FinalClause, OpenMP_UntiedClause, + OpenMP_MergeableClause, OpenMP_InReductionClause, + OpenMP_PriorityClause, OpenMP_DependClause, OpenMP_AllocateClause + ], singleRegion = true> { let summary = "task construct"; let description = [{ The task construct defines an explicit task. @@ -783,96 +559,33 @@ def TaskOp : OpenMP_Op<"task", [AttrSizedOperandSegments, execution cannot be resumed until execution of the structured block that is associated with the generated task is completed. - When a `final` clause is present on a task construct and the `final_expr` - evaluates to `true`, the generated task will be a "final task". All task - constructs encountered during execution of a final task will generate final - and included tasks. - - If the `untied` clause is present on a task construct, any thread in the - team can resume the task region after a suspension. The `untied` clause is - ignored if a `final` clause is present on the same task construct and the - `final_expr` evaluates to `true`, or if a task is an included task. - - When the `mergeable` clause is present on a task construct, the generated - task is a "mergeable task". - The `in_reduction` clause specifies that this particular task (among all the tasks in current taskgroup, if any) participates in a reduction. `in_reduction_vars_byref` indicates whether each reduction variable should be passed by value or by reference. + }] # clausesDescription; - The `priority` clause is a hint for the priority of the generated task. - The `priority` is a non-negative integer expression that provides a hint for - task execution order. Among all tasks ready to be executed, higher priority - tasks (those with a higher numerical value in the priority clause - expression) are recommended to execute before lower priority ones. The - default priority-value when no priority clause is specified should be - assumed to be zero (the lowest priority). - - The `depends` and `depend_vars` arguments are variadic lists of values - that specify the dependencies of this particular task in relation to - other tasks. - - The `allocators_vars` and `allocate_vars` arguments are a variadic list of - values that specify the memory allocator to be used to obtain storage for - private values. - - }]; - - // TODO: depend, affinity and detach clauses - let arguments = (ins Optional:$if_expr, - Optional:$final_expr, - UnitAttr:$untied, - UnitAttr:$mergeable, - Variadic:$in_reduction_vars, - OptionalAttr:$in_reduction_vars_byref, - OptionalAttr:$in_reductions, - Optional:$priority, - OptionalAttr:$depends, - Variadic:$depend_vars, - Variadic:$allocate_vars, - Variadic:$allocators_vars); - let regions = (region AnyRegion:$region); let builders = [ OpBuilder<(ins CArg<"const TaskClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `)` - |`final` `(` $final_expr `)` - |`untied` $untied - |`mergeable` $mergeable - |`in_reduction` `(` - custom( - $in_reduction_vars, type($in_reduction_vars), - $in_reduction_vars_byref, $in_reductions - ) `)` - |`priority` `(` $priority `)` - |`allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - |`depend` `(` - custom( - $depend_vars, type($depend_vars), $depends - ) `)` - ) $region attr-dict - }]; - let extraClassDeclaration = [{ - /// Returns the reduction variables - SmallVector getReductionVars() { - return SmallVector(getInReductionVars().begin(), - getInReductionVars().end()); - } - }]; + let hasVerifier = 1; } -def TaskloopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, - AutomaticAllocationScope, - DeclareOpInterfaceMethods, - RecursiveMemoryEffects, ReductionClauseInterface, - SingleBlockImplicitTerminator<"TerminatorOp">]> { +def TaskloopOp : OpenMP_Op<"taskloop", traits = [ + AttrSizedOperandSegments, AutomaticAllocationScope, + DeclareOpInterfaceMethods, RecursiveMemoryEffects, + SingleBlockImplicitTerminator<"TerminatorOp"> + ], clauses = [ + // TODO: Complete clause list (private). + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_FinalClause, OpenMP_UntiedClause, + OpenMP_MergeableClause, + OpenMP_InReductionClauseSkip, + OpenMP_ReductionClauseSkip, + OpenMP_PriorityClause, OpenMP_AllocateClause, OpenMP_GrainsizeClause, + OpenMP_NumTasksClause, OpenMP_NogroupClause + ], singleRegion = true> { let summary = "taskloop construct"; let description = [{ The taskloop construct specifies that the iterations of one or more @@ -904,32 +617,16 @@ def TaskloopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, clause expression evaluates to `false`, undeferred tasks are generated. The use of a variable in an `if` clause expression of a taskloop construct causes an implicit reference to the variable in all enclosing constructs. - - When a `final` clause is present on a taskloop construct and the `final` - clause expression evaluates to `true`, the generated tasks will be final - tasks. The use of a variable in a `final` clause expression of a taskloop - construct causes an implicit reference to the variable in all enclosing - constructs. - - If the `untied` clause is specified, all tasks generated by the taskloop - construct are untied tasks. - - When the `mergeable` clause is present on a taskloop construct, each - generated task is a mergeable task. - - Reductions can be performed in a loop by specifying reduction accumulator - variables in `reduction_vars` or `in_reduction_vars` and symbols referring - to reduction declarations in the `reductions` or `in_reductions` attribute. - Each reduction is identified by the accumulator it uses and accumulators - must not be repeated in the same reduction. The reduction declaration - specifies how to combine the values from each iteration into the final - value, which is available in the accumulator after the loop completes. - + }] # clausesDescription # [{ If an `in_reduction` clause is present on the taskloop construct, the behavior is as if each generated task was defined by a task construct on which an `in_reduction` clause with the same reduction operator and list items is present. Thus, the generated tasks are participants of a reduction - previously defined by a reduction scoping clause. + previously defined by a reduction scoping clause. In this case, accumulator + variables are specified in `in_reduction_vars`, symbols referring to + reduction declarations in `in_reductions` and `in_reduction_vars_byref` + indicate for each reduction variable whether it should be passed by value or + by reference. If a `reduction` clause is present on the taskloop construct, the behavior is as if a `task_reduction` clause with the same reduction operator and list @@ -939,95 +636,28 @@ def TaskloopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, reduction operator and list items is present. Thus, the generated tasks are participants of the reduction defined by the `task_reduction` clause that was applied to the implicit taskgroup construct. - - When a `priority` clause is present on a taskloop construct, the generated - tasks use the `priority-value` as if it was specified for each individual - task. If the `priority` clause is not specified, tasks generated by the - taskloop construct have the default task priority (zero). - - The `allocators_vars` and `allocate_vars` arguments are a variadic list of - values that specify the memory allocator to be used to obtain storage for - private values. - - If a `grainsize` clause is present on the taskloop construct, the number of - logical loop iterations assigned to each generated task is greater than or - equal to the minimum of the value of the grain-size expression and the - number of logical loop iterations, but less than two times the value of the - grain-size expression. - - If `num_tasks` is specified, the taskloop construct creates as many tasks as - the minimum of the num-tasks expression and the number of logical loop - iterations. Each task must have at least one logical loop iteration. - - By default, the taskloop construct executes as if it was enclosed in a - taskgroup construct with no statements or directives outside of the taskloop - construct. Thus, the taskloop construct creates an implicit taskgroup - region. If the `nogroup` clause is present, no implicit taskgroup region is - created. }]; - let arguments = (ins Optional:$if_expr, - Optional:$final_expr, - UnitAttr:$untied, - UnitAttr:$mergeable, - Variadic:$in_reduction_vars, - OptionalAttr:$in_reduction_vars_byref, - OptionalAttr:$in_reductions, - Variadic:$reduction_vars, - OptionalAttr:$reduction_vars_byref, - OptionalAttr:$reductions, - Optional:$priority, - Variadic:$allocate_vars, - Variadic:$allocators_vars, - Optional: $grain_size, - Optional: $num_tasks, - UnitAttr: $nogroup); - - let regions = (region AnyRegion:$region); - let builders = [ OpBuilder<(ins CArg<"const TaskloopClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `)` - |`final` `(` $final_expr `)` - |`untied` $untied - |`mergeable` $mergeable - |`in_reduction` `(` - custom( - $in_reduction_vars, type($in_reduction_vars), - $in_reduction_vars_byref, $in_reductions - ) `)` - |`reduction` `(` - custom( - $reduction_vars, type($reduction_vars), $reduction_vars_byref, - $reductions - ) `)` - |`priority` `(` $priority `:` type($priority) `)` - |`allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - |`grain_size` `(` $grain_size `:` type($grain_size) `)` - |`num_tasks` `(` $num_tasks `:` type($num_tasks) `)` - |`nogroup` $nogroup - ) $region attr-dict - }]; - let extraClassDeclaration = [{ /// Returns the reduction variables SmallVector getAllReductionVars(); + void getEffects(SmallVectorImpl &effects); - }]; + }] # clausesExtraClassDeclaration; let hasVerifier = 1; } -def TaskgroupOp : OpenMP_Op<"taskgroup", [AttrSizedOperandSegments, - ReductionClauseInterface, - AutomaticAllocationScope]> { +def TaskgroupOp : OpenMP_Op<"taskgroup", traits = [ + AttrSizedOperandSegments, AutomaticAllocationScope + ], clauses = [ + // TODO: Sort clauses alphabetically. + OpenMP_TaskReductionClause, OpenMP_AllocateClause + ], singleRegion = true> { let summary = "taskgroup construct"; let description = [{ The taskgroup construct specifies a wait on completion of child tasks of the @@ -1040,51 +670,13 @@ def TaskgroupOp : OpenMP_Op<"taskgroup", [AttrSizedOperandSegments, an implicit task scheduling point at the end of the taskgroup region. The current task is suspended at the task scheduling point until all tasks in the taskgroup set complete execution. - - The `task_reduction` clause specifies a reduction among tasks. For each list - item, the number of copies is unspecified. Any copies associated with the - reduction are initialized before they are accessed by the tasks - participating in the reduction. After the end of the region, the original - list item contains the result of the reduction. - - The `allocators_vars` and `allocate_vars` arguments are a variadic list of - values that specify the memory allocator to be used to obtain storage for - private values. - }]; - - let arguments = (ins Variadic:$task_reduction_vars, - OptionalAttr:$task_reduction_vars_byref, - OptionalAttr:$task_reductions, - Variadic:$allocate_vars, - Variadic:$allocators_vars); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TaskgroupClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`task_reduction` `(` - custom( - $task_reduction_vars, type($task_reduction_vars), - $task_reduction_vars_byref, $task_reductions - ) `)` - |`allocate` `(` - custom( - $allocate_vars, type($allocate_vars), - $allocators_vars, type($allocators_vars) - ) `)` - ) $region attr-dict - }]; - - let extraClassDeclaration = [{ - /// Returns the reduction variables - operand_range getAllReductionVars() { return getTaskReductionVars(); } - }]; - let hasVerifier = 1; - } //===----------------------------------------------------------------------===// @@ -1104,18 +696,23 @@ def TaskyieldOp : OpenMP_Op<"taskyield"> { //===----------------------------------------------------------------------===// // 2.13.7 flush Construct //===----------------------------------------------------------------------===// -def FlushOp : OpenMP_Op<"flush"> { +def FlushOp : OpenMP_Op<"flush", clauses = [ + // TODO: Complete clause list (memory_order). + ]> { let summary = "flush construct"; let description = [{ The flush construct executes the OpenMP flush operation. This operation - makes a thread’s temporary view of memory consistent with memory and + makes a thread's temporary view of memory consistent with memory and enforces an order on the memory operations of the variables explicitly specified or implied. - }]; + }] # clausesDescription; + + let arguments = !con((ins Variadic:$varList), + clausesArgs); - let arguments = (ins Variadic:$varList); + // Override inherited assembly format to include `varList`. + let assemblyFormat = "( `(` $varList^ `:` type($varList) `)` )? attr-dict"; - let assemblyFormat = [{ ( `(` $varList^ `:` type($varList) `)` )? attr-dict}]; let extraClassDeclaration = [{ /// The number of variable operands. unsigned getNumVariableOperands() { @@ -1125,7 +722,7 @@ def FlushOp : OpenMP_Op<"flush"> { Value getVariableOperand(unsigned i) { return getOperand(i); } - }]; + }] # clausesExtraClassDeclaration; } //===----------------------------------------------------------------------===// @@ -1336,8 +933,13 @@ def MapInfoOp : OpenMP_Op<"map.info", [AttrSizedOperandSegments]> { // 2.14.2 target data Construct //===---------------------------------------------------------------------===// -def TargetDataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ +def TargetDataOp: OpenMP_Op<"target_data", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_DeviceClause, OpenMP_UseDevicePtrClause, + OpenMP_UseDeviceAddrClause, OpenMP_MapClause + ], singleRegion = true> { let summary = "target data construct"; let description = [{ Map variables to a device data environment for the extent of the region. @@ -1348,48 +950,16 @@ def TargetDataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, to and from the offloading device when multiple target regions are using the same data. - The optional $if_expr 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 target region runs on a device, if it is 0 then the target region is executed on the host device. - - The optional $device parameter specifies the device number for the target - region. - - The optional $use_device_ptr specifies the device pointers to the - corresponding list items in the device data environment. - - The optional $use_device_addr specifies the address of the objects in the - device data enviornment. - - The $map_operands specifies the locator-list operands of the map clause. - - The $map_types specifies the types and modifiers for the map clause. - - TODO: depend clause and map_type_modifier values iterator and mapper. - }]; - - let arguments = (ins Optional:$if_expr, - Optional:$device, - Variadic:$use_device_ptr, - Variadic:$use_device_addr, - Variadic:$map_operands); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TargetDataClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `:` type($if_expr) `)` - | `device` `(` $device `:` type($device) `)` - | `map_entries` `(` $map_operands `:` type($map_operands) `)` - | `use_device_ptr` `(` $use_device_ptr `:` type($use_device_ptr) `)` - | `use_device_addr` `(` $use_device_addr `:` type($use_device_addr) `)`) - $region attr-dict - }]; - let hasVerifier = 1; } @@ -1397,57 +967,29 @@ def TargetDataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, // 2.14.3 target enter data Construct //===---------------------------------------------------------------------===// -def TargetEnterDataOp: OpenMP_Op<"target_enter_data", - [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ - let summary = "target enter data construct"; +def TargetEnterDataOp: OpenMP_Op<"target_enter_data", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_DeviceClause, OpenMP_DependClause, + OpenMP_NowaitClause, OpenMP_MapClause + ]> { + let summary = "target enter data construct"; let description = [{ The target enter data directive specifies that variables are mapped to a device data environment. The target enter data directive is a stand-alone directive. - The optional $if_expr 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 target region runs on a device, if it is 0 then the target region is executed on the host device. - - The optional $device parameter specifies the device number for the - target region. - - The optional $nowait eliminates the implicit barrier so the parent task - can make progress even if the target task is not yet completed. - - The $map_operands specifies the locator-list operands of the map clause. - - The $map_types specifies the types and modifiers for the map clause. - - The `depends` and `depend_vars` arguments are variadic lists of values - that specify the dependencies of this particular target task in relation to - other tasks. - - TODO: map_type_modifier values iterator and mapper. - }]; - - let arguments = (ins Optional:$if_expr, - Optional:$device, - OptionalAttr:$depends, - Variadic:$depend_vars, - UnitAttr:$nowait, - Variadic:$map_operands); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TargetEnterExitUpdateDataClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `:` type($if_expr) `)` - | `device` `(` $device `:` type($device) `)` - | `nowait` $nowait - | `map_entries` `(` $map_operands `:` type($map_operands) `)` - | `depend` `(` custom($depend_vars, type($depend_vars), $depends) `)` - ) attr-dict - }]; - let hasVerifier = 1; } @@ -1455,57 +997,29 @@ def TargetEnterDataOp: OpenMP_Op<"target_enter_data", // 2.14.4 target exit data Construct //===---------------------------------------------------------------------===// -def TargetExitDataOp: OpenMP_Op<"target_exit_data", - [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ - let summary = "target exit data construct"; +def TargetExitDataOp: OpenMP_Op<"target_exit_data", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_DeviceClause, OpenMP_DependClause, + OpenMP_NowaitClause, OpenMP_MapClause + ]> { + let summary = "target exit data construct"; let description = [{ The target exit data directive specifies that variables are mapped to a device data environment. The target exit data directive is a stand-alone directive. - The optional $if_expr 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 target region runs on a device, if it is 0 then the target region is executed on the host device. - - The optional $device parameter specifies the device number for the - target region. - - The optional $nowait eliminates the implicit barrier so the parent - task can make progress even if the target task is not yet completed. - - The $map_operands specifies the locator-list operands of the map clause. - - The $map_types specifies the types and modifiers for the map clause. - - The `depends` and `depend_vars` arguments are variadic lists of values - that specify the dependencies of this particular target task in relation to - other tasks. - - TODO: map_type_modifier values iterator and mapper. - }]; - - let arguments = (ins Optional:$if_expr, - Optional:$device, - OptionalAttr:$depends, - Variadic:$depend_vars, - UnitAttr:$nowait, - Variadic:$map_operands); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TargetEnterExitUpdateDataClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `:` type($if_expr) `)` - | `device` `(` $device `:` type($device) `)` - | `nowait` $nowait - | `map_entries` `(` $map_operands `:` type($map_operands) `)` - | `depend` `(` custom($depend_vars, type($depend_vars), $depends) `)` - ) attr-dict - }]; - let hasVerifier = 1; } @@ -1513,59 +1027,37 @@ def TargetExitDataOp: OpenMP_Op<"target_exit_data", // 2.14.6 target update Construct //===---------------------------------------------------------------------===// -def TargetUpdateOp: OpenMP_Op<"target_update", [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ - let summary = "target update construct"; +def TargetUpdateOp: OpenMP_Op<"target_update", traits = [ + AttrSizedOperandSegments + ], clauses = [ + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_DeviceClause, OpenMP_DependClause, + OpenMP_NowaitClause, OpenMP_MapClause + ]> { + let summary = "target update construct"; let description = [{ The target update directive makes the corresponding list items in the device data environment consistent with their original list items, according to the specified motion clauses. The target update construct is a stand-alone directive. - The optional $if_expr 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 target region runs on a device, if it is 0 then the target region is executed on the host device. - The optional $device parameter specifies the device number for the - target region. - - The optional $nowait eliminates the implicit barrier so the parent - task can make progress even if the target task is not yet completed. - We use `MapInfoOp` to model the motion clauses and their modifiers. Even though the spec differentiates between map-types & map-type-modifiers vs. - motion-clauses & motion-modifiers, the motion clauses and their modifiers are - a subset of map types and their modifiers. The subset relation is handled in - during verification to make sure the restrictions for target update are - respected. - - The `depends` and `depend_vars` arguments are variadic lists of values - that specify the dependencies of this particular target task in relation to - other tasks. - - }]; - - let arguments = (ins Optional:$if_expr, - Optional:$device, - OptionalAttr:$depends, - Variadic:$depend_vars, - UnitAttr:$nowait, - Variadic:$map_operands); + motion-clauses & motion-modifiers, the motion clauses and their modifiers + are a subset of map types and their modifiers. The subset relation is + handled in during verification to make sure the restrictions for target + update are respected. + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TargetEnterExitUpdateDataClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist(`if` `(` $if_expr `:` type($if_expr) `)` - | `device` `(` $device `:` type($device) `)` - | `nowait` $nowait - | `motion_entries` `(` $map_operands `:` type($map_operands) `)` - | `depend` `(` custom($depend_vars, type($depend_vars), $depends) `)` - ) attr-dict - }]; - let hasVerifier = 1; } @@ -1573,73 +1065,31 @@ def TargetUpdateOp: OpenMP_Op<"target_update", [AttrSizedOperandSegments, // 2.14.5 target construct //===----------------------------------------------------------------------===// -def TargetOp : OpenMP_Op<"target", [IsolatedFromAbove, MapClauseOwningOpInterface, - OutlineableOpenMPOpInterface, AttrSizedOperandSegments]> { +def TargetOp : OpenMP_Op<"target", traits = [ + AttrSizedOperandSegments, IsolatedFromAbove, OutlineableOpenMPOpInterface + ], clauses = [ + // TODO: Complete clause list (allocate, defaultmap, in_reduction, + // uses_allocators). + // TODO: Sort clauses alphabetically. + OpenMP_IfClause, OpenMP_DeviceClause, OpenMP_ThreadLimitClause, + OpenMP_DependClause, OpenMP_NowaitClause, OpenMP_IsDevicePtrClause, + OpenMP_HasDeviceAddrClause, OpenMP_MapClause, OpenMP_PrivateClause + ], singleRegion = true> { let summary = "target construct"; let description = [{ The target construct includes a region of code which is to be executed on a device. - The optional $if_expr 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 target region runs on a device, if it is 0 then the target region is executed on the host device. - - The optional $device parameter specifies the device number for the target region. - - The optional $thread_limit specifies the limit on the number of threads - - The optional $nowait eliminates the implicit barrier so the parent task can make progress - even if the target task is not yet completed. - - The `depends` and `depend_vars` arguments are variadic lists of values - that specify the dependencies of this particular target task in relation to - other tasks. - - The optional $is_device_ptr indicates list items are device pointers. - - The optional $has_device_addr indicates that list items already have device - addresses, so they may be directly accessed from the target device. This - includes array sections. - - The optional $map_operands maps data from the task’s environment to the - device environment. - - TODO: defaultmap, in_reduction - - }]; - - let arguments = (ins Optional:$if_expr, - Optional:$device, - Optional:$thread_limit, - OptionalAttr:$depends, - Variadic:$depend_vars, - UnitAttr:$nowait, - Variadic:$is_device_ptr, - Variadic:$has_device_addr, - Variadic:$map_operands, - Variadic:$private_vars, - OptionalAttr:$privatizers); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TargetClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - oilist( `if` `(` $if_expr `)` - | `device` `(` $device `:` type($device) `)` - | `thread_limit` `(` $thread_limit `:` type($thread_limit) `)` - | `nowait` $nowait - | `is_device_ptr` `(` $is_device_ptr `:` type($is_device_ptr) `)` - | `has_device_addr` `(` $has_device_addr `:` type($has_device_addr) `)` - | `map_entries` `(` custom($map_operands, type($map_operands)) `)` - | `private` `(` custom($private_vars, type($private_vars), $privatizers) `)` - | `depend` `(` custom($depend_vars, type($depend_vars), $depends) `)` - ) $region attr-dict - }]; - let hasVerifier = 1; } @@ -1647,57 +1097,52 @@ def TargetOp : OpenMP_Op<"target", [IsolatedFromAbove, MapClauseOwningOpInterfac //===----------------------------------------------------------------------===// // 2.16 master Construct //===----------------------------------------------------------------------===// -def MasterOp : OpenMP_Op<"master"> { +def MasterOp : OpenMP_Op<"master", singleRegion = true> { let summary = "master construct"; let description = [{ The master construct specifies a structured block that is executed by the master thread of the team. }]; - let regions = (region AnyRegion:$region); - let assemblyFormat = "$region attr-dict"; } //===----------------------------------------------------------------------===// // 2.17.1 critical Construct //===----------------------------------------------------------------------===// -def CriticalDeclareOp : OpenMP_Op<"critical.declare", [Symbol]> { +def CriticalDeclareOp : OpenMP_Op<"critical.declare", traits = [ + Symbol + ], clauses = [ + OpenMP_CriticalNameClause, OpenMP_HintClause + ]> { let summary = "declares a named critical section."; - let description = [{ Declares a named critical section. - - The name can be used in critical constructs in the dialect. - }]; - - let arguments = (ins SymbolNameAttr:$sym_name, - DefaultValuedAttr:$hint_val); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const CriticalClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - $sym_name oilist(`hint` `(` custom($hint_val) `)`) - attr-dict - }]; let hasVerifier = 1; } -def CriticalOp : OpenMP_Op<"critical", - [DeclareOpInterfaceMethods]> { +def CriticalOp : OpenMP_Op<"critical", [ + DeclareOpInterfaceMethods + ], singleRegion = 1> { let summary = "critical construct"; let description = [{ The critical construct imposes a restriction on the associated structured block (region) to be executed by only a single thread at a time. + + The optional `name` argument of critical constructs is used to identify + them. Unnamed critical constructs behave as though an identical name was + specified. }]; let arguments = (ins OptionalAttr:$name); - let regions = (region AnyRegion:$region); - let assemblyFormat = [{ (`(` $name^ `)`)? $region attr-dict }]; @@ -1721,62 +1166,34 @@ def BarrierOp : OpenMP_Op<"barrier"> { // [5.1] 2.19.9 ordered Construct //===----------------------------------------------------------------------===// -def OrderedOp : OpenMP_Op<"ordered"> { +def OrderedOp : OpenMP_Op<"ordered", clauses = [OpenMP_DoacrossClause]> { let summary = "ordered construct without region"; let description = [{ The ordered construct without region is a stand-alone directive that - specifies cross-iteration dependences in a doacross loop nest. - - The `depend_type_val` attribute refers to either the DEPEND(SOURCE) clause - or the DEPEND(SINK: vec) clause. - - The `num_loops_val` attribute specifies the number of loops in the doacross - nest. - - The `depend_vec_vars` is a variadic list of operands that specifies the index - of the loop iterator in the doacross nest for the DEPEND(SOURCE) clause or - the index of the element of "vec" for the DEPEND(SINK: vec) clause. It - contains the operands in multiple "vec" when multiple DEPEND(SINK: vec) - clauses exist in one ORDERED directive. - }]; - - let arguments = (ins OptionalAttr:$depend_type_val, - ConfinedAttr, [IntMinValue<0>]>:$num_loops_val, - Variadic:$depend_vec_vars); + specifies cross-iteration dependencies in a doacross loop nest. + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const OrderedOpClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ - ( `depend_type` `` $depend_type_val^ )? - ( `depend_vec` `(` $depend_vec_vars^ `:` type($depend_vec_vars) `)` )? - attr-dict - }]; let hasVerifier = 1; } -def OrderedRegionOp : OpenMP_Op<"ordered.region"> { +def OrderedRegionOp : OpenMP_Op<"ordered.region", clauses = [ + OpenMP_ParallelizationLevelClause + ], singleRegion = true> { let summary = "ordered construct with region"; let description = [{ The ordered construct with region specifies a structured block in a worksharing-loop, SIMD, or worksharing-loop SIMD region that is executed in the order of the loop iterations. - - The `simd` attribute corresponds to the SIMD clause specified. If it is not - present, it behaves as if the THREADS clause is specified or no clause is - specified. - }]; - - let arguments = (ins UnitAttr:$simd); - - let regions = (region AnyRegion:$region); + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const OrderedRegionClauseOps &">:$clauses)> ]; - let assemblyFormat = [{ ( `simd` $simd^ )? $region attr-dict}]; let hasVerifier = 1; } @@ -1784,17 +1201,20 @@ def OrderedRegionOp : OpenMP_Op<"ordered.region"> { // 2.17.5 taskwait Construct //===----------------------------------------------------------------------===// -def TaskwaitOp : OpenMP_Op<"taskwait"> { +def TaskwaitOp : OpenMP_Op<"taskwait", clauses = [ + // TODO: Complete clause list (depend, nowait). + ]> { let summary = "taskwait construct"; let description = [{ The taskwait construct specifies a wait on the completion of child tasks of the current task. - }]; + }] # clausesDescription; let builders = [ OpBuilder<(ins CArg<"const TaskwaitClauseOps &">:$clauses)> ]; + // TODO: Remove overriden `assemblyFormat` once a clause is added. let assemblyFormat = "attr-dict"; } @@ -1809,37 +1229,31 @@ def TaskwaitOp : OpenMP_Op<"taskwait"> { // value of the clause) here decomposes handling of this construct into a // two-step process. -def AtomicReadOp : OpenMP_Op<"atomic.read", [AllTypesMatch<["x", "v"]>, - AtomicReadOpInterface]> { - +def AtomicReadOp : OpenMP_Op<"atomic.read", traits = [ + AllTypesMatch<["x", "v"]>, AtomicReadOpInterface + ], clauses = [ + OpenMP_HintClause, OpenMP_MemoryOrderClause + ]> { let summary = "performs an atomic read"; - let description = [{ This operation performs an atomic read. The operand `x` is the address from where the value is atomically read. The operand `v` is the address where the value is stored after reading. + }] # clausesDescription; - `hint` is the value of hint (as specified in the hint clause). It is a - compile time constant. As the name suggests, this is just a hint for - optimization. + let arguments = !con((ins OpenMP_PointerLikeType:$x, + OpenMP_PointerLikeType:$v, + TypeAttr:$element_type), clausesArgs); - `memory_order` indicates the memory ordering behavior of the construct. It - can be one of `seq_cst`, `acquire` or `relaxed`. - }]; - - let arguments = (ins OpenMP_PointerLikeType:$x, - OpenMP_PointerLikeType:$v, - TypeAttr:$element_type, - DefaultValuedOptionalAttr:$hint_val, - OptionalAttr:$memory_order_val); + // Override clause-based assemblyFormat. let assemblyFormat = [{ $v `=` $x oilist( `memory_order` `(` custom($memory_order_val) `)` | `hint` `(` custom($hint_val) `)`) `:` type($x) `,` $element_type attr-dict }]; - let hasVerifier = 1; + let extraClassDeclaration = [{ /// The number of variable operands. unsigned getNumVariableOperands() { @@ -1853,13 +1267,17 @@ def AtomicReadOp : OpenMP_Op<"atomic.read", [AllTypesMatch<["x", "v"]>, assert(i < 2 && "invalid index position for an operand"); return i == 0 ? getX() : getV(); } - }]; -} + }] # clausesExtraClassDeclaration; -def AtomicWriteOp : OpenMP_Op<"atomic.write", [AtomicWriteOpInterface]> { + let hasVerifier = 1; +} +def AtomicWriteOp : OpenMP_Op<"atomic.write", traits = [ + AtomicWriteOpInterface + ], clauses = [ + OpenMP_HintClause, OpenMP_MemoryOrderClause + ]> { let summary = "performs an atomic write"; - let description = [{ This operation performs an atomic write. @@ -1867,19 +1285,12 @@ def AtomicWriteOp : OpenMP_Op<"atomic.write", [AtomicWriteOpInterface]> { written w.r.t. multiple threads. The evaluation of `expr` need not be atomic w.r.t. the write to address. In general, the type(x) must dereference to type(expr). + }] # clausesDescription; - `hint` is the value of hint (as specified in the hint clause). It is a - compile time constant. As the name suggests, this is just a hint for - optimization. + let arguments = !con((ins OpenMP_PointerLikeType:$x, + AnyType:$expr), clausesArgs); - `memory_order` indicates the memory ordering behavior of the construct. It - can be one of `seq_cst`, `release` or `relaxed`. - }]; - - let arguments = (ins OpenMP_PointerLikeType:$x, - AnyType:$expr, - DefaultValuedOptionalAttr:$hint_val, - OptionalAttr:$memory_order_val); + // Override clause-based assemblyFormat. let assemblyFormat = [{ $x `=` $expr oilist( `hint` `(` custom($hint_val) `)` @@ -1887,7 +1298,7 @@ def AtomicWriteOp : OpenMP_Op<"atomic.write", [AtomicWriteOpInterface]> { `:` type($x) `,` type($expr) attr-dict }]; - let hasVerifier = 1; + let extraClassDeclaration = [{ /// The number of variable operands. unsigned getNumVariableOperands() { @@ -1901,16 +1312,18 @@ def AtomicWriteOp : OpenMP_Op<"atomic.write", [AtomicWriteOpInterface]> { assert(i < 2 && "invalid index position for an operand"); return i == 0 ? getX() : getExpr(); } - }]; -} + }] # clausesExtraClassDeclaration; -def AtomicUpdateOp : OpenMP_Op<"atomic.update", - [SingleBlockImplicitTerminator<"YieldOp">, - RecursiveMemoryEffects, - AtomicUpdateOpInterface]> { + let hasVerifier = 1; +} +def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = [ + AtomicUpdateOpInterface, RecursiveMemoryEffects, + SingleBlockImplicitTerminator<"YieldOp"> + ], clauses = [ + OpenMP_HintClause, OpenMP_MemoryOrderClause + ], singleRegion = 1> { let summary = "performs an atomic update"; - let description = [{ This operation performs an atomic update. @@ -1918,12 +1331,6 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", Standard (OpenMP 5.0, section 2.17.7). It is the address of the variable that is being updated. `x` is atomically read/written. - `hint` is the value of hint (as used in the hint clause). It is a compile - time constant. As the name suggests, this is just a hint for optimization. - - `memory_order` indicates the memory ordering behavior of the construct. It - can be one of `seq_cst`, `release` or `relaxed`. - The region describes how to update the value of `x`. It takes the value at `x` as an input and must yield the updated value. Only the update to `x` is atomic. Generally the region must have only one instruction, but can @@ -1938,22 +1345,22 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", the core update operation is directly translated like regular operations by the host dialect. The front-end must handle semantic checks for allowed operations. - }]; + }] # clausesDescription; + + let arguments = !con((ins Arg:$x), clausesArgs); - let arguments = (ins Arg:$x, - DefaultValuedOptionalAttr:$hint_val, - OptionalAttr:$memory_order_val); + // Override region definition. let regions = (region SizedRegion<1>:$region); + + // Override clause-based assemblyFormat. let assemblyFormat = [{ oilist( `memory_order` `(` custom($memory_order_val) `)` | `hint` `(` custom($hint_val) `)`) $x `:` type($x) $region attr-dict }]; - let hasVerifier = 1; - let hasRegionVerifier = 1; - let hasCanonicalizeMethod = 1; + let extraClassDeclaration = [{ /// The number of variable operands. unsigned getNumVariableOperands() { @@ -1966,24 +1373,24 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", assert(i == 0 && "invalid index position for an operand"); return getX(); } - }]; + }] # clausesExtraClassDeclaration; + + let hasVerifier = 1; + let hasRegionVerifier = 1; + let hasCanonicalizeMethod = 1; } -def AtomicCaptureOp : OpenMP_Op<"atomic.capture", - [SingleBlockImplicitTerminator<"TerminatorOp">, - RecursiveMemoryEffects, AtomicCaptureOpInterface]> { +def AtomicCaptureOp : OpenMP_Op<"atomic.capture", traits = [ + AtomicCaptureOpInterface, RecursiveMemoryEffects, + SingleBlockImplicitTerminator<"TerminatorOp"> + ], clauses = [ + OpenMP_HintClause, OpenMP_MemoryOrderClause + ], singleRegion = 1> { let summary = "performs an atomic capture"; let description = [{ This operation performs an atomic capture. - `hint` is the value of hint (as used in the hint clause). It is a compile - time constant. As the name suggests, this is just a hint for optimization. - - `memory_order` indicates the memory ordering behavior of the construct. It - can be one of `seq_cst`, `acq_rel`, `release`, `acquire` or `relaxed`. - The region has the following allowed forms: - ``` omp.atomic.capture { omp.atomic.update ... @@ -2003,19 +1410,11 @@ def AtomicCaptureOp : OpenMP_Op<"atomic.capture", omp.terminator } ``` + }] # clausesDescription; - }]; - - let arguments = (ins DefaultValuedOptionalAttr:$hint_val, - OptionalAttr:$memory_order_val); + // Override region definition. let regions = (region SizedRegion<1>:$region); - let assemblyFormat = [{ - oilist(`memory_order` `(` custom($memory_order_val) `)` - |`hint` `(` custom($hint_val) `)`) - $region attr-dict - }]; - let hasRegionVerifier = 1; - let hasVerifier = 1; + let extraClassDeclaration = [{ /// Returns the `atomic.read` operation inside the region, if any. /// Otherwise, it returns nullptr. @@ -2028,7 +1427,10 @@ def AtomicCaptureOp : OpenMP_Op<"atomic.capture", /// Returns the `atomic.update` operation inside the region, if any. /// Otherwise, it returns nullptr. AtomicUpdateOp getAtomicUpdateOp(); - }]; + }] # clausesExtraClassDeclaration; + + let hasRegionVerifier = 1; + let hasVerifier = 1; } //===----------------------------------------------------------------------===// @@ -2078,34 +1480,39 @@ def ThreadprivateOp : OpenMP_Op<"threadprivate", //===----------------------------------------------------------------------===// // 2.18.1 Cancel Construct //===----------------------------------------------------------------------===// -def CancelOp : OpenMP_Op<"cancel"> { +def CancelOp : OpenMP_Op<"cancel", clauses = [ + OpenMP_CancelDirectiveNameClause, OpenMP_IfClause + ]> { let summary = "cancel directive"; let description = [{ The cancel construct activates cancellation of the innermost enclosing region of the type specified. - }]; - let arguments = (ins CancellationConstructTypeAttr:$cancellation_construct_type_val, - Optional:$if_expr); - let assemblyFormat = [{ `cancellation_construct_type` `(` - custom($cancellation_construct_type_val) `)` - ( `if` `(` $if_expr^ `)` )? attr-dict}]; + }] # clausesDescription; + + let builders = [ + OpBuilder<(ins CArg<"const CancelClauseOps &">:$clauses)> + ]; + let hasVerifier = 1; } //===----------------------------------------------------------------------===// // 2.18.2 Cancellation Point Construct //===----------------------------------------------------------------------===// -def CancellationPointOp : OpenMP_Op<"cancellation_point"> { +def CancellationPointOp : OpenMP_Op<"cancellation_point", clauses = [ + OpenMP_CancelDirectiveNameClause + ]> { let summary = "cancellation point directive"; let description = [{ The cancellation point construct introduces a user-defined cancellation point at which implicit or explicit tasks check if cancellation of the innermost enclosing region of the type specified has been activated. - }]; - let arguments = (ins CancellationConstructTypeAttr:$cancellation_construct_type_val); - let assemblyFormat = [{ `cancellation_construct_type` `(` - custom($cancellation_construct_type_val) `)` - attr-dict}]; + }] # clausesDescription; + + let builders = [ + OpBuilder<(ins CArg<"const CancellationPointClauseOps &">:$clauses)> + ]; + let hasVerifier = 1; } @@ -2113,11 +1520,10 @@ def CancellationPointOp : OpenMP_Op<"cancellation_point"> { // 2.19.5.7 declare reduction Directive //===----------------------------------------------------------------------===// -def DeclareReductionOp : OpenMP_Op<"declare_reduction", [Symbol, - IsolatedFromAbove, - RecipeInterface]> { +def DeclareReductionOp : OpenMP_Op<"declare_reduction", [IsolatedFromAbove, + RecipeInterface, + Symbol]> { let summary = "declares a reduction kind"; - let description = [{ Declares an OpenMP reduction kind. This requires two mandatory and two optional regions. diff --git a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp index 60c62131752f6..fdc4c7be1ca5c 100644 --- a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp +++ b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp @@ -444,7 +444,7 @@ struct ParallelOpLowering : public OpRewritePattern { // Create the parallel wrapper. auto ompParallel = rewriter.create( loc, - /* if_expr_var = */ Value{}, + /* if_expr = */ Value{}, /* num_threads_var = */ numThreadsVar, /* allocate_vars = */ llvm::SmallVector{}, /* allocators_vars = */ llvm::SmallVector{}, diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index c0be9e919d2fd..b13c8d1382fa8 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -608,12 +608,12 @@ static void printParallelRegion(OpAsmPrinter &p, Operation *op, Region ®ion, /// reduction-entry-list ::= reduction-entry /// | reduction-entry-list `,` reduction-entry -/// reduction-entry ::= symbol-ref `->` ssa-id `:` type +/// reduction-entry ::= (`byref`)? symbol-ref `->` ssa-id `:` type static ParseResult parseReductionVarList(OpAsmParser &parser, SmallVectorImpl &operands, SmallVectorImpl &types, DenseBoolArrayAttr &isByRef, - ArrayAttr &redcuctionSymbols) { + ArrayAttr &reductionSymbols) { SmallVector reductionVec; SmallVector isByRefVec; if (failed(parser.parseCommaSeparatedList([&]() { @@ -629,7 +629,7 @@ parseReductionVarList(OpAsmParser &parser, return failure(); isByRef = makeDenseBoolArrayAttr(parser.getContext(), isByRefVec); SmallVector reductions(reductionVec.begin(), reductionVec.end()); - redcuctionSymbols = ArrayAttr::get(parser.getContext(), reductions); + reductionSymbols = ArrayAttr::get(parser.getContext(), reductions); return success(); } @@ -1133,7 +1133,7 @@ static void printMembersIndex(OpAsmPrinter &p, MapInfoOp op, DenseIntElementsAttr membersIdx) { llvm::ArrayRef shape = membersIdx.getShapedType().getShape(); assert(shape.size() <= 2); - + if (!membersIdx) return; @@ -1141,8 +1141,7 @@ static void printMembersIndex(OpAsmPrinter &p, MapInfoOp op, p << "["; int rowOffset = i * shape[1]; for (int j = 0; j < shape[1]; ++j) { - p << membersIdx.getValues< - int32_t>()[rowOffset + j]; + p << membersIdx.getValues()[rowOffset + j]; if ((j + 1) < shape[1]) p << ","; } @@ -1161,8 +1160,9 @@ parseMapEntries(OpAsmParser &parser, OpAsmParser::UnresolvedOperand blockArg; Type argType; auto parseEntries = [&]() -> ParseResult { - if (parser.parseOperand(arg) || parser.parseArrow() || - parser.parseOperand(blockArg)) + if (parser.parseOperand(arg)) + return failure(); + if (succeeded(parser.parseOptionalArrow()) && parser.parseOperand(blockArg)) return failure(); mapOperands.push_back(arg); return success(); @@ -1190,12 +1190,18 @@ parseMapEntries(OpAsmParser &parser, static void printMapEntries(OpAsmPrinter &p, Operation *op, OperandRange mapOperands, TypeRange mapOperandTypes) { - auto ®ion = op->getRegion(0); + // Get pointer to the region if this is an omp.target, because printing map + // clauses for that operation has to also show the correspondence of each + // variable to the corresponding block argument. + Block *entryBlock = isa(op) ? &op->getRegion(0).front() : nullptr; unsigned argIndex = 0; for (const auto &mapOp : mapOperands) { - const auto &blockArg = region.front().getArgument(argIndex); - p << mapOp << " -> " << blockArg; + p << mapOp; + if (entryBlock) { + const auto &blockArg = entryBlock->getArgument(argIndex); + p << " -> " << blockArg; + } argIndex++; if (argIndex < mapOperands.size()) p << ", "; @@ -1467,7 +1473,7 @@ void TargetOp::build(OpBuilder &builder, OperationState &state, const TargetClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); // TODO Store clauses in op: allocateVars, allocatorVars, inReductionVars, - // inReductionDeclSymbols, reductionVars, reductionByRefAttr, + // inReduceVarByRef, inReductionDeclSymbols, reductionVars, reduceVarByRef, // reductionDeclSymbols. TargetOp::build( builder, state, clauses.ifVar, clauses.deviceVar, clauses.threadLimitVar, @@ -1491,12 +1497,11 @@ LogicalResult TargetOp::verify() { void ParallelOp::build(OpBuilder &builder, OperationState &state, ArrayRef attributes) { ParallelOp::build( - builder, state, /*if_expr_var=*/nullptr, /*num_threads_var=*/nullptr, + builder, state, /*if_expr=*/nullptr, /*num_threads_var=*/nullptr, /*allocate_vars=*/ValueRange(), /*allocators_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), /*reduction_vars_byref=*/nullptr, - /*reductions=*/nullptr, - /*proc_bind_val=*/nullptr, /*private_vars=*/ValueRange(), - /*privatizers=*/nullptr); + /*reductions=*/nullptr, /*proc_bind_val=*/nullptr, + /*private_vars=*/ValueRange(), /*privatizers=*/nullptr); state.addAttributes(attributes); } @@ -1600,7 +1605,7 @@ static bool opInGlobalImplicitParallelRegion(Operation *op) { void TeamsOp::build(OpBuilder &builder, OperationState &state, const TeamsClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); - // TODO Store clauses in op: reductionByRefAttr, privateVars, privatizers. + // TODO Store clauses in op: privateVars, privatizers. TeamsOp::build(builder, state, clauses.numTeamsLowerVar, clauses.numTeamsUpperVar, clauses.ifVar, clauses.threadLimitVar, clauses.allocateVars, @@ -1648,7 +1653,7 @@ LogicalResult TeamsOp::verify() { void SectionsOp::build(OpBuilder &builder, OperationState &state, const SectionsClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); - // TODO Store clauses in op: reductionByRefAttr, privateVars, privatizers. + // TODO Store clauses in op: privateVars, privatizers. SectionsOp::build(builder, state, clauses.reductionVars, makeDenseBoolArrayAttr(ctx, clauses.reductionVarsByRef), makeArrayAttr(ctx, clauses.reductionDeclSymbols), @@ -1782,12 +1787,12 @@ LogicalResult WsloopOp::verify() { void SimdOp::build(OpBuilder &builder, OperationState &state, const SimdClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); - // TODO Store clauses in op: privateVars, reductionByRefAttr, reductionVars, - // privatizers, reductionDeclSymbols. + // TODO Store clauses in op: privateVars, privatizers, reductionVars, + // reduceVarByRef, reductionDeclSymbols. SimdOp::build(builder, state, clauses.alignedVars, makeArrayAttr(ctx, clauses.alignmentAttrs), clauses.ifVar, clauses.nontemporalVars, clauses.orderAttr, - clauses.orderModAttr, clauses.simdlenAttr, clauses.safelenAttr); + clauses.orderModAttr, clauses.safelenAttr, clauses.simdlenAttr); } LogicalResult SimdOp::verify() { @@ -1996,7 +2001,7 @@ LogicalResult TaskgroupOp::verify() { void TaskloopOp::build(OpBuilder &builder, OperationState &state, const TaskloopClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); - // TODO Store clauses in op: reductionByRefAttr, privateVars, privatizers. + // TODO Store clauses in op: privateVars, privatizers. TaskloopOp::build( builder, state, clauses.ifVar, clauses.finalVar, clauses.untiedAttr, clauses.mergeableAttr, clauses.inReductionVars, @@ -2158,7 +2163,8 @@ void LoopNestOp::gatherWrappers( void CriticalDeclareOp::build(OpBuilder &builder, OperationState &state, const CriticalClauseOps &clauses) { - CriticalDeclareOp::build(builder, state, clauses.nameAttr, clauses.hintAttr); + CriticalDeclareOp::build(builder, state, clauses.criticalNameAttr, + clauses.hintAttr); } LogicalResult CriticalDeclareOp::verify() { @@ -2372,9 +2378,15 @@ LogicalResult AtomicCaptureOp::verifyRegions() { } //===----------------------------------------------------------------------===// -// Verifier for CancelOp +// CancelOp //===----------------------------------------------------------------------===// +void CancelOp::build(OpBuilder &builder, OperationState &state, + const CancelClauseOps &clauses) { + CancelOp::build(builder, state, clauses.cancelDirectiveNameAttr, + clauses.ifVar); +} + LogicalResult CancelOp::verify() { ClauseCancellationConstructType cct = getCancellationConstructTypeVal(); Operation *parentOp = (*this)->getParentOp(); @@ -2421,10 +2433,16 @@ LogicalResult CancelOp::verify() { // TODO : Add more when we support taskgroup. return success(); } + //===----------------------------------------------------------------------===// -// Verifier for CancelOp +// CancellationPointOp //===----------------------------------------------------------------------===// +void CancellationPointOp::build(OpBuilder &builder, OperationState &state, + const CancellationPointClauseOps &clauses) { + CancellationPointOp::build(builder, state, clauses.cancelDirectiveNameAttr); +} + LogicalResult CancellationPointOp::verify() { ClauseCancellationConstructType cct = getCancellationConstructTypeVal(); Operation *parentOp = (*this)->getParentOp(); diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 6754a5c002efc..fe257a43aa579 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -1435,7 +1435,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, }; llvm::Value *ifCond = nullptr; - if (auto ifExprVar = opInst.getIfExprVar()) + if (auto ifExprVar = opInst.getIfExpr()) ifCond = moduleTranslation.lookupValue(ifExprVar); llvm::Value *numThreads = nullptr; if (auto numThreadsVar = opInst.getNumThreadsVar()) diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index 98284822f90a4..2915963f704d3 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -64,7 +64,7 @@ func.func @no_nested_wrapper(%lb : index, %ub : index, %step : index) { func.func @if_once(%n : i1) { // expected-error@+1 {{`if` clause can appear at most once in the expansion of the oilist directive}} - omp.parallel if(%n : i1) if(%n : i1) { + omp.parallel if(%n) if(%n) { } return @@ -274,7 +274,7 @@ func.func @unconstrained_order(%lb : index, %ub : index, %step : index) { func.func @if_not_allowed(%lb : index, %ub : index, %step : index, %bool_var : i1) { // expected-error @below {{expected '{'}} - omp.wsloop if(%bool_var: i1) { + omp.wsloop if(%bool_var) { omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) { omp.yield } @@ -2043,7 +2043,7 @@ func.func @omp_target_update_invalid_motion_type(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2053,7 +2053,7 @@ func.func @omp_target_update_invalid_motion_type_2(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(delete) capture(ByRef) -> memref {name = ""} // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2063,7 +2063,7 @@ func.func @omp_target_update_invalid_motion_modifier(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(always, to) capture(ByRef) -> memref {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2073,7 +2073,7 @@ func.func @omp_target_update_invalid_motion_modifier_2(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(close, to) capture(ByRef) -> memref {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2083,7 +2083,7 @@ func.func @omp_target_update_invalid_motion_modifier_3(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(implicit, to) capture(ByRef) -> memref {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2093,7 +2093,7 @@ func.func @omp_target_update_invalid_motion_modifier_4(%map1 : memref) { %mapv = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(implicit, tofrom) capture(ByRef) -> memref {name = ""} // expected-error @below {{either to or from map types can be specified, not both}} - omp.target_update motion_entries(%mapv : memref) + omp.target_update map_entries(%mapv : memref) return } @@ -2104,7 +2104,7 @@ func.func @omp_target_update_invalid_motion_modifier_5(%map1 : memref) { %mapv2 = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(from) capture(ByRef) -> memref {name = ""} // expected-error @below {{either to or from map types can be specified, not both}} - omp.target_update motion_entries(%mapv, %mapv2 : memref, memref) + omp.target_update map_entries(%mapv, %mapv2 : memref, memref) return } llvm.mlir.global internal @_QFsubEx() : i32 @@ -2114,7 +2114,7 @@ llvm.mlir.global internal @_QFsubEx() : i32 func.func @omp_target_update_data_depend(%a: memref) { %0 = omp.map.info var_ptr(%a: memref, tensor) map_clauses(to) capture(ByRef) -> memref // expected-error @below {{op expected as many depend values as depend variables}} - omp.target_update motion_entries(%0: memref ) {operandSegmentSizes = array} + omp.target_update map_entries(%0: memref ) {operandSegmentSizes = array} return } diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index 56e65213d147b..eb283840aa7ee 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -134,16 +134,16 @@ func.func @omp_parallel_pretty(%data_var : memref, %if_cond : i1, %num_thre } // CHECK: omp.parallel - // CHECK-NEXT: omp.parallel if(%{{.*}} : i1) + // CHECK-NEXT: omp.parallel if(%{{.*}}) omp.parallel { - omp.parallel if(%if_cond: i1) { + omp.parallel if(%if_cond) { omp.terminator } omp.terminator } // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) proc_bind(close) - omp.parallel num_threads(%num_threads : i32) if(%if_cond: i1) proc_bind(close) { + omp.parallel num_threads(%num_threads : i32) if(%if_cond) proc_bind(close) { omp.terminator } @@ -804,17 +804,16 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %devic return } -// CHECK-LABEL: omp_target_data func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref, %device_addr: memref, %map1: memref, %map2: memref) -> () { // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref, tensor) map_clauses(always, from) capture(ByRef) -> memref {name = ""} - // CHECK: omp.target_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) map_entries(%[[MAP_A]] : memref) + // CHECK: omp.target_data if(%[[VAL_0:.*]]) device(%[[VAL_1:.*]] : si32) map_entries(%[[MAP_A]] : memref) %mapv1 = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(always, from) capture(ByRef) -> memref {name = ""} - omp.target_data if(%if_cond : i1) device(%device : si32) map_entries(%mapv1 : memref){} + omp.target_data if(%if_cond) device(%device : si32) map_entries(%mapv1 : memref){} // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref, tensor) map_clauses(close, present, to) capture(ByRef) -> memref {name = ""} - // CHECK: omp.target_data map_entries(%[[MAP_A]] : memref) use_device_ptr(%[[VAL_3:.*]] : memref) use_device_addr(%[[VAL_4:.*]] : memref) + // CHECK: omp.target_data use_device_ptr(%[[VAL_3:.*]] : memref) use_device_addr(%[[VAL_4:.*]] : memref) map_entries(%[[MAP_A]] : memref) %mapv2 = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(close, present, to) capture(ByRef) -> memref {name = ""} - omp.target_data map_entries(%mapv2 : memref) use_device_ptr(%device_ptr : memref) use_device_addr(%device_addr : memref) {} + omp.target_data use_device_ptr(%device_ptr : memref) use_device_addr(%device_addr : memref) map_entries(%mapv2 : memref) {} // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref, tensor) map_clauses(tofrom) capture(ByRef) -> memref {name = ""} // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} @@ -824,14 +823,14 @@ func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref, memref) {} // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} - // CHECK: omp.target_enter_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref) + // CHECK: omp.target_enter_data if(%[[VAL_0:.*]]) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref) %mapv5 = omp.map.info var_ptr(%map1 : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} - omp.target_enter_data if(%if_cond : i1) device(%device : si32) nowait map_entries(%mapv5 : memref) + omp.target_enter_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv5 : memref) // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} - // CHECK: omp.target_exit_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref) + // CHECK: omp.target_exit_data if(%[[VAL_0:.*]]) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref) %mapv6 = omp.map.info var_ptr(%map2 : memref, tensor) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref {name = ""} - omp.target_exit_data if(%if_cond : i1) device(%device : si32) nowait map_entries(%mapv6 : memref) + omp.target_exit_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv6 : memref) return } @@ -1816,7 +1815,7 @@ func.func @omp_atomic_capture(%v: memref, %x: memref, %expr: i32) { omp.atomic.read %v = %x : memref, i32 } - // CHECK: omp.atomic.capture memory_order(seq_cst) hint(contended, speculative) { + // CHECK: omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) { // CHECK-NEXT: omp.atomic.update %[[x]] : memref // CHECK-NEXT: (%[[xval:.*]]: i32): // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 @@ -1849,7 +1848,7 @@ func.func @omp_sectionsop(%data_var1 : memref, %data_var2 : memref, "omp.sections" (%redn_var) ({ // CHECK: omp.terminator omp.terminator - }) {operandSegmentSizes = array, reductions=[@add_f32]} : (!llvm.ptr) -> () + }) {operandSegmentSizes = array, reduction_vars_byref = array, reductions=[@add_f32]} : (!llvm.ptr) -> () // CHECK: omp.sections nowait { omp.sections nowait { @@ -2049,8 +2048,8 @@ func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memr } // Checking priority clause - // CHECK: omp.task priority(%[[i32_var]]) { - omp.task priority(%i32_var) { + // CHECK: omp.task priority(%[[i32_var]] : i32) { + omp.task priority(%i32_var : i32) { // CHECK: "test.foo"() : () -> () "test.foo"() : () -> () // CHECK: omp.terminator @@ -2071,8 +2070,8 @@ func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memr omp.task if(%bool_var) final(%bool_var) untied // CHECK-SAME: in_reduction(@add_f32 -> %[[redn_var1]] : !llvm.ptr, byref @add_f32 -> %[[redn_var2]] : !llvm.ptr) in_reduction(@add_f32 -> %0 : !llvm.ptr, byref @add_f32 -> %1 : !llvm.ptr) - // CHECK-SAME: priority(%[[i32_var]]) - priority(%i32_var) + // CHECK-SAME: priority(%[[i32_var]] : i32) + priority(%i32_var : i32) // CHECK-SAME: allocate(%[[data_var]] : memref -> %[[data_var]] : memref) allocate(%data_var : memref -> %data_var : memref) { // CHECK: "test.foo"() : () -> () @@ -2361,7 +2360,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () { %testi32 = "test.i32"() : () -> (i32) // CHECK: omp.taskloop priority(%{{[^:]+}}: i32) { - omp.taskloop priority(%testi32: i32) { + omp.taskloop priority(%testi32 : i32) { omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) { // CHECK: omp.yield omp.yield @@ -2529,8 +2528,8 @@ func.func @omp_target_update_data (%if_cond : i1, %device : si32, %map1: memref< %mapv_to = omp.map.info var_ptr(%map2 : memref, tensor) map_clauses(present, to) capture(ByRef) -> memref {name = ""} - // CHECK: omp.target_update if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait motion_entries(%{{.*}}, %{{.*}} : memref, memref) - omp.target_update if(%if_cond : i1) device(%device : si32) nowait motion_entries(%mapv_from , %mapv_to : memref, memref) + // CHECK: omp.target_update if(%[[VAL_0:.*]]) device(%[[VAL_1:.*]] : si32) nowait map_entries(%{{.*}}, %{{.*}} : memref, memref) + omp.target_update if(%if_cond) device(%device : si32) nowait map_entries(%mapv_from , %mapv_to : memref, memref) return } @@ -2566,8 +2565,8 @@ func.func @omp_target_enter_update_exit_data_depend(%a: memref, %b: memre } // Then map that over to the target - // CHECK: omp.target_enter_data nowait map_entries([[MAP0]], [[MAP2]] : memref, memref) depend(taskdependin -> [[ARG0]] : memref) - omp.target_enter_data nowait map_entries(%map_a, %map_c: memref, memref) depend(taskdependin -> %a: memref) + // CHECK: omp.target_enter_data depend(taskdependin -> [[ARG0]] : memref) nowait map_entries([[MAP0]], [[MAP2]] : memref, memref) + omp.target_enter_data depend(taskdependin -> %a: memref) nowait map_entries(%map_a, %map_c: memref, memref) // Compute 'b' on the target and copy it back // CHECK: omp.target map_entries([[MAP1]] -> {{%.*}} : memref) { @@ -2583,8 +2582,8 @@ func.func @omp_target_enter_update_exit_data_depend(%a: memref, %b: memre } // Copy the updated 'a' onto the target - // CHECK: omp.target_update nowait motion_entries([[MAP0]] : memref) depend(taskdependin -> [[ARG0]] : memref) - omp.target_update motion_entries(%map_a : memref) depend(taskdependin -> %a : memref) nowait + // CHECK: omp.target_update depend(taskdependin -> [[ARG0]] : memref) nowait map_entries([[MAP0]] : memref) + omp.target_update depend(taskdependin -> %a : memref) nowait map_entries(%map_a : memref) // Compute 'c' on the target and copy it back %map_c_from = omp.map.info var_ptr(%c: memref, tensor) map_clauses(from) capture(ByRef) -> memref @@ -2593,8 +2592,8 @@ func.func @omp_target_enter_update_exit_data_depend(%a: memref, %b: memre "test.foobar"() : ()->() omp.terminator } - // CHECK: omp.target_exit_data map_entries([[MAP2]] : memref) depend(taskdependin -> [[ARG2]] : memref) - omp.target_exit_data map_entries(%map_c : memref) depend(taskdependin -> %c : memref) + // CHECK: omp.target_exit_data depend(taskdependin -> [[ARG2]] : memref) map_entries([[MAP2]] : memref) + omp.target_exit_data depend(taskdependin -> %c : memref) map_entries(%map_c : memref) return } diff --git a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir index 18189ea639816..bf9fa183bfb80 100644 --- a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir @@ -110,7 +110,7 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { %22 = llvm.mlir.constant(1 : index) : i64 %23 = omp.map.bounds lower_bound(%20 : i64) upper_bound(%19 : i64) extent(%21 : i64) stride(%22 : i64) start_idx(%22 : i64) %map2 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%23) -> !llvm.ptr {name = ""} - omp.target_enter_data if(%12 : i1) device(%13 : i32) map_entries(%map1, %map2 : !llvm.ptr, !llvm.ptr) + omp.target_enter_data if(%12) device(%13 : i32) map_entries(%map1, %map2 : !llvm.ptr, !llvm.ptr) %24 = llvm.load %7 : !llvm.ptr -> i32 %25 = llvm.mlir.constant(10 : i32) : i32 %26 = llvm.icmp "sgt" %24, %25 : i32 @@ -127,7 +127,7 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { %36 = llvm.mlir.constant(1 : index) : i64 %37 = omp.map.bounds lower_bound(%34 : i64) upper_bound(%33 : i64) extent(%35 : i64) stride(%36 : i64) start_idx(%36 : i64) %map4 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%37) -> !llvm.ptr {name = ""} - omp.target_exit_data if(%26 : i1) device(%27 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr) + omp.target_exit_data if(%26) device(%27 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr) llvm.return } @@ -457,7 +457,7 @@ llvm.func @_QPopenmp_target_data_update() { omp.terminator } - omp.target_update motion_entries(%2 : !llvm.ptr) + omp.target_update map_entries(%2 : !llvm.ptr) llvm.return } diff --git a/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir index f0d88f5c13536..1e2fbe86d13c4 100644 --- a/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir @@ -6,7 +6,7 @@ llvm.func @_QPopenmp_target_data_update() { %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: error: `nowait` is not supported yet - omp.target_update motion_entries(%2 : !llvm.ptr) nowait + omp.target_update map_entries(%2 : !llvm.ptr) nowait llvm.return } diff --git a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir index f22bc12d6b94c..a714e594d7812 100644 --- a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir @@ -44,7 +44,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo %5 = llvm.load %arg2 : !llvm.ptr -> i32 %6 = llvm.mlir.constant(0 : i64) : i32 %7 = llvm.icmp "ne" %5, %6 : i32 - omp.parallel if(%7 : i1) { + omp.parallel if(%7) { llvm.store %4, %arg1 : i32, !llvm.ptr omp.terminator } @@ -94,7 +94,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo // // This test checks if MLIR expression: // %7 = llvm.icmp "ne" %5, %6 : i32 -// omp.parallel if(%7 : i1) +// omp.parallel if(%7) // is correctly lowered to LLVM IR code and the if condition variable // is passed as a param to kmpc_parallel_51 function diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir index 7c6ab21e21c60..321de67aa48a1 100644 --- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -164,7 +164,7 @@ llvm.func @test_omp_parallel_if_1(%arg0: i32) -> () { // CHECK: br label %[[OUTLINED_EXIT_IF_1:.*]] // CHECK: [[OUTLINED_EXIT_IF_1]]: // CHECK: br label %[[RETURN_BLOCK_IF_1:.*]] - omp.parallel if(%1 : i1) { + omp.parallel if(%1) { omp.barrier omp.terminator }