23#define GEN_PASS_DEF_MATHTOAPFLOATCONVERSIONPASS
24#include "mlir/Conversion/Passes.h.inc"
40 auto i32Type = IntegerType::get(
symTable->getContext(), 32);
41 auto i64Type = IntegerType::get(
symTable->getContext(), 64);
43 rewriter,
symTable,
"_mlir_apfloat_abs", {i32Type, i64Type});
52 auto floatTy = cast<FloatType>(operand.getType());
53 auto intWType = rewriter.getIntegerType(floatTy.getWidth());
54 Value operandBits = arith::ExtUIOp::create(
55 rewriter, loc, i64Type,
56 arith::BitcastOp::create(rewriter, loc, intWType, operand));
58 Value semValue = getAPFloatSemanticsValue(rewriter, loc, floatTy);
59 SmallVector<Value> params = {semValue, operandBits};
61 func::CallOp::create(rewriter, loc,
TypeRange(i64Type),
62 SymbolRefAttr::get(*fn), params)
66 arith::TruncIOp::create(rewriter, loc, intWType, negatedBits);
67 return arith::BitcastOp::create(rewriter, loc, floatTy,
71 rewriter.replaceOp(op, repl);
78template <
typename OpTy>
91 auto i1 = IntegerType::get(
symTable->getContext(), 1);
92 auto i32Type = IntegerType::get(
symTable->getContext(), 32);
93 auto i64Type = IntegerType::get(
symTable->getContext(), 64);
94 std::string funcName =
95 (llvm::Twine(
"_mlir_apfloat_is") +
APFloatName).str();
97 rewriter,
symTable, funcName, {i32Type, i64Type},
nullptr, i1);
104 rewriter, loc, op.getOperand(),
Value(), op.getType(),
106 auto floatTy = cast<FloatType>(operand.getType());
107 auto intWType = rewriter.getIntegerType(floatTy.getWidth());
108 Value operandBits = arith::ExtUIOp::create(
109 rewriter, loc, i64Type,
110 arith::BitcastOp::create(rewriter, loc, intWType, operand));
113 Value semValue = getAPFloatSemanticsValue(rewriter, loc, floatTy);
114 Value params[] = {semValue, operandBits};
115 return func::CallOp::create(rewriter, loc,
TypeRange(i1),
116 SymbolRefAttr::get(*fn), params)
119 rewriter.replaceOp(op, repl);
137 mlir::Type resType = op.getResult().getType();
138 auto floatTy = dyn_cast<FloatType>(resType);
140 auto vecTy1 = cast<VectorType>(resType);
141 floatTy = llvm::cast<FloatType>(vecTy1.getElementType());
143 auto i32Type = IntegerType::get(
symTable->getContext(), 32);
144 auto i64Type = IntegerType::get(
symTable->getContext(), 64);
146 rewriter,
symTable,
"_mlir_apfloat_fused_multiply_add",
147 {i32Type, i64Type, i64Type, i64Type});
153 IntegerType intWType = rewriter.
getIntegerType(floatTy.getWidth());
154 IntegerType int64Type = rewriter.
getI64Type();
156 auto scalarFMA = [&rewriter, &loc, &floatTy, &fn, &intWType,
158 Value operand = arith::ExtUIOp::create(
159 rewriter, loc, int64Type,
160 arith::BitcastOp::create(rewriter, loc, intWType, a));
161 Value multiplicand = arith::ExtUIOp::create(
162 rewriter, loc, int64Type,
163 arith::BitcastOp::create(rewriter, loc, intWType,
b));
164 Value addend = arith::ExtUIOp::create(
165 rewriter, loc, int64Type,
166 arith::BitcastOp::create(rewriter, loc, intWType, c));
172 SymbolRefAttr::get(*fn), params);
175 auto trunc = arith::TruncIOp::create(rewriter, loc, intWType,
176 resultOp->getResult(0));
177 return arith::BitcastOp::create(rewriter, loc, floatTy, trunc);
180 if (
auto vecTy1 = dyn_cast<VectorType>(op.getA().getType())) {
182 assert(vecTy1 == dyn_cast<VectorType>(op.getB().getType()) &&
183 "expected same vector types");
184 assert(vecTy1 == dyn_cast<VectorType>(op.getC().getType()) &&
185 "expected same vector types");
188 vector::ToElementsOp::create(rewriter, loc, op.getA())->getResults();
190 vector::ToElementsOp::create(rewriter, loc, op.getB())->getResults();
192 vector::ToElementsOp::create(rewriter, loc, op.getC())->getResults();
195 for (
auto [operand, multiplicand, addend] : llvm::zip_equal(
196 scalarOperands, scalarMultiplicands, scalarAddends)) {
197 results.push_back(scalarFMA(operand, multiplicand, addend));
200 auto fromElements = vector::FromElementsOp::create(
202 vecTy1.cloneWith(std::nullopt, results.front().getType()),
208 Value repl = scalarFMA(op.getA(), op.getB(), op.getC());
217struct MathToAPFloatConversionPass final
221 void runOnOperation()
override;
224void MathToAPFloatConversionPass::runOnOperation() {
226 RewritePatternSet patterns(context);
228 patterns.add<AbsFOpToAPFloatConversion>(context, getOperation());
229 patterns.add<IsOpToAPFloatConversion<math::IsFiniteOp>>(context,
"finite",
231 patterns.add<IsOpToAPFloatConversion<math::IsInfOp>>(context,
"infinite",
233 patterns.add<IsOpToAPFloatConversion<math::IsNaNOp>>(context,
"nan",
235 patterns.add<IsOpToAPFloatConversion<math::IsNormalOp>>(context,
"normal",
237 patterns.add<FmaOpToAPFloatConversion>(context, getOperation());
240 ScopedDiagnosticHandler scopedHandler(context, [&
result](Diagnostic &
diag) {
241 if (
diag.getSeverity() == DiagnosticSeverity::Error) {
250 return signalPassFailure();
static std::string diag(const llvm::Value &value)
IntegerType getIntegerType(unsigned width)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class implements the result iterators for the Operation class.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
FailureOr< FuncOp > lookupOrCreateFnDecl(OpBuilder &b, SymbolOpInterface symTable, StringRef name, TypeRange paramTypes, SymbolTableCollection *symbolTables=nullptr, Type resultType={})
Helper function to look up or create the symbol for a runtime library function with the given paramet...
Include the generated interface declarations.
LogicalResult checkPreconditions(RewriterBase &rewriter, Operation *op)
Check preconditions for the conversion:
Value getAPFloatSemanticsValue(OpBuilder &b, Location loc, FloatType floatTy)
Value forEachScalarValue(mlir::RewriterBase &rewriter, Location loc, Value operand1, Value operand2, Type resultType, llvm::function_ref< Value(Value, Value, Type)> fn)
Given two operands of vector type and vector result type (with the same shape), call the given functi...
void walkAndApplyPatterns(Operation *op, const FrozenRewritePatternSet &patterns, RewriterBase::Listener *listener=nullptr)
A fast walk-based pattern rewrite driver.
LogicalResult matchAndRewrite(math::AbsFOp op, PatternRewriter &rewriter) const override
SymbolOpInterface symTable
AbsFOpToAPFloatConversion(MLIRContext *context, SymbolOpInterface symTable, PatternBenefit benefit=1)
SymbolOpInterface symTable
LogicalResult matchAndRewrite(math::FmaOp op, PatternRewriter &rewriter) const override
FmaOpToAPFloatConversion(MLIRContext *context, SymbolOpInterface symTable, PatternBenefit benefit=1)
SymbolOpInterface symTable
LogicalResult matchAndRewrite(OpTy op, PatternRewriter &rewriter) const override
IsOpToAPFloatConversion(MLIRContext *context, const char *APFloatName, SymbolOpInterface symTable, PatternBenefit benefit=1)
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})