1717include "mlir/IR/OpBase.td"
1818include "mlir/Interfaces/SideEffectInterfaces.td"
1919include "mlir/Interfaces/ControlFlowInterfaces.td"
20- include "mlir/Dialect/LLVMIR/LLVMOpBase .td"
20+ include "mlir/IR/SymbolInterfaces .td"
2121include "mlir/Dialect/OpenMP/OmpCommon.td"
2222include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td"
23+ include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
2324
2425def OpenMP_Dialect : Dialect {
2526 let name = "omp";
2627 let cppNamespace = "::mlir::omp";
28+ let dependentDialects = ["::mlir::LLVM::LLVMDialect"];
2729}
2830
2931class OpenMP_Op<string mnemonic, list<OpTrait> traits = []> :
@@ -33,6 +35,27 @@ class OpenMP_Op<string mnemonic, list<OpTrait> traits = []> :
3335// LLVM integer types.
3436def IntLikeType : AnyTypeOf<[AnyInteger, Index, LLVM_AnyInteger]>;
3537
38+ def OpenMP_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> {
39+ let cppNamespace = "::mlir::omp";
40+
41+ let description = [{
42+ An interface for pointer-like types suitable to contain a value that OpenMP
43+ specification refers to as variable.
44+ }];
45+
46+ let methods = [
47+ InterfaceMethod<
48+ /*description=*/"Returns the pointee type.",
49+ /*retTy=*/"::mlir::Type",
50+ /*methodName=*/"getElementType"
51+ >,
52+ ];
53+ }
54+
55+ def OpenMP_PointerLikeType : Type<
56+ CPred<"$_self.isa<::mlir::omp::PointerLikeType>()">,
57+ "OpenMP-compatible variable type", "::mlir::omp::PointerLikeType">;
58+
3659//===----------------------------------------------------------------------===//
3760// 2.6 parallel Construct
3861//===----------------------------------------------------------------------===//
@@ -163,6 +186,18 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
163186 that the `linear_vars` and `linear_step_vars` variadic lists should contain
164187 the same number of elements.
165188
189+ Reductions can be performed in a workshare loop by specifying reduction
190+ accumulator variables in `reduction_vars` and symbols referring to reduction
191+ declarations in the `reductions` attribute. Each reduction is identified
192+ by the accumulator it uses and accumulators must not be repeated in the same
193+ reduction. The `omp.reduction` operation accepts the accumulator and a
194+ partial value which is considered to be produced by the current loop
195+ iteration for the given reduction. If multiple values are produced for the
196+ same accumulator, i.e. there are multiple `omp.reduction`s, the last value
197+ is taken. The reduction declaration specifies how to combine the values from
198+ each iteration into the final value, which is available in the accumulator
199+ after the loop completes.
200+
166201 The optional `schedule_val` attribute specifies the loop schedule for this
167202 loop, determining how the loop is distributed across the parallel threads.
168203 The optional `schedule_chunk_var` associated with this determines further
@@ -190,6 +225,9 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
190225 Variadic<AnyType>:$lastprivate_vars,
191226 Variadic<AnyType>:$linear_vars,
192227 Variadic<AnyType>:$linear_step_vars,
228+ Variadic<OpenMP_PointerLikeType>:$reduction_vars,
229+ OptionalAttr<TypedArrayAttrBase<SymbolRefAttr,
230+ "array of symbol references">>:$reductions,
193231 OptionalAttr<ScheduleKind>:$schedule_val,
194232 Optional<AnyType>:$schedule_chunk_var,
195233 OptionalAttr<ScheduleModifier>:$schedule_modifiers,
@@ -210,11 +248,11 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
210248 "ValueRange":$upperBound, "ValueRange":$step,
211249 "ValueRange":$privateVars, "ValueRange":$firstprivateVars,
212250 "ValueRange":$lastprivate_vars, "ValueRange":$linear_vars,
213- "ValueRange":$linear_step_vars, "StringAttr ":$schedule_val ,
214- "Value ":$schedule_chunk_var , "IntegerAttr ":$collapse_val ,
215- "UnitAttr ":$nowait , "IntegerAttr ":$ordered_val ,
216- "StringAttr ":$order_val , "UnitAttr ":$inclusive, CArg<"bool" ,
217- "true">:$buildBody)>,
251+ "ValueRange":$linear_step_vars, "ValueRange ":$reduction_vars ,
252+ "StringAttr ":$schedule_val , "Value ":$schedule_chunk_var ,
253+ "IntegerAttr ":$collapse_val , "UnitAttr ":$nowait ,
254+ "IntegerAttr ":$ordered_val , "StringAttr ":$order_val ,
255+ "UnitAttr":$inclusive, CArg<"bool", " true">:$buildBody)>,
218256 OpBuilder<(ins "TypeRange":$resultTypes, "ValueRange":$operands,
219257 CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes)>
220258 ];
@@ -224,13 +262,18 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
224262 let extraClassDeclaration = [{
225263 /// Returns the number of loops in the workshape loop nest.
226264 unsigned getNumLoops() { return lowerBound().size(); }
265+
266+ /// Returns the number of reduction variables.
267+ unsigned getNumReductionVars() { return reduction_vars().size(); }
227268 }];
228269 let parser = [{ return parseWsLoopOp(parser, result); }];
229270 let printer = [{ return printWsLoopOp(p, *this); }];
271+ let verifier = [{ return ::verifyWsLoopOp(*this); }];
230272}
231273
232- def YieldOp : OpenMP_Op<"yield", [NoSideEffect, ReturnLike, Terminator,
233- HasParent<"WsLoopOp">]> {
274+ def YieldOp : OpenMP_Op<"yield",
275+ [NoSideEffect, ReturnLike, Terminator,
276+ ParentOneOf<["WsLoopOp", "ReductionDeclareOp"]>]> {
234277 let summary = "loop yield and termination operation";
235278 let description = [{
236279 "omp.yield" yields SSA values from the OpenMP dialect op region and
@@ -319,4 +362,78 @@ def TaskwaitOp : OpenMP_Op<"taskwait"> {
319362 let assemblyFormat = "attr-dict";
320363}
321364
365+ //===----------------------------------------------------------------------===//
366+ // 2.19.5.7 declare reduction Directive
367+ //===----------------------------------------------------------------------===//
368+
369+ def ReductionDeclareOp : OpenMP_Op<"reduction.declare", [Symbol]> {
370+ let summary = "declares a reduction kind";
371+
372+ let description = [{
373+ Declares an OpenMP reduction kind. This requires two mandatory and one
374+ optional region.
375+
376+ 1. The initializer region specifies how to initialize the thread-local
377+ reduction value. This is usually the neutral element of the reduction.
378+ For convenience, the region has an argument that contains the value
379+ of the reduction accumulator at the start of the reduction. It is
380+ expected to `omp.yield` the new value on all control flow paths.
381+ 2. The reduction region specifies how to combine two values into one, i.e.
382+ the reduction operator. It accepts the two values as arguments and is
383+ expected to `omp.yield` the combined value on all control flow paths.
384+ 3. The atomic reduction region is optional and specifies how two values
385+ can be combined atomically given local accumulator variables. It is
386+ expected to store the combined value in the first accumulator variable.
387+
388+ Note that the MLIR type system does not allow for type-polymorphic
389+ reductions. Separate reduction declarations should be created for different
390+ element and accumulator types.
391+ }];
392+
393+ let arguments = (ins SymbolNameAttr:$sym_name,
394+ TypeAttr:$type);
395+
396+ let regions = (region AnyRegion:$initializerRegion,
397+ AnyRegion:$reductionRegion,
398+ AnyRegion:$atomicReductionRegion);
399+ let verifier = "return ::verifyReductionDeclareOp(*this);";
400+
401+ let assemblyFormat = "$sym_name `:` $type attr-dict-with-keyword "
402+ "`init` $initializerRegion "
403+ "`combiner` $reductionRegion "
404+ "custom<AtomicReductionRegion>($atomicReductionRegion)";
405+
406+ let extraClassDeclaration = [{
407+ PointerLikeType getAccumulatorType() {
408+ if (atomicReductionRegion().empty())
409+ return {};
410+
411+ return atomicReductionRegion().front().getArgument(0).getType();
412+ }
413+ }];
414+ }
415+
416+ //===----------------------------------------------------------------------===//
417+ // 2.19.5.4 reduction clause
418+ //===----------------------------------------------------------------------===//
419+
420+ def ReductionOp : OpenMP_Op<"reduction", [
421+ TypesMatchWith<"value types matches accumulator element type",
422+ "accumulator", "operand",
423+ "$_self.cast<::mlir::omp::PointerLikeType>().getElementType()">
424+ ]> {
425+ let summary = "reduction construct";
426+ let description = [{
427+ Indicates the value that is produced by the current reduction-participating
428+ entity for a reduction requested in some ancestor. The reduction is
429+ identified by the accumulator, but the value of the accumulator may not be
430+ updated immediately.
431+ }];
432+
433+ let arguments= (ins AnyType:$operand, OpenMP_PointerLikeType:$accumulator);
434+ let assemblyFormat =
435+ "$operand `,` $accumulator attr-dict `:` type($accumulator)";
436+ let verifier = "return ::verifyReductionOp(*this);";
437+ }
438+
322439#endif // OPENMP_OPS
0 commit comments