MLIR 24.0.0git
MathToEmitC.cpp
Go to the documentation of this file.
1//===- MathToEmitC.cpp - Math to EmitC Patterns -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
16
17using namespace mlir;
18
19namespace {
20/// Implement the interface to convert Math to EmitC.
21struct MathToEmitCDialectInterface : public ConvertToEmitCPatternInterface {
22 MathToEmitCDialectInterface(Dialect *dialect)
23 : ConvertToEmitCPatternInterface(dialect) {}
24
25 /// Hook for derived dialect interface to provide conversion patterns
26 /// and mark dialect legal for the conversion target.
27 void populateConvertToEmitCConversionPatterns(
28 ConversionTarget &target, TypeConverter &typeConverter,
29 RewritePatternSet &patterns, std::optional<bool> lowerToCpp) const final {
31 patterns, lowerToCpp.value_or(true) ? emitc::LanguageTarget::cpp11
32 : emitc::LanguageTarget::c99);
33 }
34};
35
36template <typename OpType>
37class LowerToEmitCCallOpaque : public OpRewritePattern<OpType> {
38 std::string calleeStr;
39 emitc::LanguageTarget languageTarget;
40 bool typeSuffix;
41
42public:
43 LowerToEmitCCallOpaque(MLIRContext *context, std::string calleeStr,
44 emitc::LanguageTarget languageTarget,
45 bool typeSuffix = true)
46 : OpRewritePattern<OpType>(context), calleeStr(std::move(calleeStr)),
47 languageTarget(languageTarget), typeSuffix(typeSuffix) {}
48
49 LogicalResult matchAndRewrite(OpType op,
50 PatternRewriter &rewriter) const override;
51};
52
53template <typename OpType>
54LogicalResult LowerToEmitCCallOpaque<OpType>::matchAndRewrite(
55 OpType op, PatternRewriter &rewriter) const {
56 if (!llvm::all_of(op->getOperandTypes(),
57 llvm::IsaPred<Float32Type, Float64Type>) ||
58 !llvm::all_of(op->getResultTypes(), [](Type type) {
59 return isa<Float32Type, Float64Type>(type) || type.isInteger(1);
60 }))
61 return rewriter.notifyMatchFailure(
62 op.getLoc(), "expected all operands to be of type f32 or f64, and "
63 "all results to be of type f32, f64 or i1");
64 if (auto roundingModeOp =
65 dyn_cast<arith::ArithRoundingModeInterface>(op.getOperation());
66 roundingModeOp && roundingModeOp.getRoundingModeAttr())
67 return rewriter.notifyMatchFailure(op.getLoc(),
68 "static rounding mode not supported");
69 std::string modifiedCalleeStr = calleeStr;
70 if (languageTarget == emitc::LanguageTarget::cpp11) {
71 modifiedCalleeStr = "std::" + calleeStr;
72 } else if (languageTarget == emitc::LanguageTarget::c99 && typeSuffix) {
73 auto operandType = op->getOperandTypes()[0];
74 if (operandType.isF32())
75 modifiedCalleeStr = calleeStr + "f";
76 }
77 rewriter.replaceOpWithNewOp<emitc::CallOpaqueOp>(
78 op, op.getType(), modifiedCalleeStr, op->getOperands());
79 return success();
80}
81
82} // namespace
83
85 registry.addExtension(+[](MLIRContext *ctx, math::MathDialect *dialect) {
86 dialect->addInterfaces<MathToEmitCDialectInterface>();
87 });
88}
89
90// Populates patterns to replace `math` operations with `emitc.call_opaque`,
91// using function names consistent with those in <math.h> or a builtin.
93 RewritePatternSet &patterns, emitc::LanguageTarget languageTarget) {
94 auto *context = patterns.getContext();
95 patterns.insert<LowerToEmitCCallOpaque<math::FloorOp>>(context, "floor",
96 languageTarget);
97 patterns.insert<LowerToEmitCCallOpaque<math::RoundOp>>(context, "round",
98 languageTarget);
99 patterns.insert<LowerToEmitCCallOpaque<math::RoundEvenOp>>(
100 context, "__builtin_roundeven", emitc::LanguageTarget::c99);
101 patterns.insert<LowerToEmitCCallOpaque<math::ExpOp>>(context, "exp",
102 languageTarget);
103 patterns.insert<LowerToEmitCCallOpaque<math::CosOp>>(context, "cos",
104 languageTarget);
105 patterns.insert<LowerToEmitCCallOpaque<math::SinOp>>(context, "sin",
106 languageTarget);
107 patterns.insert<LowerToEmitCCallOpaque<math::AcosOp>>(context, "acos",
108 languageTarget);
109 patterns.insert<LowerToEmitCCallOpaque<math::AsinOp>>(context, "asin",
110 languageTarget);
111 patterns.insert<LowerToEmitCCallOpaque<math::Atan2Op>>(context, "atan2",
112 languageTarget);
113 patterns.insert<LowerToEmitCCallOpaque<math::CeilOp>>(context, "ceil",
114 languageTarget);
115 patterns.insert<LowerToEmitCCallOpaque<math::AbsFOp>>(context, "fabs",
116 languageTarget);
117 patterns.insert<LowerToEmitCCallOpaque<math::PowFOp>>(context, "pow",
118 languageTarget);
119 patterns.insert<LowerToEmitCCallOpaque<math::SqrtOp>>(context, "sqrt",
120 languageTarget);
121 patterns.insert<LowerToEmitCCallOpaque<math::TanOp>>(context, "tan",
122 languageTarget);
123 patterns.insert<LowerToEmitCCallOpaque<math::AtanOp>>(context, "atan",
124 languageTarget);
125 patterns.insert<LowerToEmitCCallOpaque<math::SinhOp>>(context, "sinh",
126 languageTarget);
127 patterns.insert<LowerToEmitCCallOpaque<math::CoshOp>>(context, "cosh",
128 languageTarget);
129 patterns.insert<LowerToEmitCCallOpaque<math::TanhOp>>(context, "tanh",
130 languageTarget);
131 patterns.insert<LowerToEmitCCallOpaque<math::AsinhOp>>(context, "asinh",
132 languageTarget);
133 patterns.insert<LowerToEmitCCallOpaque<math::AcoshOp>>(context, "acosh",
134 languageTarget);
135 patterns.insert<LowerToEmitCCallOpaque<math::AtanhOp>>(context, "atanh",
136 languageTarget);
137 patterns.insert<LowerToEmitCCallOpaque<math::Exp2Op>>(context, "exp2",
138 languageTarget);
139 patterns.insert<LowerToEmitCCallOpaque<math::ExpM1Op>>(context, "expm1",
140 languageTarget);
141 patterns.insert<LowerToEmitCCallOpaque<math::LogOp>>(context, "log",
142 languageTarget);
143 patterns.insert<LowerToEmitCCallOpaque<math::Log2Op>>(context, "log2",
144 languageTarget);
145 patterns.insert<LowerToEmitCCallOpaque<math::Log10Op>>(context, "log10",
146 languageTarget);
147 patterns.insert<LowerToEmitCCallOpaque<math::Log1pOp>>(context, "log1p",
148 languageTarget);
149 patterns.insert<LowerToEmitCCallOpaque<math::CbrtOp>>(context, "cbrt",
150 languageTarget);
151 patterns.insert<LowerToEmitCCallOpaque<math::ErfOp>>(context, "erf",
152 languageTarget);
153 patterns.insert<LowerToEmitCCallOpaque<math::ErfcOp>>(context, "erfc",
154 languageTarget);
155 patterns.insert<LowerToEmitCCallOpaque<math::TruncOp>>(context, "trunc",
156 languageTarget);
157 patterns.insert<LowerToEmitCCallOpaque<math::CopySignOp>>(context, "copysign",
158 languageTarget);
159 patterns.insert<LowerToEmitCCallOpaque<math::FmaOp>>(context, "fma",
160 languageTarget);
161 patterns.insert<LowerToEmitCCallOpaque<math::IsNaNOp>>(
162 context, "isnan", languageTarget, /*typeSuffix=*/false);
163 patterns.insert<LowerToEmitCCallOpaque<math::IsInfOp>>(
164 context, "isinf", languageTarget, /*typeSuffix=*/false);
165 patterns.insert<LowerToEmitCCallOpaque<math::IsFiniteOp>>(
166 context, "isfinite", languageTarget, /*typeSuffix=*/false);
167 patterns.insert<LowerToEmitCCallOpaque<math::IsNormalOp>>(
168 context, "isnormal", languageTarget, /*typeSuffix=*/false);
169}
return success()
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:71
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
RewritePatternSet & insert(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
MLIRContext * getContext() const
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
LanguageTarget
Enum to specify the language target for EmitC code generation.
Definition MathToEmitC.h:17
Include the generated interface declarations.
void registerConvertMathToEmitCInterface(DialectRegistry &registry)
void populateConvertMathToEmitCPatterns(RewritePatternSet &patterns, emitc::LanguageTarget languageTarget)
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...