23 #define GET_OP_CLASSES
24 #include "mlir/Dialect/Math/IR/MathOps.cpp.inc"
31 return constFoldUnaryOp<FloatAttr>(adaptor.getOperands(),
32 [](
const APFloat &a) { return abs(a); });
40 return constFoldUnaryOp<IntegerAttr>(adaptor.getOperands(),
41 [](
const APInt &a) { return a.abs(); });
49 return constFoldUnaryOpConditional<FloatAttr>(
50 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
51 switch (a.getSizeInBits(a.getSemantics())) {
53 return APFloat(acos(a.convertToDouble()));
55 return APFloat(acosf(a.convertToFloat()));
67 return constFoldUnaryOpConditional<FloatAttr>(
68 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
69 switch (a.getSizeInBits(a.getSemantics())) {
71 return APFloat(acosh(a.convertToDouble()));
73 return APFloat(acoshf(a.convertToFloat()));
85 return constFoldUnaryOpConditional<FloatAttr>(
86 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
87 switch (a.getSizeInBits(a.getSemantics())) {
89 return APFloat(asin(a.convertToDouble()));
91 return APFloat(asinf(a.convertToFloat()));
103 return constFoldUnaryOpConditional<FloatAttr>(
104 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
105 switch (a.getSizeInBits(a.getSemantics())) {
107 return APFloat(asinh(a.convertToDouble()));
109 return APFloat(asinhf(a.convertToFloat()));
121 return constFoldUnaryOpConditional<FloatAttr>(
122 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
123 switch (a.getSizeInBits(a.getSemantics())) {
125 return APFloat(atan(a.convertToDouble()));
127 return APFloat(atanf(a.convertToFloat()));
139 return constFoldUnaryOpConditional<FloatAttr>(
140 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
141 switch (a.getSizeInBits(a.getSemantics())) {
143 return APFloat(atanh(a.convertToDouble()));
145 return APFloat(atanhf(a.convertToFloat()));
157 return constFoldBinaryOpConditional<FloatAttr>(
158 adaptor.getOperands(),
159 [](
const APFloat &a,
const APFloat &b) -> std::optional<APFloat> {
160 if (a.isZero() && b.isZero())
161 return llvm::APFloat::getNaN(a.getSemantics());
163 if (a.getSizeInBits(a.getSemantics()) == 64 &&
164 b.getSizeInBits(b.getSemantics()) == 64)
165 return APFloat(atan2(a.convertToDouble(), b.convertToDouble()));
167 if (a.getSizeInBits(a.getSemantics()) == 32 &&
168 b.getSizeInBits(b.getSemantics()) == 32)
169 return APFloat(atan2f(a.convertToFloat(), b.convertToFloat()));
180 return constFoldUnaryOp<FloatAttr>(
181 adaptor.getOperands(), [](
const APFloat &a) {
183 result.roundToIntegral(llvm::RoundingMode::TowardPositive);
192 OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {
193 return constFoldBinaryOp<FloatAttr>(adaptor.getOperands(),
194 [](
const APFloat &a,
const APFloat &b) {
206 return constFoldUnaryOpConditional<FloatAttr>(
207 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
208 switch (a.getSizeInBits(a.getSemantics())) {
210 return APFloat(cos(a.convertToDouble()));
212 return APFloat(cosf(a.convertToFloat()));
224 return constFoldUnaryOpConditional<FloatAttr>(
225 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
226 switch (a.getSizeInBits(a.getSemantics())) {
228 return APFloat(cosh(a.convertToDouble()));
230 return APFloat(coshf(a.convertToFloat()));
242 return constFoldUnaryOpConditional<FloatAttr>(
243 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
244 switch (a.getSizeInBits(a.getSemantics())) {
246 return APFloat(sin(a.convertToDouble()));
248 return APFloat(sinf(a.convertToFloat()));
260 return constFoldUnaryOpConditional<FloatAttr>(
261 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
262 switch (a.getSizeInBits(a.getSemantics())) {
264 return APFloat(sinh(a.convertToDouble()));
266 return APFloat(sinhf(a.convertToFloat()));
277 OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {
278 return constFoldUnaryOp<IntegerAttr>(
279 adaptor.getOperands(),
280 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });
287 OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {
288 return constFoldUnaryOp<IntegerAttr>(
289 adaptor.getOperands(),
290 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });
298 return constFoldUnaryOp<IntegerAttr>(
299 adaptor.getOperands(),
300 [](
const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });
308 return constFoldUnaryOpConditional<FloatAttr>(
309 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
310 switch (a.getSizeInBits(a.getSemantics())) {
312 return APFloat(erf(a.convertToDouble()));
314 return APFloat(erff(a.convertToFloat()));
326 return constFoldBinaryOpConditional<IntegerAttr>(
327 adaptor.getOperands(),
328 [](
const APInt &base,
const APInt &power) -> std::optional<APInt> {
329 unsigned width = base.getBitWidth();
330 auto zeroValue = APInt::getZero(width);
331 APInt oneValue{width, 1ULL, true};
332 APInt minusOneValue{width, -1ULL, true};
337 if (power.isNegative()) {
341 if (base.eq(oneValue))
344 if (base.ne(minusOneValue))
350 return minusOneValue;
356 APInt result = oneValue;
357 APInt curBase = base;
358 APInt curPower = power;
360 if (curPower[0] == 1)
362 curPower.lshrInPlace(1);
363 if (curPower.isZero())
377 return constFoldUnaryOpConditional<FloatAttr>(
378 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
382 if (a.getSizeInBits(a.getSemantics()) == 64)
383 return APFloat(log(a.convertToDouble()));
385 if (a.getSizeInBits(a.getSemantics()) == 32)
386 return APFloat(logf(a.convertToFloat()));
397 return constFoldUnaryOpConditional<FloatAttr>(
398 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
402 if (a.getSizeInBits(a.getSemantics()) == 64)
403 return APFloat(log2(a.convertToDouble()));
405 if (a.getSizeInBits(a.getSemantics()) == 32)
406 return APFloat(log2f(a.convertToFloat()));
417 return constFoldUnaryOpConditional<FloatAttr>(
418 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
422 switch (a.getSizeInBits(a.getSemantics())) {
424 return APFloat(log10(a.convertToDouble()));
426 return APFloat(log10f(a.convertToFloat()));
438 return constFoldUnaryOpConditional<FloatAttr>(
439 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
440 switch (a.getSizeInBits(a.getSemantics())) {
442 if ((a + APFloat(1.0)).isNegative())
444 return APFloat(log1p(a.convertToDouble()));
446 if ((a + APFloat(1.0f)).isNegative())
448 return APFloat(log1pf(a.convertToFloat()));
460 return constFoldBinaryOpConditional<FloatAttr>(
461 adaptor.getOperands(),
462 [](
const APFloat &a,
const APFloat &b) -> std::optional<APFloat> {
463 if (a.getSizeInBits(a.getSemantics()) == 64 &&
464 b.getSizeInBits(b.getSemantics()) == 64)
465 return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
467 if (a.getSizeInBits(a.getSemantics()) == 32 &&
468 b.getSizeInBits(b.getSemantics()) == 32)
469 return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
480 return constFoldUnaryOpConditional<FloatAttr>(
481 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
485 switch (a.getSizeInBits(a.getSemantics())) {
487 return APFloat(sqrt(a.convertToDouble()));
489 return APFloat(sqrtf(a.convertToFloat()));
501 return constFoldUnaryOpConditional<FloatAttr>(
502 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
503 switch (a.getSizeInBits(a.getSemantics())) {
505 return APFloat(exp(a.convertToDouble()));
507 return APFloat(expf(a.convertToFloat()));
519 return constFoldUnaryOpConditional<FloatAttr>(
520 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
521 switch (a.getSizeInBits(a.getSemantics())) {
523 return APFloat(exp2(a.convertToDouble()));
525 return APFloat(exp2f(a.convertToFloat()));
537 return constFoldUnaryOpConditional<FloatAttr>(
538 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
539 switch (a.getSizeInBits(a.getSemantics())) {
541 return APFloat(expm1(a.convertToDouble()));
543 return APFloat(expm1f(a.convertToFloat()));
555 return constFoldUnaryOpConditional<FloatAttr>(
556 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
557 switch (a.getSizeInBits(a.getSemantics())) {
559 return APFloat(tan(a.convertToDouble()));
561 return APFloat(tanf(a.convertToFloat()));
573 return constFoldUnaryOpConditional<FloatAttr>(
574 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
575 switch (a.getSizeInBits(a.getSemantics())) {
577 return APFloat(tanh(a.convertToDouble()));
579 return APFloat(tanhf(a.convertToFloat()));
590 OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
591 return constFoldUnaryOp<FloatAttr>(
592 adaptor.getOperands(), [](
const APFloat &a) {
594 result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
604 return constFoldUnaryOp<FloatAttr>(
605 adaptor.getOperands(), [](
const APFloat &a) {
607 result.roundToIntegral(llvm::RoundingMode::TowardNegative);
617 return constFoldUnaryOpConditional<FloatAttr>(
618 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
619 switch (a.getSizeInBits(a.getSemantics())) {
621 return APFloat(round(a.convertToDouble()));
623 return APFloat(roundf(a.convertToFloat()));
635 return constFoldUnaryOpConditional<FloatAttr>(
636 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
637 switch (a.getSizeInBits(a.getSemantics())) {
639 return APFloat(trunc(a.convertToDouble()));
641 return APFloat(truncf(a.convertToFloat()));
652 if (
auto poison = dyn_cast<ub::PoisonAttr>(value))
653 return builder.
create<ub::PoisonOp>(loc, type, poison);
655 return arith::ConstantOp::materialize(builder, value, type, loc);
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
Attributes are known-constant values of operations.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Include the generated interface declarations.