22#include "llvm/ADT/STLExtras.h"
23#include "llvm/Support/ErrorHandling.h"
27#define GEN_PASS_DEF_ARITHEMULATEUNSUPPORTEDFLOATS
28#include "mlir/Dialect/Arith/Transforms/Passes.h.inc"
34struct EmulateUnsupportedFloatsPass
35 : arith::impl::ArithEmulateUnsupportedFloatsBase<
36 EmulateUnsupportedFloatsPass> {
37 using arith::impl::ArithEmulateUnsupportedFloatsBase<
38 EmulateUnsupportedFloatsPass>::ArithEmulateUnsupportedFloatsBase;
40 void runOnOperation()
override;
44 EmulateFloatPattern(
const TypeConverter &converter, MLIRContext *ctx)
45 : ConversionPattern::ConversionPattern(
46 converter, Pattern::MatchAnyOpTypeTag(), 1, ctx) {}
49 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
50 ConversionPatternRewriter &rewriter)
const override;
54LogicalResult EmulateFloatPattern::matchAndRewrite(
56 ConversionPatternRewriter &rewriter)
const {
57 if (getTypeConverter()->isLegal(op))
63 Location loc = op->
getLoc();
64 const TypeConverter *converter = getTypeConverter();
65 SmallVector<Type> resultTypes;
69 return op->
emitOpError(
"type conversion failed in float emulation");
71 OperationState state(loc, op->
getName(), operands, resultTypes,
75 Operation *expandedOp = rewriter.create(state);
76 SmallVector<Value> newResults(expandedOp->
getResults());
77 for (
auto [res, oldType, newType] : llvm::zip_equal(
79 if (oldType != newType) {
80 auto truncFOp = arith::TruncFOp::create(rewriter, loc, oldType, res);
81 truncFOp.setFastmath(arith::FastMathFlags::contract);
82 res = truncFOp.getResult();
85 rewriter.replaceOp(op, newResults);
92 targetType](
Type type) -> std::optional<Type> {
93 if (llvm::is_contained(sourceTypes, type))
95 if (
auto shaped = dyn_cast<ShapedType>(type))
96 if (llvm::is_contained(sourceTypes, shaped.getElementType()))
97 return shaped.clone(targetType);
101 converter.addTargetMaterialization(
103 auto extFOp = arith::ExtFOp::create(
b, loc,
target, input.front(),
104 arith::FastMathFlagsAttr{});
105 extFOp.setFastmath(arith::FastMathFlags::contract);
112 patterns.
add<EmulateFloatPattern>(converter, patterns.
getContext());
118 target.markUnknownOpDynamicallyLegal([](
Operation *op) {
return true; });
119 target.addDynamicallyLegalDialect<arith::ArithDialect>(
120 [&](
Operation *op) -> std::optional<bool> {
121 return converter.isLegal(op);
124 target.addDynamicallyLegalOp<vector::ContractionOp, vector::ReductionOp,
125 vector::MultiDimReductionOp, vector::FMAOp,
126 vector::OuterProductOp, vector::ScanOp>(
127 [&](
Operation *op) {
return converter.isLegal(op); });
128 target.addLegalOp<arith::BitcastOp, arith::ExtFOp, arith::TruncFOp,
129 arith::ConstantOp, arith::SelectOp, vector::BroadcastOp>();
132void EmulateUnsupportedFloatsPass::runOnOperation() {
139 if (!parsedTargetType) {
140 emitError(UnknownLoc::get(ctx),
"could not map target type '" +
142 "' to a known floating-point type");
143 return signalPassFailure();
145 targetType = parsedTargetType;
146 for (StringRef sourceTypeStr : sourceTypeStrs) {
149 emitError(UnknownLoc::get(ctx),
"could not map source type '" +
151 "' to a known floating-point type");
152 return signalPassFailure();
154 sourceTypes.push_back(sourceType);
156 if (sourceTypes.empty())
159 "no source types specified, float emulation will do nothing");
161 if (llvm::is_contained(sourceTypes, targetType)) {
163 "target type cannot be an unsupported source type");
164 return signalPassFailure();
166 TypeConverter converter;
167 arith::populateEmulateUnsupportedFloatsConversions(converter, sourceTypes,
169 RewritePatternSet patterns(ctx);
170 arith::populateEmulateUnsupportedFloatsPatterns(patterns, converter);
172 arith::populateEmulateUnsupportedFloatsLegality(
target, converter);
174 if (
failed(applyPartialConversion(op,
target, std::move(patterns))))
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.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
OperationName getName()
The name of an operation is the key identifier for it.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
result_type_range getResultTypes()
SuccessorRange getSuccessors()
result_range getResults()
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
FloatType parseFloatType(MLIRContext *ctx, StringRef name)
void populateEmulateUnsupportedFloatsPatterns(RewritePatternSet &patterns, const TypeConverter &converter)
Add rewrite patterns for converting operations that use illegal float types to ones that use legal on...
void populateEmulateUnsupportedFloatsLegality(ConversionTarget &target, const TypeConverter &converter)
Set up a dialect conversion to reject arithmetic operations on unsupported float types.
void populateEmulateUnsupportedFloatsConversions(TypeConverter &converter, ArrayRef< Type > sourceTypes, Type targetType)
Populate the type conversions needed to emulate the unsupported sourceTypes with destType
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult emitOptionalWarning(std::optional< Location > loc, Args &&...args)