14348d8abSStephan Herhut //===- MathOps.cpp - MLIR operations for math implementation --------------===//
24348d8abSStephan Herhut //
34348d8abSStephan Herhut // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44348d8abSStephan Herhut // See https://llvm.org/LICENSE.txt for license information.
54348d8abSStephan Herhut // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64348d8abSStephan Herhut //
74348d8abSStephan Herhut //===----------------------------------------------------------------------===//
84348d8abSStephan Herhut
9abc362a1SJakub Kuderski #include "mlir/Dialect/Arith/IR/Arith.h"
1083bd4fe2Sjacquesguan #include "mlir/Dialect/CommonFolders.h"
114348d8abSStephan Herhut #include "mlir/Dialect/Math/IR/Math.h"
125dce7481SIvan Butygin #include "mlir/Dialect/UB/IR/UBOps.h"
131773dddaSWilliam S. Moses #include "mlir/IR/Builders.h"
14a1fe1f5fSKazu Hirata #include <optional>
154348d8abSStephan Herhut
164348d8abSStephan Herhut using namespace mlir;
174348d8abSStephan Herhut using namespace mlir::math;
184348d8abSStephan Herhut
194348d8abSStephan Herhut //===----------------------------------------------------------------------===//
204348d8abSStephan Herhut // TableGen'd op method definitions
214348d8abSStephan Herhut //===----------------------------------------------------------------------===//
224348d8abSStephan Herhut
234348d8abSStephan Herhut #define GET_OP_CLASSES
244348d8abSStephan Herhut #include "mlir/Dialect/Math/IR/MathOps.cpp.inc"
251773dddaSWilliam S. Moses
261773dddaSWilliam S. Moses //===----------------------------------------------------------------------===//
2700f7096dSJeff Niu // AbsFOp folder
28e609417cSjacquesguan //===----------------------------------------------------------------------===//
29e609417cSjacquesguan
fold(FoldAdaptor adaptor)306c30503eSMarkus Böck OpFoldResult math::AbsFOp::fold(FoldAdaptor adaptor) {
316c30503eSMarkus Böck return constFoldUnaryOp<FloatAttr>(adaptor.getOperands(),
3200f7096dSJeff Niu [](const APFloat &a) { return abs(a); });
33e609417cSjacquesguan }
34e609417cSjacquesguan
35e609417cSjacquesguan //===----------------------------------------------------------------------===//
367d9fc95bSJeff Niu // AbsIOp folder
377d9fc95bSJeff Niu //===----------------------------------------------------------------------===//
387d9fc95bSJeff Niu
fold(FoldAdaptor adaptor)396c30503eSMarkus Böck OpFoldResult math::AbsIOp::fold(FoldAdaptor adaptor) {
406c30503eSMarkus Böck return constFoldUnaryOp<IntegerAttr>(adaptor.getOperands(),
417d9fc95bSJeff Niu [](const APInt &a) { return a.abs(); });
427d9fc95bSJeff Niu }
437d9fc95bSJeff Niu
447d9fc95bSJeff Niu //===----------------------------------------------------------------------===//
45f7250179SFrederik Harwath // AcosOp folder
46f7250179SFrederik Harwath //===----------------------------------------------------------------------===//
47f7250179SFrederik Harwath
fold(FoldAdaptor adaptor)48f7250179SFrederik Harwath OpFoldResult math::AcosOp::fold(FoldAdaptor adaptor) {
49f7250179SFrederik Harwath return constFoldUnaryOpConditional<FloatAttr>(
50f7250179SFrederik Harwath adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
51f7250179SFrederik Harwath switch (a.getSizeInBits(a.getSemantics())) {
52f7250179SFrederik Harwath case 64:
53f7250179SFrederik Harwath return APFloat(acos(a.convertToDouble()));
54f7250179SFrederik Harwath case 32:
55f7250179SFrederik Harwath return APFloat(acosf(a.convertToFloat()));
56f7250179SFrederik Harwath default:
57f7250179SFrederik Harwath return {};
58f7250179SFrederik Harwath }
59f7250179SFrederik Harwath });
60f7250179SFrederik Harwath }
61f7250179SFrederik Harwath
62f7250179SFrederik Harwath //===----------------------------------------------------------------------===//
63*b8dca4faSVivek Khandelwal // AcoshOp folder
64*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
65*b8dca4faSVivek Khandelwal
fold(FoldAdaptor adaptor)66*b8dca4faSVivek Khandelwal OpFoldResult math::AcoshOp::fold(FoldAdaptor adaptor) {
67*b8dca4faSVivek Khandelwal return constFoldUnaryOpConditional<FloatAttr>(
68*b8dca4faSVivek Khandelwal adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
69*b8dca4faSVivek Khandelwal switch (a.getSizeInBits(a.getSemantics())) {
70*b8dca4faSVivek Khandelwal case 64:
71*b8dca4faSVivek Khandelwal return APFloat(acosh(a.convertToDouble()));
72*b8dca4faSVivek Khandelwal case 32:
73*b8dca4faSVivek Khandelwal return APFloat(acoshf(a.convertToFloat()));
74*b8dca4faSVivek Khandelwal default:
75*b8dca4faSVivek Khandelwal return {};
76*b8dca4faSVivek Khandelwal }
77*b8dca4faSVivek Khandelwal });
78*b8dca4faSVivek Khandelwal }
79*b8dca4faSVivek Khandelwal
80*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
81*b8dca4faSVivek Khandelwal // AsinOp folder
82*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
83*b8dca4faSVivek Khandelwal
fold(FoldAdaptor adaptor)84*b8dca4faSVivek Khandelwal OpFoldResult math::AsinOp::fold(FoldAdaptor adaptor) {
85*b8dca4faSVivek Khandelwal return constFoldUnaryOpConditional<FloatAttr>(
86*b8dca4faSVivek Khandelwal adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
87*b8dca4faSVivek Khandelwal switch (a.getSizeInBits(a.getSemantics())) {
88*b8dca4faSVivek Khandelwal case 64:
89*b8dca4faSVivek Khandelwal return APFloat(asin(a.convertToDouble()));
90*b8dca4faSVivek Khandelwal case 32:
91*b8dca4faSVivek Khandelwal return APFloat(asinf(a.convertToFloat()));
92*b8dca4faSVivek Khandelwal default:
93*b8dca4faSVivek Khandelwal return {};
94*b8dca4faSVivek Khandelwal }
95*b8dca4faSVivek Khandelwal });
96*b8dca4faSVivek Khandelwal }
97*b8dca4faSVivek Khandelwal
98*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
99*b8dca4faSVivek Khandelwal // AsinhOp folder
100*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
101*b8dca4faSVivek Khandelwal
fold(FoldAdaptor adaptor)102*b8dca4faSVivek Khandelwal OpFoldResult math::AsinhOp::fold(FoldAdaptor adaptor) {
103*b8dca4faSVivek Khandelwal return constFoldUnaryOpConditional<FloatAttr>(
104*b8dca4faSVivek Khandelwal adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
105*b8dca4faSVivek Khandelwal switch (a.getSizeInBits(a.getSemantics())) {
106*b8dca4faSVivek Khandelwal case 64:
107*b8dca4faSVivek Khandelwal return APFloat(asinh(a.convertToDouble()));
108*b8dca4faSVivek Khandelwal case 32:
109*b8dca4faSVivek Khandelwal return APFloat(asinhf(a.convertToFloat()));
110*b8dca4faSVivek Khandelwal default:
111*b8dca4faSVivek Khandelwal return {};
112*b8dca4faSVivek Khandelwal }
113*b8dca4faSVivek Khandelwal });
114*b8dca4faSVivek Khandelwal }
115*b8dca4faSVivek Khandelwal
116*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
117752c9d0dSjacquesguan // AtanOp folder
118752c9d0dSjacquesguan //===----------------------------------------------------------------------===//
119752c9d0dSjacquesguan
fold(FoldAdaptor adaptor)1206c30503eSMarkus Böck OpFoldResult math::AtanOp::fold(FoldAdaptor adaptor) {
121752c9d0dSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
1220a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
123752c9d0dSjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
124752c9d0dSjacquesguan case 64:
125752c9d0dSjacquesguan return APFloat(atan(a.convertToDouble()));
126752c9d0dSjacquesguan case 32:
127752c9d0dSjacquesguan return APFloat(atanf(a.convertToFloat()));
128752c9d0dSjacquesguan default:
129752c9d0dSjacquesguan return {};
130752c9d0dSjacquesguan }
131752c9d0dSjacquesguan });
132752c9d0dSjacquesguan }
133752c9d0dSjacquesguan
134752c9d0dSjacquesguan //===----------------------------------------------------------------------===//
135*b8dca4faSVivek Khandelwal // AtanhOp folder
136*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
137*b8dca4faSVivek Khandelwal
fold(FoldAdaptor adaptor)138*b8dca4faSVivek Khandelwal OpFoldResult math::AtanhOp::fold(FoldAdaptor adaptor) {
139*b8dca4faSVivek Khandelwal return constFoldUnaryOpConditional<FloatAttr>(
140*b8dca4faSVivek Khandelwal adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
141*b8dca4faSVivek Khandelwal switch (a.getSizeInBits(a.getSemantics())) {
142*b8dca4faSVivek Khandelwal case 64:
143*b8dca4faSVivek Khandelwal return APFloat(atanh(a.convertToDouble()));
144*b8dca4faSVivek Khandelwal case 32:
145*b8dca4faSVivek Khandelwal return APFloat(atanhf(a.convertToFloat()));
146*b8dca4faSVivek Khandelwal default:
147*b8dca4faSVivek Khandelwal return {};
148*b8dca4faSVivek Khandelwal }
149*b8dca4faSVivek Khandelwal });
150*b8dca4faSVivek Khandelwal }
151*b8dca4faSVivek Khandelwal
152*b8dca4faSVivek Khandelwal //===----------------------------------------------------------------------===//
15340d74fcbSjacquesguan // Atan2Op folder
15440d74fcbSjacquesguan //===----------------------------------------------------------------------===//
15540d74fcbSjacquesguan
fold(FoldAdaptor adaptor)1566c30503eSMarkus Böck OpFoldResult math::Atan2Op::fold(FoldAdaptor adaptor) {
15740d74fcbSjacquesguan return constFoldBinaryOpConditional<FloatAttr>(
1586c30503eSMarkus Böck adaptor.getOperands(),
1590a81ace0SKazu Hirata [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
16040d74fcbSjacquesguan if (a.isZero() && b.isZero())
16140d74fcbSjacquesguan return llvm::APFloat::getNaN(a.getSemantics());
16240d74fcbSjacquesguan
16340d74fcbSjacquesguan if (a.getSizeInBits(a.getSemantics()) == 64 &&
16440d74fcbSjacquesguan b.getSizeInBits(b.getSemantics()) == 64)
16540d74fcbSjacquesguan return APFloat(atan2(a.convertToDouble(), b.convertToDouble()));
16640d74fcbSjacquesguan
16740d74fcbSjacquesguan if (a.getSizeInBits(a.getSemantics()) == 32 &&
16840d74fcbSjacquesguan b.getSizeInBits(b.getSemantics()) == 32)
16940d74fcbSjacquesguan return APFloat(atan2f(a.convertToFloat(), b.convertToFloat()));
17040d74fcbSjacquesguan
17140d74fcbSjacquesguan return {};
17240d74fcbSjacquesguan });
17340d74fcbSjacquesguan }
17440d74fcbSjacquesguan
17540d74fcbSjacquesguan //===----------------------------------------------------------------------===//
1761773dddaSWilliam S. Moses // CeilOp folder
1771773dddaSWilliam S. Moses //===----------------------------------------------------------------------===//
1781773dddaSWilliam S. Moses
fold(FoldAdaptor adaptor)1796c30503eSMarkus Böck OpFoldResult math::CeilOp::fold(FoldAdaptor adaptor) {
1806c30503eSMarkus Böck return constFoldUnaryOp<FloatAttr>(
1816c30503eSMarkus Böck adaptor.getOperands(), [](const APFloat &a) {
18283bd4fe2Sjacquesguan APFloat result(a);
18383bd4fe2Sjacquesguan result.roundToIntegral(llvm::RoundingMode::TowardPositive);
18483bd4fe2Sjacquesguan return result;
18583bd4fe2Sjacquesguan });
1861773dddaSWilliam S. Moses }
1871773dddaSWilliam S. Moses
1881773dddaSWilliam S. Moses //===----------------------------------------------------------------------===//
189e609417cSjacquesguan // CopySignOp folder
190e609417cSjacquesguan //===----------------------------------------------------------------------===//
191e609417cSjacquesguan
fold(FoldAdaptor adaptor)1926c30503eSMarkus Böck OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {
1936c30503eSMarkus Böck return constFoldBinaryOp<FloatAttr>(adaptor.getOperands(),
19483bd4fe2Sjacquesguan [](const APFloat &a, const APFloat &b) {
19583bd4fe2Sjacquesguan APFloat result(a);
19683bd4fe2Sjacquesguan result.copySign(b);
19783bd4fe2Sjacquesguan return result;
19883bd4fe2Sjacquesguan });
199e609417cSjacquesguan }
200e609417cSjacquesguan
201e609417cSjacquesguan //===----------------------------------------------------------------------===//
202e3434a86Sjacquesguan // CosOp folder
203e3434a86Sjacquesguan //===----------------------------------------------------------------------===//
204e3434a86Sjacquesguan
fold(FoldAdaptor adaptor)2056c30503eSMarkus Böck OpFoldResult math::CosOp::fold(FoldAdaptor adaptor) {
206e3434a86Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
2070a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
208e3434a86Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
209e3434a86Sjacquesguan case 64:
210e3434a86Sjacquesguan return APFloat(cos(a.convertToDouble()));
211e3434a86Sjacquesguan case 32:
212e3434a86Sjacquesguan return APFloat(cosf(a.convertToFloat()));
213e3434a86Sjacquesguan default:
214e3434a86Sjacquesguan return {};
215e3434a86Sjacquesguan }
216e3434a86Sjacquesguan });
217e3434a86Sjacquesguan }
218e3434a86Sjacquesguan
219e3434a86Sjacquesguan //===----------------------------------------------------------------------===//
220762964e9SSungsoon Cho // CoshOp folder
221762964e9SSungsoon Cho //===----------------------------------------------------------------------===//
222762964e9SSungsoon Cho
fold(FoldAdaptor adaptor)223762964e9SSungsoon Cho OpFoldResult math::CoshOp::fold(FoldAdaptor adaptor) {
224762964e9SSungsoon Cho return constFoldUnaryOpConditional<FloatAttr>(
225762964e9SSungsoon Cho adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
226762964e9SSungsoon Cho switch (a.getSizeInBits(a.getSemantics())) {
227762964e9SSungsoon Cho case 64:
228762964e9SSungsoon Cho return APFloat(cosh(a.convertToDouble()));
229762964e9SSungsoon Cho case 32:
230762964e9SSungsoon Cho return APFloat(coshf(a.convertToFloat()));
231762964e9SSungsoon Cho default:
232762964e9SSungsoon Cho return {};
233762964e9SSungsoon Cho }
234762964e9SSungsoon Cho });
235762964e9SSungsoon Cho }
236762964e9SSungsoon Cho
237762964e9SSungsoon Cho //===----------------------------------------------------------------------===//
23871e52a12Sjacquesguan // SinOp folder
23971e52a12Sjacquesguan //===----------------------------------------------------------------------===//
24071e52a12Sjacquesguan
fold(FoldAdaptor adaptor)2416c30503eSMarkus Böck OpFoldResult math::SinOp::fold(FoldAdaptor adaptor) {
24271e52a12Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
2430a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
24471e52a12Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
24571e52a12Sjacquesguan case 64:
24671e52a12Sjacquesguan return APFloat(sin(a.convertToDouble()));
24771e52a12Sjacquesguan case 32:
24871e52a12Sjacquesguan return APFloat(sinf(a.convertToFloat()));
24971e52a12Sjacquesguan default:
25071e52a12Sjacquesguan return {};
25171e52a12Sjacquesguan }
25271e52a12Sjacquesguan });
25371e52a12Sjacquesguan }
25471e52a12Sjacquesguan
25571e52a12Sjacquesguan //===----------------------------------------------------------------------===//
256aa165edcSRob Suderman // SinhOp folder
257aa165edcSRob Suderman //===----------------------------------------------------------------------===//
258aa165edcSRob Suderman
fold(FoldAdaptor adaptor)259aa165edcSRob Suderman OpFoldResult math::SinhOp::fold(FoldAdaptor adaptor) {
260aa165edcSRob Suderman return constFoldUnaryOpConditional<FloatAttr>(
261aa165edcSRob Suderman adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
262aa165edcSRob Suderman switch (a.getSizeInBits(a.getSemantics())) {
263aa165edcSRob Suderman case 64:
264aa165edcSRob Suderman return APFloat(sinh(a.convertToDouble()));
265aa165edcSRob Suderman case 32:
266aa165edcSRob Suderman return APFloat(sinhf(a.convertToFloat()));
267aa165edcSRob Suderman default:
268aa165edcSRob Suderman return {};
269aa165edcSRob Suderman }
270aa165edcSRob Suderman });
271aa165edcSRob Suderman }
272aa165edcSRob Suderman
273aa165edcSRob Suderman //===----------------------------------------------------------------------===//
274e609417cSjacquesguan // CountLeadingZerosOp folder
275e609417cSjacquesguan //===----------------------------------------------------------------------===//
276e609417cSjacquesguan
fold(FoldAdaptor adaptor)2776c30503eSMarkus Böck OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {
2786c30503eSMarkus Böck return constFoldUnaryOp<IntegerAttr>(
279f8f3db27SKazu Hirata adaptor.getOperands(),
280f8f3db27SKazu Hirata [](const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });
281e609417cSjacquesguan }
282e609417cSjacquesguan
283e609417cSjacquesguan //===----------------------------------------------------------------------===//
284e609417cSjacquesguan // CountTrailingZerosOp folder
285e609417cSjacquesguan //===----------------------------------------------------------------------===//
286e609417cSjacquesguan
fold(FoldAdaptor adaptor)2876c30503eSMarkus Böck OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {
2886c30503eSMarkus Böck return constFoldUnaryOp<IntegerAttr>(
289f8f3db27SKazu Hirata adaptor.getOperands(),
290f8f3db27SKazu Hirata [](const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });
291e609417cSjacquesguan }
292e609417cSjacquesguan
293e609417cSjacquesguan //===----------------------------------------------------------------------===//
294e609417cSjacquesguan // CtPopOp folder
295e609417cSjacquesguan //===----------------------------------------------------------------------===//
296e609417cSjacquesguan
fold(FoldAdaptor adaptor)2976c30503eSMarkus Böck OpFoldResult math::CtPopOp::fold(FoldAdaptor adaptor) {
2986c30503eSMarkus Böck return constFoldUnaryOp<IntegerAttr>(
299cbde2124SKazu Hirata adaptor.getOperands(),
300cbde2124SKazu Hirata [](const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });
301e609417cSjacquesguan }
302e609417cSjacquesguan
303e609417cSjacquesguan //===----------------------------------------------------------------------===//
3046eebdc46Sjacquesguan // ErfOp folder
3056eebdc46Sjacquesguan //===----------------------------------------------------------------------===//
3066eebdc46Sjacquesguan
fold(FoldAdaptor adaptor)3076c30503eSMarkus Böck OpFoldResult math::ErfOp::fold(FoldAdaptor adaptor) {
3086eebdc46Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
3090a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
3106eebdc46Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
3116eebdc46Sjacquesguan case 64:
3126eebdc46Sjacquesguan return APFloat(erf(a.convertToDouble()));
3136eebdc46Sjacquesguan case 32:
3146eebdc46Sjacquesguan return APFloat(erff(a.convertToFloat()));
3156eebdc46Sjacquesguan default:
3166eebdc46Sjacquesguan return {};
3176eebdc46Sjacquesguan }
3186eebdc46Sjacquesguan });
3196eebdc46Sjacquesguan }
3206eebdc46Sjacquesguan
3216eebdc46Sjacquesguan //===----------------------------------------------------------------------===//
322cd3a234fSSlava Zakharin // IPowIOp folder
323cd3a234fSSlava Zakharin //===----------------------------------------------------------------------===//
324cd3a234fSSlava Zakharin
fold(FoldAdaptor adaptor)3256c30503eSMarkus Böck OpFoldResult math::IPowIOp::fold(FoldAdaptor adaptor) {
326cd3a234fSSlava Zakharin return constFoldBinaryOpConditional<IntegerAttr>(
3276c30503eSMarkus Böck adaptor.getOperands(),
3280a81ace0SKazu Hirata [](const APInt &base, const APInt &power) -> std::optional<APInt> {
329cd3a234fSSlava Zakharin unsigned width = base.getBitWidth();
330cd3a234fSSlava Zakharin auto zeroValue = APInt::getZero(width);
331cd3a234fSSlava Zakharin APInt oneValue{width, 1ULL, /*isSigned=*/true};
332cd3a234fSSlava Zakharin APInt minusOneValue{width, -1ULL, /*isSigned=*/true};
333cd3a234fSSlava Zakharin
334cd3a234fSSlava Zakharin if (power.isZero())
335cd3a234fSSlava Zakharin return oneValue;
336cd3a234fSSlava Zakharin
337cd3a234fSSlava Zakharin if (power.isNegative()) {
338cd3a234fSSlava Zakharin // Leave 0 raised to negative power not folded.
339cd3a234fSSlava Zakharin if (base.isZero())
340cd3a234fSSlava Zakharin return {};
341cd3a234fSSlava Zakharin if (base.eq(oneValue))
342cd3a234fSSlava Zakharin return oneValue;
343cd3a234fSSlava Zakharin // If abs(base) > 1, then the result is zero.
344cd3a234fSSlava Zakharin if (base.ne(minusOneValue))
345cd3a234fSSlava Zakharin return zeroValue;
346cd3a234fSSlava Zakharin // base == -1:
347cd3a234fSSlava Zakharin // -1: power is odd
348cd3a234fSSlava Zakharin // 1: power is even
349cd3a234fSSlava Zakharin if (power[0] == 1)
350cd3a234fSSlava Zakharin return minusOneValue;
351cd3a234fSSlava Zakharin
352cd3a234fSSlava Zakharin return oneValue;
353cd3a234fSSlava Zakharin }
354cd3a234fSSlava Zakharin
355cd3a234fSSlava Zakharin // power is positive.
356cd3a234fSSlava Zakharin APInt result = oneValue;
357cd3a234fSSlava Zakharin APInt curBase = base;
358cd3a234fSSlava Zakharin APInt curPower = power;
359cd3a234fSSlava Zakharin while (true) {
360cd3a234fSSlava Zakharin if (curPower[0] == 1)
361cd3a234fSSlava Zakharin result *= curBase;
362cd3a234fSSlava Zakharin curPower.lshrInPlace(1);
363cd3a234fSSlava Zakharin if (curPower.isZero())
364cd3a234fSSlava Zakharin return result;
365cd3a234fSSlava Zakharin curBase *= curBase;
366cd3a234fSSlava Zakharin }
367cd3a234fSSlava Zakharin });
368cd3a234fSSlava Zakharin
369cd3a234fSSlava Zakharin return Attribute();
370cd3a234fSSlava Zakharin }
371cd3a234fSSlava Zakharin
372cd3a234fSSlava Zakharin //===----------------------------------------------------------------------===//
3739c22853eSjacquesguan // LogOp folder
3749c22853eSjacquesguan //===----------------------------------------------------------------------===//
3759c22853eSjacquesguan
fold(FoldAdaptor adaptor)3766c30503eSMarkus Böck OpFoldResult math::LogOp::fold(FoldAdaptor adaptor) {
3779c22853eSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
3780a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
3799c22853eSjacquesguan if (a.isNegative())
3809c22853eSjacquesguan return {};
3819c22853eSjacquesguan
3829c22853eSjacquesguan if (a.getSizeInBits(a.getSemantics()) == 64)
3839c22853eSjacquesguan return APFloat(log(a.convertToDouble()));
3849c22853eSjacquesguan
3859c22853eSjacquesguan if (a.getSizeInBits(a.getSemantics()) == 32)
3869c22853eSjacquesguan return APFloat(logf(a.convertToFloat()));
3879c22853eSjacquesguan
3889c22853eSjacquesguan return {};
3899c22853eSjacquesguan });
3909c22853eSjacquesguan }
3919c22853eSjacquesguan
3929c22853eSjacquesguan //===----------------------------------------------------------------------===//
3931773dddaSWilliam S. Moses // Log2Op folder
3941773dddaSWilliam S. Moses //===----------------------------------------------------------------------===//
3951773dddaSWilliam S. Moses
fold(FoldAdaptor adaptor)3966c30503eSMarkus Böck OpFoldResult math::Log2Op::fold(FoldAdaptor adaptor) {
397ad4b7fb3Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
3980a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
399ad4b7fb3Sjacquesguan if (a.isNegative())
4001773dddaSWilliam S. Moses return {};
4011773dddaSWilliam S. Moses
402ad4b7fb3Sjacquesguan if (a.getSizeInBits(a.getSemantics()) == 64)
403ad4b7fb3Sjacquesguan return APFloat(log2(a.convertToDouble()));
4041773dddaSWilliam S. Moses
405ad4b7fb3Sjacquesguan if (a.getSizeInBits(a.getSemantics()) == 32)
406ad4b7fb3Sjacquesguan return APFloat(log2f(a.convertToFloat()));
407164c7afaSWilliam S. Moses
408164c7afaSWilliam S. Moses return {};
409ad4b7fb3Sjacquesguan });
410164c7afaSWilliam S. Moses }
411164c7afaSWilliam S. Moses
412164c7afaSWilliam S. Moses //===----------------------------------------------------------------------===//
413a5cae20bSjacquesguan // Log10Op folder
414a5cae20bSjacquesguan //===----------------------------------------------------------------------===//
415a5cae20bSjacquesguan
fold(FoldAdaptor adaptor)4166c30503eSMarkus Böck OpFoldResult math::Log10Op::fold(FoldAdaptor adaptor) {
417a5cae20bSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
4180a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
419a5cae20bSjacquesguan if (a.isNegative())
420a5cae20bSjacquesguan return {};
421a5cae20bSjacquesguan
422a5cae20bSjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
423a5cae20bSjacquesguan case 64:
424a5cae20bSjacquesguan return APFloat(log10(a.convertToDouble()));
425a5cae20bSjacquesguan case 32:
426a5cae20bSjacquesguan return APFloat(log10f(a.convertToFloat()));
427a5cae20bSjacquesguan default:
428a5cae20bSjacquesguan return {};
429a5cae20bSjacquesguan }
430a5cae20bSjacquesguan });
431a5cae20bSjacquesguan }
432a5cae20bSjacquesguan
433a5cae20bSjacquesguan //===----------------------------------------------------------------------===//
434c3d856bfSjacquesguan // Log1pOp folder
435c3d856bfSjacquesguan //===----------------------------------------------------------------------===//
436c3d856bfSjacquesguan
fold(FoldAdaptor adaptor)4376c30503eSMarkus Böck OpFoldResult math::Log1pOp::fold(FoldAdaptor adaptor) {
438c3d856bfSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
4390a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
440c3d856bfSjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
441c3d856bfSjacquesguan case 64:
442c3d856bfSjacquesguan if ((a + APFloat(1.0)).isNegative())
443c3d856bfSjacquesguan return {};
444c3d856bfSjacquesguan return APFloat(log1p(a.convertToDouble()));
445c3d856bfSjacquesguan case 32:
446c3d856bfSjacquesguan if ((a + APFloat(1.0f)).isNegative())
447c3d856bfSjacquesguan return {};
448c3d856bfSjacquesguan return APFloat(log1pf(a.convertToFloat()));
449c3d856bfSjacquesguan default:
450c3d856bfSjacquesguan return {};
451c3d856bfSjacquesguan }
452c3d856bfSjacquesguan });
453c3d856bfSjacquesguan }
454c3d856bfSjacquesguan
455c3d856bfSjacquesguan //===----------------------------------------------------------------------===//
456164c7afaSWilliam S. Moses // PowFOp folder
457164c7afaSWilliam S. Moses //===----------------------------------------------------------------------===//
458164c7afaSWilliam S. Moses
fold(FoldAdaptor adaptor)4596c30503eSMarkus Böck OpFoldResult math::PowFOp::fold(FoldAdaptor adaptor) {
460362240e0Sjacquesguan return constFoldBinaryOpConditional<FloatAttr>(
4616c30503eSMarkus Böck adaptor.getOperands(),
4620a81ace0SKazu Hirata [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
463362240e0Sjacquesguan if (a.getSizeInBits(a.getSemantics()) == 64 &&
464362240e0Sjacquesguan b.getSizeInBits(b.getSemantics()) == 64)
465362240e0Sjacquesguan return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
466164c7afaSWilliam S. Moses
467362240e0Sjacquesguan if (a.getSizeInBits(a.getSemantics()) == 32 &&
468362240e0Sjacquesguan b.getSizeInBits(b.getSemantics()) == 32)
469362240e0Sjacquesguan return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
4701773dddaSWilliam S. Moses
4711773dddaSWilliam S. Moses return {};
472362240e0Sjacquesguan });
4731773dddaSWilliam S. Moses }
4741773dddaSWilliam S. Moses
4754d7d5c5fSjacquesguan //===----------------------------------------------------------------------===//
4764d7d5c5fSjacquesguan // SqrtOp folder
4774d7d5c5fSjacquesguan //===----------------------------------------------------------------------===//
4784d7d5c5fSjacquesguan
fold(FoldAdaptor adaptor)4796c30503eSMarkus Böck OpFoldResult math::SqrtOp::fold(FoldAdaptor adaptor) {
4804d7d5c5fSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
4810a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
4824d7d5c5fSjacquesguan if (a.isNegative())
48326c95ae3Sjacquesguan return {};
48426c95ae3Sjacquesguan
4854d7d5c5fSjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
4864d7d5c5fSjacquesguan case 64:
4874d7d5c5fSjacquesguan return APFloat(sqrt(a.convertToDouble()));
4884d7d5c5fSjacquesguan case 32:
4894d7d5c5fSjacquesguan return APFloat(sqrtf(a.convertToFloat()));
4904d7d5c5fSjacquesguan default:
49126c95ae3Sjacquesguan return {};
4924d7d5c5fSjacquesguan }
4934d7d5c5fSjacquesguan });
49426c95ae3Sjacquesguan }
49526c95ae3Sjacquesguan
4969e241c70Sjacquesguan //===----------------------------------------------------------------------===//
4979e241c70Sjacquesguan // ExpOp folder
4989e241c70Sjacquesguan //===----------------------------------------------------------------------===//
4999e241c70Sjacquesguan
fold(FoldAdaptor adaptor)5006c30503eSMarkus Böck OpFoldResult math::ExpOp::fold(FoldAdaptor adaptor) {
5019e241c70Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
5020a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
5039e241c70Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
5049e241c70Sjacquesguan case 64:
5059e241c70Sjacquesguan return APFloat(exp(a.convertToDouble()));
5069e241c70Sjacquesguan case 32:
5079e241c70Sjacquesguan return APFloat(expf(a.convertToFloat()));
5089e241c70Sjacquesguan default:
5099e241c70Sjacquesguan return {};
5109e241c70Sjacquesguan }
5119e241c70Sjacquesguan });
5129e241c70Sjacquesguan }
5139e241c70Sjacquesguan
51478015047Sjacquesguan //===----------------------------------------------------------------------===//
51578015047Sjacquesguan // Exp2Op folder
51678015047Sjacquesguan //===----------------------------------------------------------------------===//
51778015047Sjacquesguan
fold(FoldAdaptor adaptor)5186c30503eSMarkus Böck OpFoldResult math::Exp2Op::fold(FoldAdaptor adaptor) {
51978015047Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
5200a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
52178015047Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
52278015047Sjacquesguan case 64:
52378015047Sjacquesguan return APFloat(exp2(a.convertToDouble()));
52478015047Sjacquesguan case 32:
52578015047Sjacquesguan return APFloat(exp2f(a.convertToFloat()));
52678015047Sjacquesguan default:
52778015047Sjacquesguan return {};
52878015047Sjacquesguan }
52978015047Sjacquesguan });
53078015047Sjacquesguan }
53178015047Sjacquesguan
53216cb6ce5Sjacquesguan //===----------------------------------------------------------------------===//
53316cb6ce5Sjacquesguan // ExpM1Op folder
53416cb6ce5Sjacquesguan //===----------------------------------------------------------------------===//
53516cb6ce5Sjacquesguan
fold(FoldAdaptor adaptor)5366c30503eSMarkus Böck OpFoldResult math::ExpM1Op::fold(FoldAdaptor adaptor) {
53716cb6ce5Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
5380a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
53916cb6ce5Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
54016cb6ce5Sjacquesguan case 64:
54116cb6ce5Sjacquesguan return APFloat(expm1(a.convertToDouble()));
54216cb6ce5Sjacquesguan case 32:
54316cb6ce5Sjacquesguan return APFloat(expm1f(a.convertToFloat()));
54416cb6ce5Sjacquesguan default:
54516cb6ce5Sjacquesguan return {};
54616cb6ce5Sjacquesguan }
54716cb6ce5Sjacquesguan });
54816cb6ce5Sjacquesguan }
54916cb6ce5Sjacquesguan
550f1033a3fSjacquesguan //===----------------------------------------------------------------------===//
551f1033a3fSjacquesguan // TanOp folder
552f1033a3fSjacquesguan //===----------------------------------------------------------------------===//
553f1033a3fSjacquesguan
fold(FoldAdaptor adaptor)5546c30503eSMarkus Böck OpFoldResult math::TanOp::fold(FoldAdaptor adaptor) {
555f1033a3fSjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
5560a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
557f1033a3fSjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
558f1033a3fSjacquesguan case 64:
559f1033a3fSjacquesguan return APFloat(tan(a.convertToDouble()));
560f1033a3fSjacquesguan case 32:
561f1033a3fSjacquesguan return APFloat(tanf(a.convertToFloat()));
562f1033a3fSjacquesguan default:
563f1033a3fSjacquesguan return {};
564f1033a3fSjacquesguan }
565f1033a3fSjacquesguan });
566f1033a3fSjacquesguan }
567f1033a3fSjacquesguan
568008ea1c2Sjacquesguan //===----------------------------------------------------------------------===//
569008ea1c2Sjacquesguan // TanhOp folder
570008ea1c2Sjacquesguan //===----------------------------------------------------------------------===//
571008ea1c2Sjacquesguan
fold(FoldAdaptor adaptor)5726c30503eSMarkus Böck OpFoldResult math::TanhOp::fold(FoldAdaptor adaptor) {
573008ea1c2Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
5740a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
575008ea1c2Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
576008ea1c2Sjacquesguan case 64:
577008ea1c2Sjacquesguan return APFloat(tanh(a.convertToDouble()));
578008ea1c2Sjacquesguan case 32:
579008ea1c2Sjacquesguan return APFloat(tanhf(a.convertToFloat()));
580008ea1c2Sjacquesguan default:
581008ea1c2Sjacquesguan return {};
582008ea1c2Sjacquesguan }
583008ea1c2Sjacquesguan });
584008ea1c2Sjacquesguan }
585008ea1c2Sjacquesguan
586ac66d87cSjacquesguan //===----------------------------------------------------------------------===//
587ac66d87cSjacquesguan // RoundEvenOp folder
588ac66d87cSjacquesguan //===----------------------------------------------------------------------===//
589ac66d87cSjacquesguan
fold(FoldAdaptor adaptor)5906c30503eSMarkus Böck OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
5916c30503eSMarkus Böck return constFoldUnaryOp<FloatAttr>(
5926c30503eSMarkus Böck adaptor.getOperands(), [](const APFloat &a) {
593238e08d6Sjacquesguan APFloat result(a);
594238e08d6Sjacquesguan result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
595238e08d6Sjacquesguan return result;
596ac66d87cSjacquesguan });
597ac66d87cSjacquesguan }
598ac66d87cSjacquesguan
599b53bccb1Sjacquesguan //===----------------------------------------------------------------------===//
6005bb62105SKai Sasaki // FloorOp folder
6015bb62105SKai Sasaki //===----------------------------------------------------------------------===//
6025bb62105SKai Sasaki
fold(FoldAdaptor adaptor)6036c30503eSMarkus Böck OpFoldResult math::FloorOp::fold(FoldAdaptor adaptor) {
6046c30503eSMarkus Böck return constFoldUnaryOp<FloatAttr>(
6056c30503eSMarkus Böck adaptor.getOperands(), [](const APFloat &a) {
6065bb62105SKai Sasaki APFloat result(a);
6075bb62105SKai Sasaki result.roundToIntegral(llvm::RoundingMode::TowardNegative);
6085bb62105SKai Sasaki return result;
6095bb62105SKai Sasaki });
6105bb62105SKai Sasaki }
6115bb62105SKai Sasaki
6125bb62105SKai Sasaki //===----------------------------------------------------------------------===//
613b53bccb1Sjacquesguan // RoundOp folder
614b53bccb1Sjacquesguan //===----------------------------------------------------------------------===//
615b53bccb1Sjacquesguan
fold(FoldAdaptor adaptor)6166c30503eSMarkus Böck OpFoldResult math::RoundOp::fold(FoldAdaptor adaptor) {
617b53bccb1Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
6180a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
619b53bccb1Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
620b53bccb1Sjacquesguan case 64:
621b53bccb1Sjacquesguan return APFloat(round(a.convertToDouble()));
622b53bccb1Sjacquesguan case 32:
623b53bccb1Sjacquesguan return APFloat(roundf(a.convertToFloat()));
624b53bccb1Sjacquesguan default:
625b53bccb1Sjacquesguan return {};
626b53bccb1Sjacquesguan }
627b53bccb1Sjacquesguan });
628b53bccb1Sjacquesguan }
629b53bccb1Sjacquesguan
6309d0b90e9Sjacquesguan //===----------------------------------------------------------------------===//
6319d0b90e9Sjacquesguan // TruncOp folder
6329d0b90e9Sjacquesguan //===----------------------------------------------------------------------===//
6339d0b90e9Sjacquesguan
fold(FoldAdaptor adaptor)6346c30503eSMarkus Böck OpFoldResult math::TruncOp::fold(FoldAdaptor adaptor) {
6359d0b90e9Sjacquesguan return constFoldUnaryOpConditional<FloatAttr>(
6360a81ace0SKazu Hirata adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
6379d0b90e9Sjacquesguan switch (a.getSizeInBits(a.getSemantics())) {
6389d0b90e9Sjacquesguan case 64:
6399d0b90e9Sjacquesguan return APFloat(trunc(a.convertToDouble()));
6409d0b90e9Sjacquesguan case 32:
6419d0b90e9Sjacquesguan return APFloat(truncf(a.convertToFloat()));
6429d0b90e9Sjacquesguan default:
6439d0b90e9Sjacquesguan return {};
6449d0b90e9Sjacquesguan }
6459d0b90e9Sjacquesguan });
6469d0b90e9Sjacquesguan }
6479d0b90e9Sjacquesguan
6481773dddaSWilliam S. Moses /// Materialize an integer or floating point constant.
materializeConstant(OpBuilder & builder,Attribute value,Type type,Location loc)6491773dddaSWilliam S. Moses Operation *math::MathDialect::materializeConstant(OpBuilder &builder,
6501773dddaSWilliam S. Moses Attribute value, Type type,
6511773dddaSWilliam S. Moses Location loc) {
6525dce7481SIvan Butygin if (auto poison = dyn_cast<ub::PoisonAttr>(value))
6535dce7481SIvan Butygin return builder.create<ub::PoisonOp>(loc, type, poison);
6545dce7481SIvan Butygin
65500e3566dSRahul Kayaith return arith::ConstantOp::materialize(builder, value, type, loc);
6561773dddaSWilliam S. Moses }
657