MLIR 23.0.0git
OpenACCUtilsReduction.cpp
Go to the documentation of this file.
1//===- OpenACCUtilsReduction.cpp - OpenACC reduction utilities ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13#include "llvm/Support/raw_ostream.h"
14
15using namespace mlir;
16
17namespace mlir {
18namespace acc {
19
20static bool isFloatOrComplexType(Type ty) {
21 return isa<FloatType, ComplexType>(ty);
22}
23
25getReductionCombineParDims(ReductionCombineOp reductionCombineOp) {
26 if (GPUParallelDimsAttr parDimsAttr = getParDimsAttr(reductionCombineOp))
27 return SmallVector<GPUParallelDimAttr>(parDimsAttr.getArray());
28 llvm_unreachable(
29 "expected parallel dimensions attribute for reduction combine op");
30}
31
33getReductionCombineParDims(ReductionCombineRegionOp combineRegionOp) {
34 for (Operation *user : combineRegionOp.getSrcVar().getUsers()) {
35 if (auto accumulateOp = dyn_cast<ReductionAccumulateOp>(user))
37 accumulateOp.getParDims().getArray());
38 }
39 if (GPUParallelDimsAttr parDimsAttr = getParDimsAttr(combineRegionOp))
40 return SmallVector<GPUParallelDimAttr>(parDimsAttr.getArray());
41 return {};
42}
43
44ReductionOperator translateAtomicRMWKind(arith::AtomicRMWKind kind) {
45 switch (kind) {
46 case arith::AtomicRMWKind::addf:
47 case arith::AtomicRMWKind::addi:
48 return ReductionOperator::AccAdd;
49 case arith::AtomicRMWKind::mulf:
50 case arith::AtomicRMWKind::muli:
51 return ReductionOperator::AccMul;
52 case arith::AtomicRMWKind::maxs:
53 case arith::AtomicRMWKind::maxu:
54 case arith::AtomicRMWKind::maximumf:
55 case arith::AtomicRMWKind::maxnumf:
56 return ReductionOperator::AccMax;
57 case arith::AtomicRMWKind::minu:
58 case arith::AtomicRMWKind::mins:
59 case arith::AtomicRMWKind::minimumf:
60 case arith::AtomicRMWKind::minnumf:
61 return ReductionOperator::AccMin;
62 case arith::AtomicRMWKind::andi:
63 return ReductionOperator::AccIand;
64 case arith::AtomicRMWKind::ori:
65 return ReductionOperator::AccIor;
66 case arith::AtomicRMWKind::xori:
67 return ReductionOperator::AccXor;
68 case arith::AtomicRMWKind::assign:
69 break;
70 }
71 llvm_unreachable("unsupported atomic kind");
72}
73
74std::optional<arith::AtomicRMWKind>
75translateACCReductionOperator(ReductionOperator redOp, Type type) {
76 if (type.isInteger() && type.isUnsignedInteger())
77 return std::nullopt;
78
79 if (auto reducible = dyn_cast<ReducibleType>(type)) {
80 if (std::optional<arith::AtomicRMWKind> kind =
81 reducible.getAtomicRMWKind(redOp))
82 return kind;
83 return std::nullopt;
84 }
85
86 switch (redOp) {
87 case ReductionOperator::AccAdd:
88 if (type.isInteger())
89 return arith::AtomicRMWKind::addi;
90 if (isFloatOrComplexType(type))
91 return arith::AtomicRMWKind::addf;
92 break;
93 case ReductionOperator::AccMul:
94 if (type.isInteger())
95 return arith::AtomicRMWKind::muli;
96 if (isFloatOrComplexType(type))
97 return arith::AtomicRMWKind::mulf;
98 break;
99 case ReductionOperator::AccMax:
100 if (type.isInteger())
101 return arith::AtomicRMWKind::maxs;
102 if (type.isFloat())
103 return arith::AtomicRMWKind::maxnumf;
104 break;
105 case ReductionOperator::AccMaximumf:
106 return arith::AtomicRMWKind::maximumf;
107 case ReductionOperator::AccMaxnumf:
108 return arith::AtomicRMWKind::maxnumf;
109 case ReductionOperator::AccMin:
110 if (type.isInteger())
111 return arith::AtomicRMWKind::mins;
112 if (type.isFloat())
113 return arith::AtomicRMWKind::minnumf;
114 break;
115 case ReductionOperator::AccMinimumf:
116 return arith::AtomicRMWKind::minimumf;
117 case ReductionOperator::AccMinnumf:
118 return arith::AtomicRMWKind::minnumf;
119 case ReductionOperator::AccIand:
120 case ReductionOperator::AccLand:
121 if (type.isInteger())
122 return arith::AtomicRMWKind::andi;
123 break;
124 case ReductionOperator::AccIor:
125 case ReductionOperator::AccLor:
126 if (type.isInteger())
127 return arith::AtomicRMWKind::ori;
128 break;
129 case ReductionOperator::AccXor:
130 case ReductionOperator::AccNeqv:
131 if (type.isInteger())
132 return arith::AtomicRMWKind::xori;
133 break;
134 case ReductionOperator::AccEqv:
135 case ReductionOperator::AccNone:
136 break;
137 }
138 return std::nullopt;
139}
140
141static TypedAttr getReductionIdentityValueAttr(arith::AtomicRMWKind kind,
142 Type type, OpBuilder &builder,
143 Location loc,
144 bool useOnlyFiniteValue) {
145 if (type.isIntOrIndexOrFloat()) {
146 TypedAttr attr = arith::getIdentityValueAttr(kind, type, builder, loc,
147 useOnlyFiniteValue);
148 if (!attr)
149 emitError(loc) << "reduction identity: operator not supported " << kind;
150 return attr;
151 }
152 if (auto complexTy = dyn_cast<ComplexType>(type)) {
153 auto eltTy = dyn_cast<FloatType>(complexTy.getElementType());
154 if (!eltTy) {
155 emitError(loc) << "reduction identity: complex with non-floating "
156 "element type";
157 return nullptr;
158 }
159 switch (kind) {
160 case arith::AtomicRMWKind::addf: {
161 TypedAttr scalarAttr = arith::getIdentityValueAttr(
162 kind, eltTy, builder, loc, useOnlyFiniteValue);
163 assert(scalarAttr && "expected scalar identity for complex reduction");
164 double d = cast<FloatAttr>(scalarAttr).getValue().convertToDouble();
165 return complex::NumberAttr::get(complexTy, d, d);
166 }
167 case arith::AtomicRMWKind::mulf: {
168 TypedAttr scalarAttr = arith::getIdentityValueAttr(
169 kind, eltTy, builder, loc, useOnlyFiniteValue);
170 assert(scalarAttr &&
171 "expected scalar identity for complex mulf reduction");
172 auto realPart = cast<FloatAttr>(scalarAttr).getValue();
173 return complex::NumberAttr::get(complexTy, realPart.convertToDouble(),
174 0.0);
175 }
176 default:
177 emitError(loc)
178 << "reduction identity: operator not supported for complex " << kind;
179 return nullptr;
180 }
181 }
182 emitError(loc) << "reduction identity: type not supported " << type;
183 return nullptr;
184}
185
187 arith::AtomicRMWKind kind, bool useOnlyFiniteValue) {
188 TypedAttr typedAttr =
189 getReductionIdentityValueAttr(kind, type, b, loc, useOnlyFiniteValue);
190 assert(typedAttr && "expected identity attribute");
191 if (auto numAttr = dyn_cast<complex::NumberAttr>(typedAttr)) {
192 auto complexTy = cast<ComplexType>(numAttr.getType());
193 auto floatElt = cast<FloatType>(complexTy.getElementType());
194 Value realVal = arith::ConstantOp::create(
195 b, loc, b.getFloatAttr(floatElt, numAttr.getReal()));
196 Value imagVal = arith::ConstantOp::create(
197 b, loc, b.getFloatAttr(floatElt, numAttr.getImag()));
198 return complex::CreateOp::create(b, loc, complexTy, realVal, imagVal);
199 }
200 return arith::ConstantOp::create(b, loc, typedAttr);
201}
202
204 arith::AtomicRMWKind kind) {
205 assert(lhs.getType() == rhs.getType() &&
206 "expected same type for lhs and rhs");
207 if (isa<ComplexType>(lhs.getType())) {
208 switch (kind) {
209 case arith::AtomicRMWKind::addf:
210 return complex::AddOp::create(b, loc, lhs, rhs);
211 case arith::AtomicRMWKind::mulf:
212 return complex::MulOp::create(b, loc, lhs, rhs);
213 default:
214 llvm_unreachable("unsupported complex atomic reduction kind");
215 }
216 }
217 return arith::getReductionOp(kind, b, loc, lhs, rhs);
218}
219
220} // namespace acc
221} // namespace mlir
lhs
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:209
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
user_range getUsers()
Returns a range of all users.
Definition Operation.h:898
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
bool isFloat() const
Return true if this is an float type (with the specified width).
Definition Types.cpp:47
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
Definition Types.cpp:122
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
Definition Types.cpp:90
bool isInteger() const
Return true if this is an integer type (with the specified width).
Definition Types.cpp:58
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
GPUParallelDimsAttr getParDimsAttr(Operation *op)
Obtain the parallel dimensions carried by op, if any.
static TypedAttr getReductionIdentityValueAttr(arith::AtomicRMWKind kind, Type type, OpBuilder &builder, Location loc, bool useOnlyFiniteValue)
SmallVector< GPUParallelDimAttr > getReductionCombineParDims(ReductionCombineOp op)
Returns the parallel dimensions that participate in op's combine step.
std::optional< arith::AtomicRMWKind > translateACCReductionOperator(ReductionOperator redOp, Type type)
Maps an acc reduction operator to the arith atomic RMW kind for type.
ReductionOperator translateAtomicRMWKind(arith::AtomicRMWKind kind)
Maps an arith atomic RMW kind to the corresponding acc reduction operator.
static bool isFloatOrComplexType(Type ty)
Value createIdentityValue(OpBuilder &b, Location loc, Type type, arith::AtomicRMWKind kind, bool useOnlyFiniteValue=true)
Creates the identity (neutral) value for a reduction of type and kind.
Value generateReductionOp(OpBuilder &b, Location loc, Value lhs, Value rhs, arith::AtomicRMWKind kind)
Combines two reduction partial values using the operator for kind.
TypedAttr getIdentityValueAttr(AtomicRMWKind kind, Type resultType, OpBuilder &builder, Location loc, bool useOnlyFiniteValue=false)
Returns the identity value attribute associated with an AtomicRMWKind op.
Value getReductionOp(AtomicRMWKind op, OpBuilder &builder, Location loc, Value lhs, Value rhs)
Returns the value obtained by applying the reduction operation kind associated with a binary AtomicRM...
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.