[Mlir-commits] [mlir] [mlir][math] Add vector support for math-to-apfloat (PR #172715)
Maksim Levental
llvmlistbot at llvm.org
Wed Dec 17 10:56:21 PST 2025
https://github.com/makslevental created https://github.com/llvm/llvm-project/pull/172715
None
>From fd6323059d9a5b60d23375dbdc781ff3b7859d15 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Wed, 17 Dec 2025 10:53:55 -0800
Subject: [PATCH] [mlir][math] Add vector support for math-to-apfloat
---
.../ArithAndMathToAPFloat/ArithToAPFloat.cpp | 67 -------------------
.../ArithAndMathToAPFloat/Utils.cpp | 25 ++++++-
.../Conversion/ArithAndMathToAPFloat/Utils.h | 56 ++++++++++++++++
3 files changed, 79 insertions(+), 69 deletions(-)
diff --git a/mlir/lib/Conversion/ArithAndMathToAPFloat/ArithToAPFloat.cpp b/mlir/lib/Conversion/ArithAndMathToAPFloat/ArithToAPFloat.cpp
index b9ba94ef08098..d9574e23dd61d 100644
--- a/mlir/lib/Conversion/ArithAndMathToAPFloat/ArithToAPFloat.cpp
+++ b/mlir/lib/Conversion/ArithAndMathToAPFloat/ArithToAPFloat.cpp
@@ -46,73 +46,6 @@ lookupOrCreateBinaryFn(OpBuilder &b, SymbolOpInterface symTable, StringRef name,
{i32Type, i64Type, i64Type}, symbolTables);
}
-/// Given two operands of vector type and vector result type (with the same
-/// shape), call the given function for each pair of scalar operands and
-/// package the result into a vector. If the given operands and result type are
-/// not vectors, call the function directly. The second operand is optional.
-template <typename Fn, typename... Values>
-static Value forEachScalarValue(RewriterBase &rewriter, Location loc,
- Value operand1, Value operand2, Type resultType,
- Fn fn) {
- auto vecTy1 = dyn_cast<VectorType>(operand1.getType());
- if (operand2) {
- // Sanity check: Operand types must match.
- assert(vecTy1 == dyn_cast<VectorType>(operand2.getType()) &&
- "expected same vector types");
- }
- if (!vecTy1) {
- // Not a vector. Call the function directly.
- return fn(operand1, operand2, resultType);
- }
-
- // Prepare scalar operands.
- ResultRange sclars1 =
- vector::ToElementsOp::create(rewriter, loc, operand1)->getResults();
- SmallVector<Value> scalars2;
- if (!operand2) {
- // No second operand. Create a vector of empty values.
- scalars2.assign(vecTy1.getNumElements(), Value());
- } else {
- llvm::append_range(
- scalars2,
- vector::ToElementsOp::create(rewriter, loc, operand2)->getResults());
- }
-
- // Call the function for each pair of scalar operands.
- auto resultVecType = cast<VectorType>(resultType);
- SmallVector<Value> results;
- for (auto [scalar1, scalar2] : llvm::zip_equal(sclars1, scalars2)) {
- Value result = fn(scalar1, scalar2, resultVecType.getElementType());
- results.push_back(result);
- }
-
- // Package the results into a vector.
- return vector::FromElementsOp::create(
- rewriter, loc,
- vecTy1.cloneWith(/*shape=*/std::nullopt, results.front().getType()),
- results);
-}
-
-/// Check preconditions for the conversion:
-/// 1. All operands / results must be integers or floats (or vectors thereof).
-/// 2. The bitwidth of the operands / results must be <= 64.
-static LogicalResult checkPreconditions(RewriterBase &rewriter, Operation *op) {
- for (Value value : llvm::concat<Value>(op->getOperands(), op->getResults())) {
- Type type = value.getType();
- if (auto vecTy = dyn_cast<VectorType>(type)) {
- type = vecTy.getElementType();
- }
- if (!type.isIntOrFloat()) {
- return rewriter.notifyMatchFailure(
- op, "only integers and floats (or vectors thereof) are supported");
- }
- if (type.getIntOrFloatBitWidth() > 64)
- return rewriter.notifyMatchFailure(op,
- "bitwidth > 64 bits is not supported");
- }
- return success();
-}
-
/// Rewrite a binary arithmetic operation to an APFloat function call.
template <typename OpTy>
struct BinaryArithOpToAPFloatConversion final : OpRewritePattern<OpTy> {
diff --git a/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.cpp b/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.cpp
index 2b5857367dc40..340e015404d86 100644
--- a/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.cpp
+++ b/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.cpp
@@ -9,14 +9,35 @@
#include "Utils.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypeInterfaces.h"
#include "mlir/IR/Location.h"
+#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/Value.h"
-mlir::Value mlir::getAPFloatSemanticsValue(OpBuilder &b, Location loc,
- FloatType floatTy) {
+using namespace mlir;
+
+Value mlir::getAPFloatSemanticsValue(OpBuilder &b, Location loc,
+ FloatType floatTy) {
int32_t sem = llvm::APFloatBase::SemanticsToEnum(floatTy.getFloatSemantics());
return arith::ConstantOp::create(b, loc, b.getI32Type(),
b.getIntegerAttr(b.getI32Type(), sem));
}
+
+LogicalResult mlir::checkPreconditions(RewriterBase &rewriter, Operation *op) {
+ for (Value value : llvm::concat<Value>(op->getOperands(), op->getResults())) {
+ Type type = value.getType();
+ if (auto vecTy = dyn_cast<VectorType>(type)) {
+ type = vecTy.getElementType();
+ }
+ if (!type.isIntOrFloat()) {
+ return rewriter.notifyMatchFailure(
+ op, "only integers and floats (or vectors thereof) are supported");
+ }
+ if (type.getIntOrFloatBitWidth() > 64)
+ return rewriter.notifyMatchFailure(op,
+ "bitwidth > 64 bits is not supported");
+ }
+ return success();
+}
diff --git a/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.h b/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.h
index 5f11d24261b43..d38d3b4c93945 100644
--- a/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.h
+++ b/mlir/lib/Conversion/ArithAndMathToAPFloat/Utils.h
@@ -9,6 +9,9 @@
#ifndef MLIR_CONVERSION_ARITHANDMATHTOAPFLOAT_UTILS_H_
#define MLIR_CONVERSION_ARITHANDMATHTOAPFLOAT_UTILS_H_
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/IR/PatternMatch.h"
+
namespace mlir {
class Value;
class OpBuilder;
@@ -16,6 +19,59 @@ class Location;
class FloatType;
Value getAPFloatSemanticsValue(OpBuilder &b, Location loc, FloatType floatTy);
+
+/// Given two operands of vector type and vector result type (with the same
+/// shape), call the given function for each pair of scalar operands and
+/// package the result into a vector. If the given operands and result type are
+/// not vectors, call the function directly. The second operand is optional.
+template <typename Fn, typename... Values>
+Value forEachScalarValue(mlir::RewriterBase &rewriter, Location loc,
+ Value operand1, Value operand2, Type resultType,
+ Fn fn) {
+ auto vecTy1 = dyn_cast<VectorType>(operand1.getType());
+ if (operand2) {
+ // Sanity check: Operand types must match.
+ assert(vecTy1 == dyn_cast<VectorType>(operand2.getType()) &&
+ "expected same vector types");
+ }
+ if (!vecTy1) {
+ // Not a vector. Call the function directly.
+ return fn(operand1, operand2, resultType);
+ }
+
+ // Prepare scalar operands.
+ ResultRange sclars1 =
+ vector::ToElementsOp::create(rewriter, loc, operand1)->getResults();
+ SmallVector<Value> scalars2;
+ if (!operand2) {
+ // No second operand. Create a vector of empty values.
+ scalars2.assign(vecTy1.getNumElements(), Value());
+ } else {
+ llvm::append_range(
+ scalars2,
+ vector::ToElementsOp::create(rewriter, loc, operand2)->getResults());
+ }
+
+ // Call the function for each pair of scalar operands.
+ auto resultVecType = cast<VectorType>(resultType);
+ SmallVector<Value> results;
+ for (auto [scalar1, scalar2] : llvm::zip_equal(sclars1, scalars2)) {
+ Value result = fn(scalar1, scalar2, resultVecType.getElementType());
+ results.push_back(result);
+ }
+
+ // Package the results into a vector.
+ return vector::FromElementsOp::create(
+ rewriter, loc,
+ vecTy1.cloneWith(/*shape=*/std::nullopt, results.front().getType()),
+ results);
+}
+
+/// Check preconditions for the conversion:
+/// 1. All operands / results must be integers or floats (or vectors thereof).
+/// 2. The bitwidth of the operands / results must be <= 64.
+LogicalResult checkPreconditions(RewriterBase &rewriter, Operation *op);
+
} // namespace mlir
#endif // MLIR_CONVERSION_ARITHANDMATHTOAPFLOAT_UTILS_H_
More information about the Mlir-commits
mailing list