This makes the op consistent with other ops in vector dialect.
Differential Revision: https://reviews.llvm.org/D119343
Vector_Op<"reduction", [NoSideEffect,
PredOpTrait<"source operand and result have same element type",
TCresVTEtIsSameAsOpBase<0, 0>>]>,
- Arguments<(ins StrAttr:$kind, AnyVector:$vector, Variadic<AnyType>:$acc)>,
+ Arguments<(ins Vector_CombiningKindAttr:$kind, AnyVector:$vector,
+ Optional<AnyType>:$acc)>,
Results<(outs AnyType:$dest)> {
let summary = "reduction operation";
let description = [{
Example:
```mlir
- %1 = vector.reduction "add", %0 : vector<16xf32> into f32
+ %1 = vector.reduction <add>, %0 : vector<16xf32> into f32
- %3 = vector.reduction "xor", %2 : vector<4xi32> into i32
+ %3 = vector.reduction <xor>, %2 : vector<4xi32> into i32
- %4 = vector.reduction "mul", %0, %1 : vector<16xf32> into f32
+ %4 = vector.reduction <mul>, %0, %1 : vector<16xf32> into f32
```
}];
let extraClassDeclaration = [{
return vector().getType().cast<VectorType>();
}
}];
+ let builders = [
+ // Builder that infers the type of `dest`.
+ OpBuilder<(ins "CombiningKind":$kind, "Value":$vector, "Value":$acc)>,
+ // Builder that infers the type of `dest` and has no accumulator.
+ OpBuilder<(ins "CombiningKind":$kind, "Value":$vector)>
+ ];
+
+ // TODO: Migrate to assemblyFormat once `AllTypesMatch` supports optional
+ // operands.
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
Example:
```mlir
- %1 = vector.multi_reduction "add", %0 [1, 3] :
+ %1 = vector.multi_reduction <add>, %0 [1, 3] :
vector<4x8x16x32xf32> into vector<4x16xf32>
- %2 = vector.multi_reduction "add", %1 [0, 1] :
+ %2 = vector.multi_reduction <add>, %1 [0, 1] :
vector<4x16xf32> into f32
```
}];
Value operand = adaptor.getOperands()[0];
if (eltType.isIntOrIndex()) {
// Integer reductions: add/mul/min/max/and/or/xor.
- if (kind == "add")
+ if (kind == vector::CombiningKind::ADD)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_add>(reductionOp,
llvmType, operand);
- else if (kind == "mul")
+ else if (kind == vector::CombiningKind::MUL)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_mul>(reductionOp,
llvmType, operand);
- else if (kind == "minui")
+ else if (kind == vector::CombiningKind::MINUI)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_umin>(
reductionOp, llvmType, operand);
- else if (kind == "minsi")
+ else if (kind == vector::CombiningKind::MINSI)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_smin>(
reductionOp, llvmType, operand);
- else if (kind == "maxui")
+ else if (kind == vector::CombiningKind::MAXUI)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_umax>(
reductionOp, llvmType, operand);
- else if (kind == "maxsi")
+ else if (kind == vector::CombiningKind::MAXSI)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_smax>(
reductionOp, llvmType, operand);
- else if (kind == "and")
+ else if (kind == vector::CombiningKind::AND)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_and>(reductionOp,
llvmType, operand);
- else if (kind == "or")
+ else if (kind == vector::CombiningKind::OR)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_or>(reductionOp,
llvmType, operand);
- else if (kind == "xor")
+ else if (kind == vector::CombiningKind::XOR)
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_xor>(reductionOp,
llvmType, operand);
else
return failure();
// Floating-point reductions: add/mul/min/max
- if (kind == "add") {
+ if (kind == vector::CombiningKind::ADD) {
// Optional accumulator (or zero).
Value acc = adaptor.getOperands().size() > 1
? adaptor.getOperands()[1]
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_fadd>(
reductionOp, llvmType, acc, operand,
rewriter.getBoolAttr(reassociateFPReductions));
- } else if (kind == "mul") {
+ } else if (kind == vector::CombiningKind::MUL) {
// Optional accumulator (or one).
Value acc = adaptor.getOperands().size() > 1
? adaptor.getOperands()[1]
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_fmul>(
reductionOp, llvmType, acc, operand,
rewriter.getBoolAttr(reassociateFPReductions));
- } else if (kind == "minf")
+ } else if (kind == vector::CombiningKind::MINF)
// FIXME: MLIR's 'minf' and LLVM's 'vector_reduce_fmin' do not handle
// NaNs/-0.0/+0.0 in the same way.
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_fmin>(reductionOp,
llvmType, operand);
- else if (kind == "maxf")
+ else if (kind == vector::CombiningKind::MAXF)
// FIXME: MLIR's 'maxf' and LLVM's 'vector_reduce_fmax' do not handle
// NaNs/-0.0/+0.0 in the same way.
rewriter.replaceOpWithNewOp<LLVM::vector_reduce_fmax>(reductionOp,
/// %7 = select %3, %6, %arg2 : vector<128xi1>, vector<128xf32>
/// affine.yield %7 : vector<128xf32>
/// }
-/// %1 = vector.reduction "add", %0 : vector<128xf32> into f32
+/// %1 = vector.reduction <add>, %0 : vector<128xf32> into f32
/// return %1 : f32
/// }
/// ```
///
/// Example 2:
/// * 'replaced': %0 = affine.for %i = 0 to 512 iter_args(%x = ...) -> (f32)
- /// * 'replacement': %1 = vector.reduction "add" %0 : vector<4xf32> into f32
+ /// * 'replacement': %1 = vector.reduction <add>, %0 : vector<4xf32> into
+ /// f32
void registerLoopResultScalarReplacement(Value replaced, Value replacement);
/// Returns in 'replacedVals' the scalar replacement for values in
///
/// Example 2:
/// * 'replaced': %0 = affine.for %i = 0 to 512 iter_args(%x = ...) -> (f32)
-/// * 'replacement': %1 = vector.reduction "add" %0 : vector<4xf32> into f32
+/// * 'replacement': %1 = vector.reduction <add>, %0 : vector<4xf32> into f32
void VectorizationState::registerLoopResultScalarReplacement(
Value replaced, Value replacement) {
assert(isa<AffineForOp>(replaced.getDefiningOp()));
// Sparse compiler synthesis methods (reductions).
//===----------------------------------------------------------------------===//
-/// Maps reduction kind to name encoding.
-static StringRef getReductionName(Reduction kind) {
+/// Maps reduction kind to vector::CombiningKind.
+static vector::CombiningKind getCombiningKind(Reduction kind) {
switch (kind) {
case kNoReduc:
break;
case kSum:
- return "add";
+ return vector::CombiningKind::ADD;
case kProduct:
- return "mul";
+ return vector::CombiningKind::MUL;
case kAnd:
- return "and";
+ return vector::CombiningKind::AND;
case kOr:
- return "or";
+ return vector::CombiningKind::OR;
case kXor:
- return "xor";
+ return vector::CombiningKind::XOR;
}
llvm_unreachable("unknown reduction kind");
}
/// Generates final value for a vector reduction.
static Value genVectorReducEnd(CodeGen &codegen, PatternRewriter &rewriter,
Location loc, VectorType vtp) {
- StringRef name = getReductionName(codegen.redKind);
- StringAttr kind = rewriter.getStringAttr(name);
- return rewriter.create<vector::ReductionOp>(loc, vtp.getElementType(), kind,
- codegen.redVal, ValueRange{});
+ vector::CombiningKind kind = getCombiningKind(codegen.redKind);
+ return rewriter.create<vector::ReductionOp>(loc, kind, codegen.redVal);
}
/// Updates scalarized reduction value.
// ReductionOp
//===----------------------------------------------------------------------===//
+void vector::ReductionOp::build(OpBuilder &builder, OperationState &result,
+ CombiningKind kind, Value vector) {
+ build(builder, result, kind, vector, /*acc=*/Value());
+}
+
+void vector::ReductionOp::build(OpBuilder &builder, OperationState &result,
+ CombiningKind kind, Value vector, Value acc) {
+ build(builder, result, vector.getType().cast<VectorType>().getElementType(),
+ kind, vector, acc);
+}
+
LogicalResult ReductionOp::verify() {
// Verify for 1-D vector.
int64_t rank = getVectorType().getRank();
return emitOpError("unsupported reduction rank: ") << rank;
// Verify supported reduction kind.
- StringRef strKind = kind();
- auto maybeKind = symbolizeCombiningKind(strKind);
- if (!maybeKind)
- return emitOpError("unknown reduction kind: ") << strKind;
-
Type eltType = dest().getType();
- if (!isSupportedCombiningKind(*maybeKind, eltType))
+ if (!isSupportedCombiningKind(kind(), eltType))
return emitOpError("unsupported reduction type '")
- << eltType << "' for kind '" << strKind << "'";
+ << eltType << "' for kind '" << stringifyCombiningKind(kind())
+ << "'";
// Verify optional accumulator.
- if (!acc().empty()) {
- if (strKind != "add" && strKind != "mul")
- return emitOpError("no accumulator for reduction kind: ") << strKind;
+ if (acc()) {
+ if (kind() != CombiningKind::ADD && kind() != CombiningKind::MUL)
+ return emitOpError("no accumulator for reduction kind: ")
+ << stringifyCombiningKind(kind());
if (!eltType.isa<FloatType>())
return emitOpError("no accumulator for type: ") << eltType;
}
SmallVector<OpAsmParser::OperandType, 2> operandsInfo;
Type redType;
Type resType;
- Attribute attr;
- if (parser.parseAttribute(attr, "kind", result.attributes) ||
+ CombiningKindAttr kindAttr;
+ if (parser.parseCustomAttributeWithFallback(kindAttr, Type{}, "kind",
+ result.attributes) ||
parser.parseComma() || parser.parseOperandList(operandsInfo) ||
parser.parseColonType(redType) ||
parser.parseKeywordType("into", resType) ||
}
void ReductionOp::print(OpAsmPrinter &p) {
- p << " \"" << kind() << "\", " << vector();
- if (!acc().empty())
+ p << " ";
+ kindAttr().print(p);
+ p << ", " << vector();
+ if (acc())
p << ", " << acc();
p << " : " << vector().getType() << " into " << dest().getType();
}
Value mlir::vector::getVectorReductionOp(arith::AtomicRMWKind op,
OpBuilder &builder, Location loc,
Value vector) {
- Type scalarType = vector.getType().cast<ShapedType>().getElementType();
switch (op) {
case arith::AtomicRMWKind::addf:
case arith::AtomicRMWKind::addi:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("add"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::ADD, vector);
case arith::AtomicRMWKind::mulf:
case arith::AtomicRMWKind::muli:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("mul"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MUL, vector);
case arith::AtomicRMWKind::minf:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("minf"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MINF, vector);
case arith::AtomicRMWKind::mins:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("minsi"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MINSI, vector);
case arith::AtomicRMWKind::minu:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("minui"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MINUI, vector);
case arith::AtomicRMWKind::maxf:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("maxf"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MAXF, vector);
case arith::AtomicRMWKind::maxs:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("maxsi"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MAXSI, vector);
case arith::AtomicRMWKind::maxu:
- return builder.create<vector::ReductionOp>(vector.getLoc(), scalarType,
- builder.getStringAttr("maxui"),
- vector, ValueRange{});
+ return builder.create<vector::ReductionOp>(vector.getLoc(),
+ CombiningKind::MAXUI, vector);
// TODO: Add remaining reduction operations.
default:
(void)emitOptionalError(loc, "Reduction operation type not supported");
rewriter.getZeroAttr(multiReductionOp.getDestType()));
int outerDim = multiReductionOp.getSourceVectorType().getShape()[0];
- // TODO: Add vector::CombiningKind attribute instead of string to
- // vector.reduction.
- auto getKindStr = [](vector::CombiningKind kind) {
- switch (kind) {
- case vector::CombiningKind::ADD:
- return "add";
- case vector::CombiningKind::MUL:
- return "mul";
- case vector::CombiningKind::MINUI:
- return "minui";
- case vector::CombiningKind::MINSI:
- return "minsi";
- case vector::CombiningKind::MINF:
- return "minf";
- case vector::CombiningKind::MAXUI:
- return "maxui";
- case vector::CombiningKind::MAXSI:
- return "maxsi";
- case vector::CombiningKind::MAXF:
- return "maxf";
- case vector::CombiningKind::AND:
- return "and";
- case vector::CombiningKind::OR:
- return "or";
- case vector::CombiningKind::XOR:
- return "xor";
- }
- llvm_unreachable("unknown combining kind");
- };
-
for (int i = 0; i < outerDim; ++i) {
auto v = rewriter.create<vector::ExtractOp>(
loc, multiReductionOp.source(), ArrayRef<int64_t>{i});
- auto reducedValue = rewriter.create<vector::ReductionOp>(
- loc, getElementTypeOrSelf(multiReductionOp.getDestType()),
- rewriter.getStringAttr(getKindStr(multiReductionOp.kind())), v,
- ValueRange{});
+ auto reducedValue =
+ rewriter.create<vector::ReductionOp>(loc, multiReductionOp.kind(), v);
result = rewriter.create<vector::InsertElementOp>(
loc, reducedValue, result,
rewriter.create<arith::ConstantIndexOp>(loc, i));
: rewriter.create<vector::ExtractOp>(op.getLoc(), rhs, c);
Value m = createMul(op.getLoc(), a, b, isInt, rewriter);
Value reduced = rewriter.create<vector::ReductionOp>(
- op.getLoc(), dstType.getElementType(), rewriter.getStringAttr("add"),
- m, ValueRange{});
+ op.getLoc(), vector::CombiningKind::ADD, m);
SmallVector<int64_t, 2> pos = rank == 1 ? SmallVector<int64_t, 2>{r}
: SmallVector<int64_t, 2>{r, c};
if (lhsType.getRank() == 1) {
assert(rhsType.getRank() == 1 && "corrupt contraction");
Value m = createMul(loc, op.lhs(), op.rhs(), isInt, rewriter);
- StringAttr kind = rewriter.getStringAttr("add");
- Value res = rewriter.create<vector::ReductionOp>(loc, resType, kind, m,
- ValueRange{});
+ auto kind = vector::CombiningKind::ADD;
+ Value res = rewriter.create<vector::ReductionOp>(loc, kind, m);
if (auto acc = op.acc())
res = createAdd(op.getLoc(), res, acc, isInt, rewriter);
return res;
// REASSOC: return %[[V]] : f32
//
func @reduce_add_f32(%arg0: vector<16xf32>) -> f32 {
- %0 = vector.reduction "add", %arg0 : vector<16xf32> into f32
+ %0 = vector.reduction <add>, %arg0 : vector<16xf32> into f32
return %0 : f32
}
// REASSOC: return %[[V]] : f32
//
func @reduce_mul_f32(%arg0: vector<16xf32>) -> f32 {
- %0 = vector.reduction "mul", %arg0 : vector<16xf32> into f32
+ %0 = vector.reduction <mul>, %arg0 : vector<16xf32> into f32
return %0 : f32
}
// -----
func @reduce_f16(%arg0: vector<16xf16>) -> f16 {
- %0 = vector.reduction "add", %arg0 : vector<16xf16> into f16
+ %0 = vector.reduction <add>, %arg0 : vector<16xf16> into f16
return %0 : f16
}
// CHECK-LABEL: @reduce_f16(
// -----
func @reduce_f32(%arg0: vector<16xf32>) -> f32 {
- %0 = vector.reduction "add", %arg0 : vector<16xf32> into f32
+ %0 = vector.reduction <add>, %arg0 : vector<16xf32> into f32
return %0 : f32
}
// CHECK-LABEL: @reduce_f32(
// -----
func @reduce_f64(%arg0: vector<16xf64>) -> f64 {
- %0 = vector.reduction "add", %arg0 : vector<16xf64> into f64
+ %0 = vector.reduction <add>, %arg0 : vector<16xf64> into f64
return %0 : f64
}
// CHECK-LABEL: @reduce_f64(
// -----
func @reduce_i8(%arg0: vector<16xi8>) -> i8 {
- %0 = vector.reduction "add", %arg0 : vector<16xi8> into i8
+ %0 = vector.reduction <add>, %arg0 : vector<16xi8> into i8
return %0 : i8
}
// CHECK-LABEL: @reduce_i8(
// -----
func @reduce_i32(%arg0: vector<16xi32>) -> i32 {
- %0 = vector.reduction "add", %arg0 : vector<16xi32> into i32
+ %0 = vector.reduction <add>, %arg0 : vector<16xi32> into i32
return %0 : i32
}
// CHECK-LABEL: @reduce_i32(
// -----
func @reduce_i64(%arg0: vector<16xi64>) -> i64 {
- %0 = vector.reduction "add", %arg0 : vector<16xi64> into i64
+ %0 = vector.reduction <add>, %arg0 : vector<16xi64> into i64
return %0 : i64
}
// CHECK-LABEL: @reduce_i64(
// -----
func @reduce_index(%arg0: vector<16xindex>) -> index {
- %0 = vector.reduction "add", %arg0 : vector<16xindex> into index
+ %0 = vector.reduction <add>, %arg0 : vector<16xindex> into index
return %0 : index
}
// CHECK-LABEL: @reduce_index(
// CHECK: %[[add:.*]] = arith.addf %[[red_iter]], %[[ld]] : vector<128xf32>
// CHECK: affine.yield %[[add]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[min:.*]] = arith.minf %[[red_iter]], %[[ld]] : vector<128xf32>
// CHECK: affine.yield %[[min]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_min:.*]] = vector.reduction "minf", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_min:.*]] = vector.reduction <minf>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_min]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[max:.*]] = arith.maxf %[[red_iter]], %[[ld]] : vector<128xf32>
// CHECK: affine.yield %[[max]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_max:.*]] = vector.reduction "maxf", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_max:.*]] = vector.reduction <maxf>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_max]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[min:.*]] = arith.minsi %[[red_iter]], %[[ld]] : vector<128xi32>
// CHECK: affine.yield %[[min]] : vector<128xi32>
// CHECK: }
-// CHECK: %[[final_min:.*]] = vector.reduction "minsi", %[[vred:.*]] : vector<128xi32> into i32
+// CHECK: %[[final_min:.*]] = vector.reduction <minsi>, %[[vred:.*]] : vector<128xi32> into i32
// CHECK: affine.store %[[final_min]], %{{.*}} : memref<256xi32>
// CHECK: }
// CHECK: %[[max:.*]] = arith.maxsi %[[red_iter]], %[[ld]] : vector<128xi32>
// CHECK: affine.yield %[[max]] : vector<128xi32>
// CHECK: }
-// CHECK: %[[final_max:.*]] = vector.reduction "maxsi", %[[vred:.*]] : vector<128xi32> into i32
+// CHECK: %[[final_max:.*]] = vector.reduction <maxsi>, %[[vred:.*]] : vector<128xi32> into i32
// CHECK: affine.store %[[final_max]], %{{.*}} : memref<256xi32>
// CHECK: }
// CHECK: %[[min:.*]] = arith.minui %[[red_iter]], %[[ld]] : vector<128xi32>
// CHECK: affine.yield %[[min]] : vector<128xi32>
// CHECK: }
-// CHECK: %[[final_min:.*]] = vector.reduction "minui", %[[vred:.*]] : vector<128xi32> into i32
+// CHECK: %[[final_min:.*]] = vector.reduction <minui>, %[[vred:.*]] : vector<128xi32> into i32
// CHECK: affine.store %[[final_min]], %{{.*}} : memref<256xi32>
// CHECK: }
// CHECK: %[[max:.*]] = arith.maxui %[[red_iter]], %[[ld]] : vector<128xi32>
// CHECK: affine.yield %[[max]] : vector<128xi32>
// CHECK: }
-// CHECK: %[[final_max:.*]] = vector.reduction "maxui", %[[vred:.*]] : vector<128xi32> into i32
+// CHECK: %[[final_max:.*]] = vector.reduction <maxui>, %[[vred:.*]] : vector<128xi32> into i32
// CHECK: affine.store %[[final_max]], %{{.*}} : memref<256xi32>
// CHECK: }
// CHECK: %[[add:.*]] = arith.addf %[[ld]], %[[red_iter]] : vector<128xf32>
// CHECK: affine.yield %[[add]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[add:.*]] = arith.addf %[[red_iter]], %[[exp]] : vector<128xf32>
// CHECK: affine.yield %[[add]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[mul:.*]] = arith.mulf %[[part_prod]], %[[ld]] : vector<128xf32>
// CHECK: affine.yield %[[add]], %[[mul]] : vector<128xf32>, vector<128xf32>
// CHECK: }
-// CHECK: %[[nonfinal_sum:.*]] = vector.reduction "add", %[[vred:.*]]#0 : vector<128xf32> into f32
+// CHECK: %[[nonfinal_sum:.*]] = vector.reduction <add>, %[[vred:.*]]#0 : vector<128xf32> into f32
// Note that to compute the final sum we need to add the original initial value
// (%cst) since it is not zero.
// CHECK: %[[final_sum:.*]] = arith.addf %[[nonfinal_sum]], %[[cst]] : f32
// For the final product we don't need to do this additional step because the
// initial value equals to 1 (the neutral element for multiplication).
-// CHECK: %[[final_prod:.*]] = vector.reduction "mul", %[[vred:.*]]#1 : vector<128xf32> into f32
+// CHECK: %[[final_prod:.*]] = vector.reduction <mul>, %[[vred:.*]]#1 : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: affine.store %[[final_prod]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[mul:.*]] = arith.muli %[[part_prod]], %[[ld]] : vector<128xi64>
// CHECK: affine.yield %[[add]], %[[mul]] : vector<128xi64>, vector<128xi64>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]]#0 : vector<128xi64> into i64
-// CHECK: %[[final_prod:.*]] = vector.reduction "mul", %[[vred:.*]]#1 : vector<128xi64> into i64
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]]#0 : vector<128xi64> into i64
+// CHECK: %[[final_prod:.*]] = vector.reduction <mul>, %[[vred:.*]]#1 : vector<128xi64> into i64
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xi64>
// CHECK: affine.store %[[final_prod]], %{{.*}} : memref<256xi64>
// CHECK: }
// CHECK: %[[outer_add:.*]] = arith.addf %[[outer_iter]], %[[inner_red]] : vector<128xf32>
// CHECK: affine.yield %[[outer_add]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[outer_red:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[outer_red:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<1xf32>
// -----
// CHECK: %[[new_acc:.*]] = arith.select %[[mask]], %[[add]], %[[red_iter]] : vector<128xi1>, vector<128xf32>
// CHECK: affine.yield %[[new_acc]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK: %[[new_acc:.*]] = arith.select %[[mask]], %[[add]], %[[red_iter]] : vector<128xi1>, vector<128xf32>
// CHECK: affine.yield %[[new_acc]] : vector<128xf32>
// CHECK: }
-// CHECK: %[[final_sum:.*]] = vector.reduction "add", %[[vred:.*]] : vector<128xf32> into f32
+// CHECK: %[[final_sum:.*]] = vector.reduction <add>, %[[vred:.*]] : vector<128xf32> into f32
// CHECK: affine.store %[[final_sum]], %{{.*}} : memref<256xf32>
// CHECK: }
// CHECK-VEC1: %[[a:.*]] = arith.addf %[[red_in]], %[[m]] : vector<16xf32>
// CHECK-VEC1: scf.yield %[[a]] : vector<16xf32>
// CHECK-VEC1: }
-// CHECK-VEC1: %{{.*}} = vector.reduction "add", %[[red]] : vector<16xf32> into f32
+// CHECK-VEC1: %{{.*}} = vector.reduction <add>, %[[red]] : vector<16xf32> into f32
// CHECK-VEC1: return
//
// CHECK-VEC2-LABEL: func @reduction_d
// CHECK-VEC2: %[[a:.*]] = arith.addf %[[red_in]], %[[m]] : vector<16xf32>
// CHECK-VEC2: scf.yield %[[a]] : vector<16xf32>
// CHECK-VEC2: }
-// CHECK-VEC2: %{{.*}} = vector.reduction "add", %[[red]] : vector<16xf32> into f32
+// CHECK-VEC2: %{{.*}} = vector.reduction <add>, %[[red]] : vector<16xf32> into f32
// CHECK-VEC2: return
//
func @reduction_d(%arga: tensor<1024xf32, #DenseVector>, %argb: tensor<1024xf32>, %argx: tensor<f32>) -> tensor<f32> {
// CHECK: %[[VAL_83:.*]] = arith.select %[[VAL_80]], %[[VAL_82]], %[[VAL_77]] : vector<8xi1>, vector<8xf64>
// CHECK: scf.yield %[[VAL_83]] : vector<8xf64>
// CHECK: }
-// CHECK: %[[VAL_84:.*]] = vector.reduction "add", %[[VAL_85:.*]] : vector<8xf64> into f64
+// CHECK: %[[VAL_84:.*]] = vector.reduction <add>, %[[VAL_85:.*]] : vector<8xf64> into f64
// CHECK: scf.yield %[[VAL_84]] : f64
// CHECK: }
// CHECK: memref.store %[[VAL_86:.*]], %[[VAL_15]][] : memref<f64>
// -----
func @reduce_unknown_kind(%arg0: vector<16xf32>) -> f32 {
- // expected-error@+1 {{'vector.reduction' op unknown reduction kind: joho}}
- %0 = vector.reduction "joho", %arg0 : vector<16xf32> into f32
+ // expected-error@+1 {{custom op 'vector.reduction' Unknown combining kind: joho}}
+ %0 = vector.reduction <joho>, %arg0 : vector<16xf32> into f32
}
// -----
func @reduce_elt_type_mismatch(%arg0: vector<16xf32>) -> i32 {
// expected-error@+1 {{'vector.reduction' op failed to verify that source operand and result have same element type}}
- %0 = vector.reduction "add", %arg0 : vector<16xf32> into i32
+ %0 = vector.reduction <add>, %arg0 : vector<16xf32> into i32
}
// -----
func @reduce_unsupported_attr(%arg0: vector<16xf32>) -> i32 {
- // expected-error@+1 {{attribute 'kind' failed to satisfy constraint: string attribute}}
+ // expected-error@+1 {{expected '<'}}
%0 = vector.reduction 1234, %arg0 : vector<16xf32> into i32
}
func @reduce_unsupported_third_argument(%arg0: vector<16xf32>, %arg1: f32) -> f32 {
// expected-error@+1 {{'vector.reduction' unsupported number of operands}}
- %0 = vector.reduction "add", %arg0, %arg1, %arg1 : vector<16xf32> into f32
+ %0 = vector.reduction <add>, %arg0, %arg1, %arg1 : vector<16xf32> into f32
}
// -----
func @reduce_unsupported_accumulator_kind(%arg0: vector<16xf32>, %arg1: f32) -> f32 {
// expected-error@+1 {{'vector.reduction' op no accumulator for reduction kind: min}}
- %0 = vector.reduction "minf", %arg0, %arg1 : vector<16xf32> into f32
+ %0 = vector.reduction <minf>, %arg0, %arg1 : vector<16xf32> into f32
}
// -----
func @reduce_unsupported_accumulator_type(%arg0: vector<16xi32>, %arg1: i32) -> i32 {
// expected-error@+1 {{'vector.reduction' op no accumulator for type: 'i32'}}
- %0 = vector.reduction "add", %arg0, %arg1 : vector<16xi32> into i32
+ %0 = vector.reduction <add>, %arg0, %arg1 : vector<16xi32> into i32
}
// -----
func @reduce_unsupported_type(%arg0: vector<16xf32>) -> f32 {
// expected-error@+1 {{'vector.reduction' op unsupported reduction type}}
- %0 = vector.reduction "xor", %arg0 : vector<16xf32> into f32
+ %0 = vector.reduction <xor>, %arg0 : vector<16xf32> into f32
}
// -----
func @reduce_unsupported_rank(%arg0: vector<4x16xf32>) -> f32 {
// expected-error@+1 {{'vector.reduction' op unsupported reduction rank: 2}}
- %0 = vector.reduction "add", %arg0 : vector<4x16xf32> into f32
+ %0 = vector.reduction <add>, %arg0 : vector<4x16xf32> into f32
}
// -----
// CHECK-LABEL: @reduce_fp
func @reduce_fp(%arg0: vector<16xf32>, %arg1: f32) -> f32 {
- // CHECK: vector.reduction "add", %{{.*}} : vector<16xf32> into f32
- vector.reduction "add", %arg0 : vector<16xf32> into f32
- // CHECK: vector.reduction "add", %{{.*}}, %{{.*}} : vector<16xf32> into f32
- vector.reduction "add", %arg0, %arg1 : vector<16xf32> into f32
- // CHECK: vector.reduction "mul", %{{.*}} : vector<16xf32> into f32
- vector.reduction "mul", %arg0 : vector<16xf32> into f32
- // CHECK: vector.reduction "mul", %{{.*}}, %{{.*}} : vector<16xf32> into f32
- vector.reduction "mul", %arg0, %arg1 : vector<16xf32> into f32
- // CHECK: vector.reduction "minf", %{{.*}} : vector<16xf32> into f32
- vector.reduction "minf", %arg0 : vector<16xf32> into f32
- // CHECK: %[[X:.*]] = vector.reduction "maxf", %{{.*}} : vector<16xf32> into f32
- %0 = vector.reduction "maxf", %arg0 : vector<16xf32> into f32
+ // CHECK: vector.reduction <add>, %{{.*}} : vector<16xf32> into f32
+ vector.reduction <add>, %arg0 : vector<16xf32> into f32
+ // CHECK: vector.reduction <add>, %{{.*}}, %{{.*}} : vector<16xf32> into f32
+ vector.reduction <add>, %arg0, %arg1 : vector<16xf32> into f32
+ // CHECK: vector.reduction <mul>, %{{.*}} : vector<16xf32> into f32
+ vector.reduction <mul>, %arg0 : vector<16xf32> into f32
+ // CHECK: vector.reduction <mul>, %{{.*}}, %{{.*}} : vector<16xf32> into f32
+ vector.reduction <mul>, %arg0, %arg1 : vector<16xf32> into f32
+ // CHECK: vector.reduction <minf>, %{{.*}} : vector<16xf32> into f32
+ vector.reduction <minf>, %arg0 : vector<16xf32> into f32
+ // CHECK: %[[X:.*]] = vector.reduction <maxf>, %{{.*}} : vector<16xf32> into f32
+ %0 = vector.reduction <maxf>, %arg0 : vector<16xf32> into f32
// CHECK: return %[[X]] : f32
return %0 : f32
}
// CHECK-LABEL: @reduce_int
func @reduce_int(%arg0: vector<16xi32>) -> i32 {
- // CHECK: vector.reduction "add", %{{.*}} : vector<16xi32> into i32
- vector.reduction "add", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "mul", %{{.*}} : vector<16xi32> into i32
- vector.reduction "mul", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "minui", %{{.*}} : vector<16xi32> into i32
- vector.reduction "minui", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "minsi", %{{.*}} : vector<16xi32> into i32
- vector.reduction "minsi", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "maxui", %{{.*}} : vector<16xi32> into i32
- vector.reduction "maxui", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "maxsi", %{{.*}} : vector<16xi32> into i32
- vector.reduction "maxsi", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "and", %{{.*}} : vector<16xi32> into i32
- vector.reduction "and", %arg0 : vector<16xi32> into i32
- // CHECK: vector.reduction "or", %{{.*}} : vector<16xi32> into i32
- vector.reduction "or", %arg0 : vector<16xi32> into i32
- // CHECK: %[[X:.*]] = vector.reduction "xor", %{{.*}} : vector<16xi32> into i32
- %0 = vector.reduction "xor", %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <add>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <add>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <mul>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <mul>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <minui>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <minui>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <minsi>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <minsi>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <maxui>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <maxui>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <maxsi>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <maxsi>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <and>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <and>, %arg0 : vector<16xi32> into i32
+ // CHECK: vector.reduction <or>, %{{.*}} : vector<16xi32> into i32
+ vector.reduction <or>, %arg0 : vector<16xi32> into i32
+ // CHECK: %[[X:.*]] = vector.reduction <xor>, %{{.*}} : vector<16xi32> into i32
+ %0 = vector.reduction <xor>, %arg0 : vector<16xi32> into i32
// CHECK: return %[[X]] : i32
return %0 : i32
}
// CHECK-SAME: %[[B:.*1]]: vector<4xf32>,
// CHECK-SAME: %[[C:.*2]]: f32
// CHECK: %[[F:.*]] = arith.mulf %[[A]], %[[B]] : vector<4xf32>
-// CHECK: %[[R:.*]] = vector.reduction "add", %[[F]] : vector<4xf32> into f32
+// CHECK: %[[R:.*]] = vector.reduction <add>, %[[F]] : vector<4xf32> into f32
// CHECK: %[[ACC:.*]] = arith.addf %[[R]], %[[C]] : f32
// CHECK: return %[[ACC]] : f32
// CHECK-SAME: %[[B:.*1]]: vector<4xi32>,
// CHECK-SAME: %[[C:.*2]]: i32
// CHECK: %[[F:.*]] = arith.muli %[[A]], %[[B]] : vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction "add", %[[F]] : vector<4xi32> into i32
+// CHECK: %[[R:.*]] = vector.reduction <add>, %[[F]] : vector<4xi32> into i32
// CHECK: %[[ACC:.*]] = arith.addi %[[R]], %[[C]] : i32
// CHECK: return %[[ACC]] : i32
// CHECK: %[[R:.*]] = arith.constant dense<0.000000e+00> : vector<2xf32>
// CHECK: %[[T0:.*]] = vector.extract %[[A]][0] : vector<2x3xf32>
// CHECK: %[[T2:.*]] = arith.mulf %[[T0]], %[[B]] : vector<3xf32>
-// CHECK: %[[T3:.*]] = vector.reduction "add", %[[T2]] : vector<3xf32> into f32
+// CHECK: %[[T3:.*]] = vector.reduction <add>, %[[T2]] : vector<3xf32> into f32
// CHECK: %[[T4:.*]] = vector.insert %[[T3]], %[[R]] [0] : f32 into vector<2xf32>
// CHECK: %[[T5:.*]] = vector.extract %[[A]][1] : vector<2x3xf32>
// CHECK: %[[T7:.*]] = arith.mulf %[[T5]], %[[B]] : vector<3xf32>
-// CHECK: %[[T8:.*]] = vector.reduction "add", %[[T7]] : vector<3xf32> into f32
+// CHECK: %[[T8:.*]] = vector.reduction <add>, %[[T7]] : vector<3xf32> into f32
// CHECK: %[[T9:.*]] = vector.insert %[[T8]], %[[T4]] [1] : f32 into vector<2xf32>
// CHECK: %[[T10:.*]] = arith.addf %[[T9]], %[[C]] : vector<2xf32>
// CHECK: return %[[T10]] : vector<2xf32>
// CHECK: %[[R:.*]] = arith.constant dense<0> : vector<2xi32>
// CHECK: %[[T0:.*]] = vector.extract %[[A]][0] : vector<2x3xi32>
// CHECK: %[[T2:.*]] = arith.muli %[[T0]], %[[B]] : vector<3xi32>
-// CHECK: %[[T3:.*]] = vector.reduction "add", %[[T2]] : vector<3xi32> into i32
+// CHECK: %[[T3:.*]] = vector.reduction <add>, %[[T2]] : vector<3xi32> into i32
// CHECK: %[[T4:.*]] = vector.insert %[[T3]], %[[R]] [0] : i32 into vector<2xi32>
// CHECK: %[[T5:.*]] = vector.extract %[[A]][1] : vector<2x3xi32>
// CHECK: %[[T7:.*]] = arith.muli %[[T5]], %[[B]] : vector<3xi32>
-// CHECK: %[[T8:.*]] = vector.reduction "add", %[[T7]] : vector<3xi32> into i32
+// CHECK: %[[T8:.*]] = vector.reduction <add>, %[[T7]] : vector<3xi32> into i32
// CHECK: %[[T9:.*]] = vector.insert %[[T8]], %[[T4]] [1] : i32 into vector<2xi32>
// CHECK: %[[T10:.*]] = arith.addi %[[T9]], %[[C]] : vector<2xi32>
// CHECK: return %[[T10]] : vector<2xi32>
// CHECK: %[[R:.*]] = arith.constant dense<0.000000e+00> : vector<2xf32>
// CHECK: %[[T0:.*]] = vector.extract %[[B]][0] : vector<2x3xf32>
// CHECK: %[[T2:.*]] = arith.mulf %[[T0]], %[[A]] : vector<3xf32>
-// CHECK: %[[T3:.*]] = vector.reduction "add", %[[T2]] : vector<3xf32> into f32
+// CHECK: %[[T3:.*]] = vector.reduction <add>, %[[T2]] : vector<3xf32> into f32
// CHECK: %[[T4:.*]] = vector.insert %[[T3]], %[[R]] [0] : f32 into vector<2xf32>
// CHECK: %[[T5:.*]] = vector.extract %[[B]][1] : vector<2x3xf32>
// CHECK: %[[T7:.*]] = arith.mulf %[[T5]], %[[A]] : vector<3xf32>
-// CHECK: %[[T8:.*]] = vector.reduction "add", %[[T7]] : vector<3xf32> into f32
+// CHECK: %[[T8:.*]] = vector.reduction <add>, %[[T7]] : vector<3xf32> into f32
// CHECK: %[[T9:.*]] = vector.insert %[[T8]], %[[T4]] [1] : f32 into vector<2xf32>
// CHECK: %[[T10:.*]] = arith.addf %[[T9]], %[[C]] : vector<2xf32>
// CHECK: return %[[T10]] : vector<2xf32>
// CHECK: %[[T0:.*]] = vector.extract %[[A]][0] : vector<2x2xf32>
// CHECK: %[[T2:.*]] = vector.extract %[[Bt]][0] : vector<2x2xf32>
// CHECK: %[[T9:.*]] = arith.mulf %[[T0]], %[[T2]] : vector<2xf32>
-// CHECK: %[[T10:.*]] = vector.reduction "add", %[[T9]] : vector<2xf32> into f32
+// CHECK: %[[T10:.*]] = vector.reduction <add>, %[[T9]] : vector<2xf32> into f32
// CHECK: %[[T11:.*]] = vector.insert %[[T10]], %[[R]] [0, 0] : f32 into vector<2x2xf32>
//
// CHECK: %[[T12:.*]] = vector.extract %[[Bt]][1] : vector<2x2xf32>
// CHECK: %[[T19:.*]] = arith.mulf %[[T0]], %[[T12]] : vector<2xf32>
-// CHECK: %[[T20:.*]] = vector.reduction "add", %[[T19]] : vector<2xf32> into f32
+// CHECK: %[[T20:.*]] = vector.reduction <add>, %[[T19]] : vector<2xf32> into f32
// CHECK: %[[T21:.*]] = vector.insert %[[T20]], %[[T11]] [0, 1] : f32 into vector<2x2xf32>
//
// CHECK: %[[T23:.*]] = vector.extract %[[A]][1] : vector<2x2xf32>
// CHECK: %[[T24:.*]] = vector.extract %[[Bt]][0] : vector<2x2xf32>
// CHECK: %[[T32:.*]] = arith.mulf %[[T23]], %[[T24]] : vector<2xf32>
-// CHECK: %[[T33:.*]] = vector.reduction "add", %[[T32]] : vector<2xf32> into f32
+// CHECK: %[[T33:.*]] = vector.reduction <add>, %[[T32]] : vector<2xf32> into f32
// CHECK: %[[T34:.*]] = vector.insert %[[T33]], %[[T21]] [1, 0] : f32 into vector<2x2xf32>
//
// CHECK: %[[T40:.*]] = vector.extract %[[Bt]][1] : vector<2x2xf32>
// CHECK: %[[T41:.*]] = arith.mulf %[[T23]], %[[T40]] : vector<2xf32>
-// CHECK: %[[T42:.*]] = vector.reduction "add", %[[T41]] : vector<2xf32> into f32
+// CHECK: %[[T42:.*]] = vector.reduction <add>, %[[T41]] : vector<2xf32> into f32
// CHECK: %[[T43:.*]] = vector.insert %[[T42]], %[[T34]] [1, 1] : f32 into vector<2x2xf32>
//
// CHECK: %[[T52:.*]] = arith.addf %[[T43]], %[[C]] : vector<2x2xf32>
// CHECK: %[[T0:.*]] = vector.extract %[[A]][0] : vector<2x3xf32>
// CHECK: %[[T1:.*]] = vector.extract %[[B]][0] : vector<2x3xf32>
// CHECK: %[[T2:.*]] = arith.mulf %[[T0]], %[[T1]] : vector<3xf32>
-// CHECK: %[[T3:.*]] = vector.reduction "add", %[[T2]] : vector<3xf32> into f32
+// CHECK: %[[T3:.*]] = vector.reduction <add>, %[[T2]] : vector<3xf32> into f32
// CHECK: %[[T4:.*]] = arith.addf %[[T3]], %[[C]] : f32
// CHECK: %[[T5:.*]] = vector.extract %[[A]][1] : vector<2x3xf32>
// CHECK: %[[T6:.*]] = vector.extract %[[B]][1] : vector<2x3xf32>
// CHECK: %[[T7:.*]] = arith.mulf %[[T5]], %[[T6]] : vector<3xf32>
-// CHECK: %[[T8:.*]] = vector.reduction "add", %[[T7]] : vector<3xf32> into f32
+// CHECK: %[[T8:.*]] = vector.reduction <add>, %[[T7]] : vector<3xf32> into f32
// CHECK: %[[T9:.*]] = arith.addf %[[T8]], %[[T4]] : f32
// CHECK: return %[[T9]] : f32
// CHECK: %[[T7:.*]] = vector.extract %[[B]][2, 0] : vector<3x2xf32>
// CHECK: %[[T9:.*]] = vector.insert %[[T7]], %[[T6]] [2] : f32 into vector<3xf32>
// CHECK: %[[T10:.*]] = arith.mulf %[[T0]], %[[T9]] : vector<3xf32>
-// CHECK: %[[T11:.*]] = vector.reduction "add", %[[T10]] : vector<3xf32> into f32
+// CHECK: %[[T11:.*]] = vector.reduction <add>, %[[T10]] : vector<3xf32> into f32
// CHECK: %[[ACC0:.*]] = arith.addf %[[T11]], %[[C]] : f32
//
// CHECK: %[[T12:.*]] = vector.extract %[[A]][1] : vector<2x3xf32>
// CHECK: %[[T19:.*]] = vector.extract %[[B]][2, 1] : vector<3x2xf32>
// CHECK: %[[T21:.*]] = vector.insert %[[T19]], %[[T18]] [2] : f32 into vector<3xf32>
// CHECK: %[[T22:.*]] = arith.mulf %[[T12]], %[[T21]] : vector<3xf32>
-// CHECK: %[[T23:.*]] = vector.reduction "add", %[[T22]] : vector<3xf32> into f32
+// CHECK: %[[T23:.*]] = vector.reduction <add>, %[[T22]] : vector<3xf32> into f32
// CHECK: %[[ACC1:.*]] = arith.addf %[[T23]], %[[ACC0]] : f32
// CHECK: return %[[ACC1]] : f32
// REDUCE: %[[a0:.*]] = vector.extract %[[A]][0] : vector<2x4xf32>
// REDUCE-NEXT: %[[b0:.*]] = vector.extract %[[Bt]][0] : vector<3x4xf32>
// REDUCE-NEXT: %[[ab00:.*]] = mul %[[a0]], %[[b0]] : vector<4xf32>
-// REDUCE-NEXT: %[[s00:.*]] = vector.reduction "add", %[[ab00]] : vector<4xf32> into f32
+// REDUCE-NEXT: %[[s00:.*]] = vector.reduction <add>, %[[ab00]] : vector<4xf32> into f32
// REDUCE-NEXT: %[[r00:.*]] = vector.insert %[[s00]], %[[RES]] [0, 0] : f32 into vector<2x3xf32>
//
// ...
// REDUCE: %[[a1:.*]] = vector.extract %[[A]][1] : vector<2x4xf32>
// REDUCE-NEXT: %[[b2:.*]] = vector.extract %[[Bt]][2] : vector<3x4xf32>
// REDUCE-NEXT: %[[ab12:.*]] = mul %[[a1]], %[[b02]] : vector<4xf32>
-// REDUCE-NEXT: %[[s12:.*]] = vector.reduction "add", %[[ab12]] : vector<4xf32> into f32
+// REDUCE-NEXT: %[[s12:.*]] = vector.reduction <add>, %[[ab12]] : vector<4xf32> into f32
// REDUCE-NEXT: %[[r12:.*]] = vector.insert %[[s12]], %{{.*}} [1, 2] : f32 into vector<2x3xf32>
//
// REDUCE: return %[[c3]] : vector<2x3xf32>
// CHECK: %[[C0:.+]] = arith.constant 0 : index
// CHECK: %[[C1:.+]] = arith.constant 1 : index
// CHECK: %[[V0:.+]] = vector.extract %[[INPUT]][0]
-// CHECK: %[[RV0:.+]] = vector.reduction "mul", %[[V0]] : vector<4xf32> into f32
+// CHECK: %[[RV0:.+]] = vector.reduction <mul>, %[[V0]] : vector<4xf32> into f32
// CHECK: %[[RESULT_VEC_1:.+]] = vector.insertelement %[[RV0:.+]], %[[RESULT_VEC_0]][%[[C0]] : index] : vector<2xf32>
// CHECK: %[[V1:.+]] = vector.extract %[[INPUT]][1]
-// CHECK: %[[RV1:.+]] = vector.reduction "mul", %[[V1]] : vector<4xf32> into f32
+// CHECK: %[[RV1:.+]] = vector.reduction <mul>, %[[V1]] : vector<4xf32> into f32
// CHECK: %[[RESULT_VEC:.+]] = vector.insertelement %[[RV1:.+]], %[[RESULT_VEC_1]][%[[C1]] : index] : vector<2xf32>
// CHECK: return %[[RESULT_VEC]]
// CHECK-LABEL: func @vector_multi_reduction_to_scalar
// CHECK-SAME: %[[INPUT:.+]]: vector<2x4xf32>
// CHECK: %[[CASTED:.*]] = vector.shape_cast %[[INPUT]] : vector<2x4xf32> to vector<8xf32>
-// CHECK: %[[REDUCED:.*]] = vector.reduction "mul", %[[CASTED]] : vector<8xf32> into f32
+// CHECK: %[[REDUCED:.*]] = vector.reduction <mul>, %[[CASTED]] : vector<8xf32> into f32
// CHECK: %[[INSERTED:.*]] = vector.insertelement %[[REDUCED]], {{.*}} : vector<1xf32>
// CHECK: %[[RES:.*]] = vector.extract %[[INSERTED]][0] : vector<1xf32>
// CHECK: return %[[RES]]
// CHECK-DAG: %[[C5:.+]] = arith.constant 5 : index
// CHECK: %[[RESHAPED_INPUT:.+]] = vector.shape_cast %[[INPUT]] : vector<2x3x4x5xi32> to vector<6x20xi32>
// CHECK: %[[V0:.+]] = vector.extract %[[RESHAPED_INPUT]][0] : vector<6x20xi32>
-// CHECK: %[[V0R:.+]] = vector.reduction "add", %[[V0]] : vector<20xi32> into i32
+// CHECK: %[[V0R:.+]] = vector.reduction <add>, %[[V0]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC_1:.+]] = vector.insertelement %[[V0R]], %[[FLAT_RESULT_VEC_0]][%[[C0]] : index] : vector<6xi32>
// CHECK: %[[V1:.+]] = vector.extract %[[RESHAPED_INPUT]][1] : vector<6x20xi32>
-// CHECK: %[[V1R:.+]] = vector.reduction "add", %[[V1]] : vector<20xi32> into i32
+// CHECK: %[[V1R:.+]] = vector.reduction <add>, %[[V1]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC_2:.+]] = vector.insertelement %[[V1R]], %[[FLAT_RESULT_VEC_1]][%[[C1]] : index] : vector<6xi32>
// CHECK: %[[V2:.+]] = vector.extract %[[RESHAPED_INPUT]][2] : vector<6x20xi32>
-// CHECK: %[[V2R:.+]] = vector.reduction "add", %[[V2]] : vector<20xi32> into i32
+// CHECK: %[[V2R:.+]] = vector.reduction <add>, %[[V2]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC_3:.+]] = vector.insertelement %[[V2R]], %[[FLAT_RESULT_VEC_2]][%[[C2]] : index] : vector<6xi32>
// CHECK: %[[V3:.+]] = vector.extract %[[RESHAPED_INPUT]][3] : vector<6x20xi32>
-// CHECK: %[[V3R:.+]] = vector.reduction "add", %[[V3]] : vector<20xi32> into i32
+// CHECK: %[[V3R:.+]] = vector.reduction <add>, %[[V3]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC_4:.+]] = vector.insertelement %[[V3R]], %[[FLAT_RESULT_VEC_3]][%[[C3]] : index] : vector<6xi32>
// CHECK: %[[V4:.+]] = vector.extract %[[RESHAPED_INPUT]][4] : vector<6x20xi32>
-// CHECK: %[[V4R:.+]] = vector.reduction "add", %[[V4]] : vector<20xi32> into i32
+// CHECK: %[[V4R:.+]] = vector.reduction <add>, %[[V4]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC_5:.+]] = vector.insertelement %[[V4R]], %[[FLAT_RESULT_VEC_4]][%[[C4]] : index] : vector<6xi32>
/// CHECK: %[[V5:.+]] = vector.extract %[[RESHAPED_INPUT]][5] : vector<6x20xi32>
-// CHECK: %[[V5R:.+]] = vector.reduction "add", %[[V5]] : vector<20xi32> into i32
+// CHECK: %[[V5R:.+]] = vector.reduction <add>, %[[V5]] : vector<20xi32> into i32
// CHECK: %[[FLAT_RESULT_VEC:.+]] = vector.insertelement %[[V5R]], %[[FLAT_RESULT_VEC_5]][%[[C5]] : index] : vector<6xi32>
// CHECK: %[[RESULT:.+]] = vector.shape_cast %[[FLAT_RESULT_VEC]] : vector<6xi32> to vector<2x3xi32>
// CHECK: return %[[RESULT]]
// CHECK: %[[C7:.+]] = arith.constant 7 : index
// CHECK: %[[TRANSPOSED_INPUT:.+]] = vector.transpose %[[INPUT]], [1, 2, 0] : vector<3x2x4xf32> to vector<2x4x3xf32>
// CHECK: %[[V0:.+]] = vector.extract %[[TRANSPOSED_INPUT]][0, 0]
-// CHECK: %[[RV0:.+]] = vector.reduction "mul", %[[V0]] : vector<3xf32> into f32
+// CHECK: %[[RV0:.+]] = vector.reduction <mul>, %[[V0]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_1:.+]] = vector.insertelement %[[RV0:.+]], %[[RESULT_VEC_0]][%[[C0]] : index] : vector<8xf32>
// CHECK: %[[V1:.+]] = vector.extract %[[TRANSPOSED_INPUT]][0, 1]
-// CHECK: %[[RV1:.+]] = vector.reduction "mul", %[[V1]] : vector<3xf32> into f32
+// CHECK: %[[RV1:.+]] = vector.reduction <mul>, %[[V1]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_2:.+]] = vector.insertelement %[[RV1:.+]], %[[RESULT_VEC_1]][%[[C1]] : index] : vector<8xf32>
// CHECK: %[[V2:.+]] = vector.extract %[[TRANSPOSED_INPUT]][0, 2]
-// CHECK: %[[RV2:.+]] = vector.reduction "mul", %[[V2]] : vector<3xf32> into f32
+// CHECK: %[[RV2:.+]] = vector.reduction <mul>, %[[V2]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_3:.+]] = vector.insertelement %[[RV2:.+]], %[[RESULT_VEC_2]][%[[C2]] : index] : vector<8xf32>
// CHECK: %[[V3:.+]] = vector.extract %[[TRANSPOSED_INPUT]][0, 3]
-// CHECK: %[[RV3:.+]] = vector.reduction "mul", %[[V3]] : vector<3xf32> into f32
+// CHECK: %[[RV3:.+]] = vector.reduction <mul>, %[[V3]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_4:.+]] = vector.insertelement %[[RV3:.+]], %[[RESULT_VEC_3]][%[[C3]] : index] : vector<8xf32>
// CHECK: %[[V4:.+]] = vector.extract %[[TRANSPOSED_INPUT]][1, 0]
-// CHECK: %[[RV4:.+]] = vector.reduction "mul", %[[V4]] : vector<3xf32> into f32
+// CHECK: %[[RV4:.+]] = vector.reduction <mul>, %[[V4]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_5:.+]] = vector.insertelement %[[RV4:.+]], %[[RESULT_VEC_4]][%[[C4]] : index] : vector<8xf32>
// CHECK: %[[V5:.+]] = vector.extract %[[TRANSPOSED_INPUT]][1, 1]
-// CHECK: %[[RV5:.+]] = vector.reduction "mul", %[[V5]] : vector<3xf32> into f32
+// CHECK: %[[RV5:.+]] = vector.reduction <mul>, %[[V5]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_6:.+]] = vector.insertelement %[[RV5:.+]], %[[RESULT_VEC_5]][%[[C5]] : index] : vector<8xf32>
// CHECK: %[[V6:.+]] = vector.extract %[[TRANSPOSED_INPUT]][1, 2]
-// CHECK: %[[RV6:.+]] = vector.reduction "mul", %[[V6]] : vector<3xf32> into f32
+// CHECK: %[[RV6:.+]] = vector.reduction <mul>, %[[V6]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC_7:.+]] = vector.insertelement %[[RV6:.+]], %[[RESULT_VEC_6]][%[[C6]] : index] : vector<8xf32>
// CHECK: %[[V7:.+]] = vector.extract %[[TRANSPOSED_INPUT]][1, 3]
-// CHECK: %[[RV7:.+]] = vector.reduction "mul", %[[V7]] : vector<3xf32> into f32
+// CHECK: %[[RV7:.+]] = vector.reduction <mul>, %[[V7]] : vector<3xf32> into f32
// CHECK: %[[RESULT_VEC:.+]] = vector.insertelement %[[RV7:.+]], %[[RESULT_VEC_7]][%[[C7]] : index] : vector<8xf32>
// CHECK: %[[RESHAPED_VEC:.+]] = vector.shape_cast %[[RESULT_VEC]] : vector<8xf32> to vector<2x4xf32>
// CHECK: return %[[RESHAPED_VEC]]
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v2 : vector<64xf32> into f32
+ %0 = vector.reduction <add>, %v2 : vector<64xf32> into f32
vector.print %0 : f32
// CHECK: 67
- %1 = vector.reduction "mul", %v2 : vector<64xf32> into f32
+ %1 = vector.reduction <mul>, %v2 : vector<64xf32> into f32
vector.print %1 : f32
// CHECK: 6
- %2 = vector.reduction "minf", %v2 : vector<64xf32> into f32
+ %2 = vector.reduction <minf>, %v2 : vector<64xf32> into f32
vector.print %2 : f32
// CHECK: 1
- %3 = vector.reduction "maxf", %v2 : vector<64xf32> into f32
+ %3 = vector.reduction <maxf>, %v2 : vector<64xf32> into f32
vector.print %3 : f32
// CHECK: 3
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v9 : vector<10xf32> into f32
+ %0 = vector.reduction <add>, %v9 : vector<10xf32> into f32
vector.print %0 : f32
// CHECK: -7.75
- %1 = vector.reduction "mul", %v9 : vector<10xf32> into f32
+ %1 = vector.reduction <mul>, %v9 : vector<10xf32> into f32
vector.print %1 : f32
// CHECK: -5760
- %2 = vector.reduction "minf", %v9 : vector<10xf32> into f32
+ %2 = vector.reduction <minf>, %v9 : vector<10xf32> into f32
vector.print %2 : f32
// CHECK: -16
- %3 = vector.reduction "maxf", %v9 : vector<10xf32> into f32
+ %3 = vector.reduction <maxf>, %v9 : vector<10xf32> into f32
vector.print %3 : f32
// CHECK: 5
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v2 : vector<64xf64> into f64
+ %0 = vector.reduction <add>, %v2 : vector<64xf64> into f64
vector.print %0 : f64
// CHECK: 67
- %1 = vector.reduction "mul", %v2 : vector<64xf64> into f64
+ %1 = vector.reduction <mul>, %v2 : vector<64xf64> into f64
vector.print %1 : f64
// CHECK: 6
- %2 = vector.reduction "minf", %v2 : vector<64xf64> into f64
+ %2 = vector.reduction <minf>, %v2 : vector<64xf64> into f64
vector.print %2 : f64
// CHECK: 1
- %3 = vector.reduction "maxf", %v2 : vector<64xf64> into f64
+ %3 = vector.reduction <maxf>, %v2 : vector<64xf64> into f64
vector.print %3 : f64
// CHECK: 3
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v9 : vector<10xf64> into f64
+ %0 = vector.reduction <add>, %v9 : vector<10xf64> into f64
vector.print %0 : f64
// CHECK: -7.75
- %1 = vector.reduction "mul", %v9 : vector<10xf64> into f64
+ %1 = vector.reduction <mul>, %v9 : vector<10xf64> into f64
vector.print %1 : f64
// CHECK: -5760
- %2 = vector.reduction "minf", %v9 : vector<10xf64> into f64
+ %2 = vector.reduction <minf>, %v9 : vector<10xf64> into f64
vector.print %2 : f64
// CHECK: -16
- %3 = vector.reduction "maxf", %v9 : vector<10xf64> into f64
+ %3 = vector.reduction <maxf>, %v9 : vector<10xf64> into f64
vector.print %3 : f64
// CHECK: 5
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v9 : vector<10xi32> into i32
+ %0 = vector.reduction <add>, %v9 : vector<10xi32> into i32
vector.print %0 : i32
// CHECK: -88
- %1 = vector.reduction "mul", %v9 : vector<10xi32> into i32
+ %1 = vector.reduction <mul>, %v9 : vector<10xi32> into i32
vector.print %1 : i32
// CHECK: -1228800
- %2 = vector.reduction "minsi", %v9 : vector<10xi32> into i32
+ %2 = vector.reduction <minsi>, %v9 : vector<10xi32> into i32
vector.print %2 : i32
// CHECK: -80
- %3 = vector.reduction "maxsi", %v9 : vector<10xi32> into i32
+ %3 = vector.reduction <maxsi>, %v9 : vector<10xi32> into i32
vector.print %3 : i32
// CHECK: 5
- %4 = vector.reduction "and", %v9 : vector<10xi32> into i32
+ %4 = vector.reduction <and>, %v9 : vector<10xi32> into i32
vector.print %4 : i32
// CHECK: 0
- %5 = vector.reduction "or", %v9 : vector<10xi32> into i32
+ %5 = vector.reduction <or>, %v9 : vector<10xi32> into i32
vector.print %5 : i32
// CHECK: -1
- %6 = vector.reduction "xor", %v9 : vector<10xi32> into i32
+ %6 = vector.reduction <xor>, %v9 : vector<10xi32> into i32
vector.print %6 : i32
// CHECK: -68
// CHECK: ( -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1 )
- %0 = vector.reduction "add", %v : vector<24xi4> into i4
+ %0 = vector.reduction <add>, %v : vector<24xi4> into i4
vector.print %0 : i4
// CHECK: 4
- %1 = vector.reduction "mul", %v : vector<24xi4> into i4
+ %1 = vector.reduction <mul>, %v : vector<24xi4> into i4
vector.print %1 : i4
// CHECK: 0
- %2 = vector.reduction "minsi", %v : vector<24xi4> into i4
+ %2 = vector.reduction <minsi>, %v : vector<24xi4> into i4
vector.print %2 : i4
// CHECK: -8
- %3 = vector.reduction "maxsi", %v : vector<24xi4> into i4
+ %3 = vector.reduction <maxsi>, %v : vector<24xi4> into i4
vector.print %3 : i4
// CHECK: 7
- %4 = vector.reduction "and", %v : vector<24xi4> into i4
+ %4 = vector.reduction <and>, %v : vector<24xi4> into i4
vector.print %4 : i4
// CHECK: 0
- %5 = vector.reduction "or", %v : vector<24xi4> into i4
+ %5 = vector.reduction <or>, %v : vector<24xi4> into i4
vector.print %5 : i4
// CHECK: -1
- %6 = vector.reduction "xor", %v : vector<24xi4> into i4
+ %6 = vector.reduction <xor>, %v : vector<24xi4> into i4
vector.print %6 : i4
// CHECK: 0
// Various vector reductions. Not full functional unit tests, but
// a simple integration test to see if the code runs end-to-end.
- %0 = vector.reduction "add", %v9 : vector<10xi64> into i64
+ %0 = vector.reduction <add>, %v9 : vector<10xi64> into i64
vector.print %0 : i64
// CHECK: -88
- %1 = vector.reduction "mul", %v9 : vector<10xi64> into i64
+ %1 = vector.reduction <mul>, %v9 : vector<10xi64> into i64
vector.print %1 : i64
// CHECK: -1228800
- %2 = vector.reduction "minsi", %v9 : vector<10xi64> into i64
+ %2 = vector.reduction <minsi>, %v9 : vector<10xi64> into i64
vector.print %2 : i64
// CHECK: -80
- %3 = vector.reduction "maxsi", %v9 : vector<10xi64> into i64
+ %3 = vector.reduction <maxsi>, %v9 : vector<10xi64> into i64
vector.print %3 : i64
// CHECK: 5
- %4 = vector.reduction "and", %v9 : vector<10xi64> into i64
+ %4 = vector.reduction <and>, %v9 : vector<10xi64> into i64
vector.print %4 : i64
// CHECK: 0
- %5 = vector.reduction "or", %v9 : vector<10xi64> into i64
+ %5 = vector.reduction <or>, %v9 : vector<10xi64> into i64
vector.print %5 : i64
// CHECK: -1
- %6 = vector.reduction "xor", %v9 : vector<10xi64> into i64
+ %6 = vector.reduction <xor>, %v9 : vector<10xi64> into i64
vector.print %6 : i64
// CHECK: -68
//
// CHECK: ( -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 )
- %0 = vector.reduction "add", %v : vector<16xsi4> into si4
+ %0 = vector.reduction <add>, %v : vector<16xsi4> into si4
vector.print %0 : si4
// CHECK: -8
- %1 = vector.reduction "mul", %v : vector<16xsi4> into si4
+ %1 = vector.reduction <mul>, %v : vector<16xsi4> into si4
vector.print %1 : si4
// CHECK: 0
- %2 = vector.reduction "minsi", %v : vector<16xsi4> into si4
+ %2 = vector.reduction <minsi>, %v : vector<16xsi4> into si4
vector.print %2 : si4
// CHECK: -8
- %3 = vector.reduction "maxsi", %v : vector<16xsi4> into si4
+ %3 = vector.reduction <maxsi>, %v : vector<16xsi4> into si4
vector.print %3 : si4
// CHECK: 7
- %4 = vector.reduction "and", %v : vector<16xsi4> into si4
+ %4 = vector.reduction <and>, %v : vector<16xsi4> into si4
vector.print %4 : si4
// CHECK: 0
- %5 = vector.reduction "or", %v : vector<16xsi4> into si4
+ %5 = vector.reduction <or>, %v : vector<16xsi4> into si4
vector.print %5 : si4
// CHECK: -1
- %6 = vector.reduction "xor", %v : vector<16xsi4> into si4
+ %6 = vector.reduction <xor>, %v : vector<16xsi4> into si4
vector.print %6 : si4
// CHECK: 0
//
// CHECK: ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 )
- %0 = vector.reduction "add", %v : vector<16xui4> into ui4
+ %0 = vector.reduction <add>, %v : vector<16xui4> into ui4
vector.print %0 : ui4
// CHECK: 8
- %1 = vector.reduction "mul", %v : vector<16xui4> into ui4
+ %1 = vector.reduction <mul>, %v : vector<16xui4> into ui4
vector.print %1 : ui4
// CHECK: 0
- %2 = vector.reduction "minui", %v : vector<16xui4> into ui4
+ %2 = vector.reduction <minui>, %v : vector<16xui4> into ui4
vector.print %2 : ui4
// CHECK: 0
- %3 = vector.reduction "maxui", %v : vector<16xui4> into ui4
+ %3 = vector.reduction <maxui>, %v : vector<16xui4> into ui4
vector.print %3 : ui4
// CHECK: 15
- %4 = vector.reduction "and", %v : vector<16xui4> into ui4
+ %4 = vector.reduction <and>, %v : vector<16xui4> into ui4
vector.print %4 : ui4
// CHECK: 0
- %5 = vector.reduction "or", %v : vector<16xui4> into ui4
+ %5 = vector.reduction <or>, %v : vector<16xui4> into ui4
vector.print %5 : ui4
// CHECK: 15
- %6 = vector.reduction "xor", %v : vector<16xui4> into ui4
+ %6 = vector.reduction <xor>, %v : vector<16xui4> into ui4
vector.print %6 : ui4
// CHECK: 0