xref: /llvm-project/mlir/lib/Dialect/Math/IR/MathOps.cpp (revision b8dca4fa729fcbd5d42ce3ca056dc4d278da2548)
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