13#include "llvm/Support/raw_ostream.h"
21 return isa<FloatType, ComplexType>(ty);
26 if (GPUParallelDimsAttr parDimsAttr =
getParDimsAttr(reductionCombineOp))
29 "expected parallel dimensions attribute for reduction combine op");
35 if (
auto accumulateOp = dyn_cast<ReductionAccumulateOp>(user))
37 accumulateOp.getParDims().getArray());
39 if (GPUParallelDimsAttr parDimsAttr =
getParDimsAttr(combineRegionOp))
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:
71 llvm_unreachable(
"unsupported atomic kind");
74std::optional<arith::AtomicRMWKind>
79 if (
auto reducible = dyn_cast<ReducibleType>(type)) {
80 if (std::optional<arith::AtomicRMWKind> kind =
81 reducible.getAtomicRMWKind(redOp))
87 case ReductionOperator::AccAdd:
89 return arith::AtomicRMWKind::addi;
91 return arith::AtomicRMWKind::addf;
93 case ReductionOperator::AccMul:
95 return arith::AtomicRMWKind::muli;
97 return arith::AtomicRMWKind::mulf;
99 case ReductionOperator::AccMax:
101 return arith::AtomicRMWKind::maxs;
103 return arith::AtomicRMWKind::maxnumf;
105 case ReductionOperator::AccMaximumf:
106 return arith::AtomicRMWKind::maximumf;
107 case ReductionOperator::AccMaxnumf:
108 return arith::AtomicRMWKind::maxnumf;
109 case ReductionOperator::AccMin:
111 return arith::AtomicRMWKind::mins;
113 return arith::AtomicRMWKind::minnumf;
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:
122 return arith::AtomicRMWKind::andi;
124 case ReductionOperator::AccIor:
125 case ReductionOperator::AccLor:
127 return arith::AtomicRMWKind::ori;
129 case ReductionOperator::AccXor:
130 case ReductionOperator::AccNeqv:
132 return arith::AtomicRMWKind::xori;
134 case ReductionOperator::AccEqv:
135 case ReductionOperator::AccNone:
144 bool useOnlyFiniteValue) {
149 emitError(loc) <<
"reduction identity: operator not supported " << kind;
152 if (
auto complexTy = dyn_cast<ComplexType>(type)) {
153 auto eltTy = dyn_cast<FloatType>(complexTy.getElementType());
155 emitError(loc) <<
"reduction identity: complex with non-floating "
160 case arith::AtomicRMWKind::addf: {
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);
167 case arith::AtomicRMWKind::mulf: {
169 kind, eltTy, builder, loc, useOnlyFiniteValue);
171 "expected scalar identity for complex mulf reduction");
172 auto realPart = cast<FloatAttr>(scalarAttr).getValue();
173 return complex::NumberAttr::get(complexTy, realPart.convertToDouble(),
178 <<
"reduction identity: operator not supported for complex " << kind;
182 emitError(loc) <<
"reduction identity: type not supported " << type;
187 arith::AtomicRMWKind kind,
bool useOnlyFiniteValue) {
188 TypedAttr typedAttr =
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);
200 return arith::ConstantOp::create(
b, loc, typedAttr);
204 arith::AtomicRMWKind kind) {
205 assert(
lhs.getType() ==
rhs.getType() &&
206 "expected same type for lhs and rhs");
207 if (isa<ComplexType>(
lhs.getType())) {
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);
214 llvm_unreachable(
"unsupported complex atomic reduction kind");
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
user_range getUsers()
Returns a range of all users.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isFloat() const
Return true if this is an float type (with the specified width).
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isInteger() const
Return true if this is an integer type (with the specified width).
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
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.