brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.5 KiB · bbeef0f Raw
763 lines · cpp
1//===- MathOps.cpp - MLIR operations for math implementation --------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Dialect/Arith/IR/Arith.h"10#include "mlir/Dialect/CommonFolders.h"11#include "mlir/Dialect/Math/IR/Math.h"12#include "mlir/Dialect/UB/IR/UBOps.h"13#include "mlir/IR/Builders.h"14#include <optional>15 16using namespace mlir;17using namespace mlir::math;18 19//===----------------------------------------------------------------------===//20// Common helpers21//===----------------------------------------------------------------------===//22 23/// Return the type of the same shape (scalar, vector or tensor) containing i1.24static Type getI1SameShape(Type type) {25  auto i1Type = IntegerType::get(type.getContext(), 1);26  if (auto shapedType = llvm::dyn_cast<ShapedType>(type))27    return shapedType.cloneWith(std::nullopt, i1Type);28  if (llvm::isa<UnrankedTensorType>(type))29    return UnrankedTensorType::get(i1Type);30  return i1Type;31}32 33//===----------------------------------------------------------------------===//34// TableGen'd op method definitions35//===----------------------------------------------------------------------===//36 37#define GET_OP_CLASSES38#include "mlir/Dialect/Math/IR/MathOps.cpp.inc"39 40//===----------------------------------------------------------------------===//41// AbsFOp folder42//===----------------------------------------------------------------------===//43 44OpFoldResult math::AbsFOp::fold(FoldAdaptor adaptor) {45  return constFoldUnaryOp<FloatAttr>(adaptor.getOperands(),46                                     [](const APFloat &a) { return abs(a); });47}48 49//===----------------------------------------------------------------------===//50// AbsIOp folder51//===----------------------------------------------------------------------===//52 53OpFoldResult math::AbsIOp::fold(FoldAdaptor adaptor) {54  return constFoldUnaryOp<IntegerAttr>(adaptor.getOperands(),55                                       [](const APInt &a) { return a.abs(); });56}57 58//===----------------------------------------------------------------------===//59// AcosOp folder60//===----------------------------------------------------------------------===//61 62OpFoldResult math::AcosOp::fold(FoldAdaptor adaptor) {63  return constFoldUnaryOpConditional<FloatAttr>(64      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {65        switch (a.getSizeInBits(a.getSemantics())) {66        case 64:67          return APFloat(acos(a.convertToDouble()));68        case 32:69          return APFloat(acosf(a.convertToFloat()));70        default:71          return {};72        }73      });74}75 76//===----------------------------------------------------------------------===//77// AcoshOp folder78//===----------------------------------------------------------------------===//79 80OpFoldResult math::AcoshOp::fold(FoldAdaptor adaptor) {81  return constFoldUnaryOpConditional<FloatAttr>(82      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {83        switch (a.getSizeInBits(a.getSemantics())) {84        case 64:85          return APFloat(acosh(a.convertToDouble()));86        case 32:87          return APFloat(acoshf(a.convertToFloat()));88        default:89          return {};90        }91      });92}93 94//===----------------------------------------------------------------------===//95// AsinOp folder96//===----------------------------------------------------------------------===//97 98OpFoldResult math::AsinOp::fold(FoldAdaptor adaptor) {99  return constFoldUnaryOpConditional<FloatAttr>(100      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {101        switch (a.getSizeInBits(a.getSemantics())) {102        case 64:103          return APFloat(asin(a.convertToDouble()));104        case 32:105          return APFloat(asinf(a.convertToFloat()));106        default:107          return {};108        }109      });110}111 112//===----------------------------------------------------------------------===//113// AsinhOp folder114//===----------------------------------------------------------------------===//115 116OpFoldResult math::AsinhOp::fold(FoldAdaptor adaptor) {117  return constFoldUnaryOpConditional<FloatAttr>(118      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {119        switch (a.getSizeInBits(a.getSemantics())) {120        case 64:121          return APFloat(asinh(a.convertToDouble()));122        case 32:123          return APFloat(asinhf(a.convertToFloat()));124        default:125          return {};126        }127      });128}129 130//===----------------------------------------------------------------------===//131// AtanOp folder132//===----------------------------------------------------------------------===//133 134OpFoldResult math::AtanOp::fold(FoldAdaptor adaptor) {135  return constFoldUnaryOpConditional<FloatAttr>(136      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {137        switch (a.getSizeInBits(a.getSemantics())) {138        case 64:139          return APFloat(atan(a.convertToDouble()));140        case 32:141          return APFloat(atanf(a.convertToFloat()));142        default:143          return {};144        }145      });146}147 148//===----------------------------------------------------------------------===//149// AtanhOp folder150//===----------------------------------------------------------------------===//151 152OpFoldResult math::AtanhOp::fold(FoldAdaptor adaptor) {153  return constFoldUnaryOpConditional<FloatAttr>(154      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {155        switch (a.getSizeInBits(a.getSemantics())) {156        case 64:157          return APFloat(atanh(a.convertToDouble()));158        case 32:159          return APFloat(atanhf(a.convertToFloat()));160        default:161          return {};162        }163      });164}165 166//===----------------------------------------------------------------------===//167// Atan2Op folder168//===----------------------------------------------------------------------===//169 170OpFoldResult math::Atan2Op::fold(FoldAdaptor adaptor) {171  return constFoldBinaryOpConditional<FloatAttr>(172      adaptor.getOperands(),173      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {174        if (a.isZero() && b.isZero())175          return llvm::APFloat::getNaN(a.getSemantics());176 177        if (a.getSizeInBits(a.getSemantics()) == 64 &&178            b.getSizeInBits(b.getSemantics()) == 64)179          return APFloat(atan2(a.convertToDouble(), b.convertToDouble()));180 181        if (a.getSizeInBits(a.getSemantics()) == 32 &&182            b.getSizeInBits(b.getSemantics()) == 32)183          return APFloat(atan2f(a.convertToFloat(), b.convertToFloat()));184 185        return {};186      });187}188 189//===----------------------------------------------------------------------===//190// CeilOp folder191//===----------------------------------------------------------------------===//192 193OpFoldResult math::CeilOp::fold(FoldAdaptor adaptor) {194  return constFoldUnaryOp<FloatAttr>(195      adaptor.getOperands(), [](const APFloat &a) {196        APFloat result(a);197        result.roundToIntegral(llvm::RoundingMode::TowardPositive);198        return result;199      });200}201 202//===----------------------------------------------------------------------===//203// CopySignOp folder204//===----------------------------------------------------------------------===//205 206OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {207  return constFoldBinaryOp<FloatAttr>(adaptor.getOperands(),208                                      [](const APFloat &a, const APFloat &b) {209                                        APFloat result(a);210                                        result.copySign(b);211                                        return result;212                                      });213}214 215//===----------------------------------------------------------------------===//216// CosOp folder217//===----------------------------------------------------------------------===//218 219OpFoldResult math::CosOp::fold(FoldAdaptor adaptor) {220  return constFoldUnaryOpConditional<FloatAttr>(221      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {222        switch (a.getSizeInBits(a.getSemantics())) {223        case 64:224          return APFloat(cos(a.convertToDouble()));225        case 32:226          return APFloat(cosf(a.convertToFloat()));227        default:228          return {};229        }230      });231}232 233//===----------------------------------------------------------------------===//234// CoshOp folder235//===----------------------------------------------------------------------===//236 237OpFoldResult math::CoshOp::fold(FoldAdaptor adaptor) {238  return constFoldUnaryOpConditional<FloatAttr>(239      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {240        switch (a.getSizeInBits(a.getSemantics())) {241        case 64:242          return APFloat(cosh(a.convertToDouble()));243        case 32:244          return APFloat(coshf(a.convertToFloat()));245        default:246          return {};247        }248      });249}250 251//===----------------------------------------------------------------------===//252// SinOp folder253//===----------------------------------------------------------------------===//254 255OpFoldResult math::SinOp::fold(FoldAdaptor adaptor) {256  return constFoldUnaryOpConditional<FloatAttr>(257      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {258        switch (a.getSizeInBits(a.getSemantics())) {259        case 64:260          return APFloat(sin(a.convertToDouble()));261        case 32:262          return APFloat(sinf(a.convertToFloat()));263        default:264          return {};265        }266      });267}268 269//===----------------------------------------------------------------------===//270// SinhOp folder271//===----------------------------------------------------------------------===//272 273OpFoldResult math::SinhOp::fold(FoldAdaptor adaptor) {274  return constFoldUnaryOpConditional<FloatAttr>(275      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {276        switch (a.getSizeInBits(a.getSemantics())) {277        case 64:278          return APFloat(sinh(a.convertToDouble()));279        case 32:280          return APFloat(sinhf(a.convertToFloat()));281        default:282          return {};283        }284      });285}286 287//===----------------------------------------------------------------------===//288// SinCosOp getShapeForUnroll289//===----------------------------------------------------------------------===//290 291std::optional<SmallVector<int64_t, 4>> math::SincosOp::getShapeForUnroll() {292  if (auto vt = mlir::dyn_cast<VectorType>(getOperand().getType()))293    return llvm::to_vector<4>(vt.getShape());294  return std::nullopt;295}296 297//===----------------------------------------------------------------------===//298// CountLeadingZerosOp folder299//===----------------------------------------------------------------------===//300 301OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {302  return constFoldUnaryOp<IntegerAttr>(303      adaptor.getOperands(),304      [](const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });305}306 307//===----------------------------------------------------------------------===//308// CountTrailingZerosOp folder309//===----------------------------------------------------------------------===//310 311OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {312  return constFoldUnaryOp<IntegerAttr>(313      adaptor.getOperands(),314      [](const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });315}316 317//===----------------------------------------------------------------------===//318// CtPopOp folder319//===----------------------------------------------------------------------===//320 321OpFoldResult math::CtPopOp::fold(FoldAdaptor adaptor) {322  return constFoldUnaryOp<IntegerAttr>(323      adaptor.getOperands(),324      [](const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });325}326 327//===----------------------------------------------------------------------===//328// ErfOp folder329//===----------------------------------------------------------------------===//330 331OpFoldResult math::ErfOp::fold(FoldAdaptor adaptor) {332  return constFoldUnaryOpConditional<FloatAttr>(333      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {334        switch (a.getSizeInBits(a.getSemantics())) {335        case 64:336          return APFloat(erf(a.convertToDouble()));337        case 32:338          return APFloat(erff(a.convertToFloat()));339        default:340          return {};341        }342      });343}344 345//===----------------------------------------------------------------------===//346// ErfcOp folder347//===----------------------------------------------------------------------===//348 349OpFoldResult math::ErfcOp::fold(FoldAdaptor adaptor) {350  return constFoldUnaryOpConditional<FloatAttr>(351      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {352        switch (APFloat::SemanticsToEnum(a.getSemantics())) {353        case APFloat::Semantics::S_IEEEdouble:354          return APFloat(erfc(a.convertToDouble()));355        case APFloat::Semantics::S_IEEEsingle:356          return APFloat(erfcf(a.convertToFloat()));357        default:358          return {};359        }360      });361}362 363//===----------------------------------------------------------------------===//364// IPowIOp folder365//===----------------------------------------------------------------------===//366 367OpFoldResult math::IPowIOp::fold(FoldAdaptor adaptor) {368  return constFoldBinaryOpConditional<IntegerAttr>(369      adaptor.getOperands(),370      [](const APInt &base, const APInt &power) -> std::optional<APInt> {371        unsigned width = base.getBitWidth();372        auto zeroValue = APInt::getZero(width);373        APInt oneValue{width, 1ULL, /*isSigned=*/true};374        APInt minusOneValue{width, -1ULL, /*isSigned=*/true};375 376        if (power.isZero())377          return oneValue;378 379        if (power.isNegative()) {380          // Leave 0 raised to negative power not folded.381          if (base.isZero())382            return {};383          if (base.eq(oneValue))384            return oneValue;385          // If abs(base) > 1, then the result is zero.386          if (base.ne(minusOneValue))387            return zeroValue;388          // base == -1:389          //   -1: power is odd390          //    1: power is even391          if (power[0] == 1)392            return minusOneValue;393 394          return oneValue;395        }396 397        // power is positive.398        APInt result = oneValue;399        APInt curBase = base;400        APInt curPower = power;401        while (true) {402          if (curPower[0] == 1)403            result *= curBase;404          curPower.lshrInPlace(1);405          if (curPower.isZero())406            return result;407          curBase *= curBase;408        }409      });410 411  return Attribute();412}413 414//===----------------------------------------------------------------------===//415// LogOp folder416//===----------------------------------------------------------------------===//417 418OpFoldResult math::LogOp::fold(FoldAdaptor adaptor) {419  return constFoldUnaryOpConditional<FloatAttr>(420      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {421        if (a.isNegative())422          return {};423 424        if (a.getSizeInBits(a.getSemantics()) == 64)425          return APFloat(log(a.convertToDouble()));426 427        if (a.getSizeInBits(a.getSemantics()) == 32)428          return APFloat(logf(a.convertToFloat()));429 430        return {};431      });432}433 434//===----------------------------------------------------------------------===//435// Log2Op folder436//===----------------------------------------------------------------------===//437 438OpFoldResult math::Log2Op::fold(FoldAdaptor adaptor) {439  return constFoldUnaryOpConditional<FloatAttr>(440      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {441        if (a.isNegative())442          return {};443 444        if (a.getSizeInBits(a.getSemantics()) == 64)445          return APFloat(log2(a.convertToDouble()));446 447        if (a.getSizeInBits(a.getSemantics()) == 32)448          return APFloat(log2f(a.convertToFloat()));449 450        return {};451      });452}453 454//===----------------------------------------------------------------------===//455// Log10Op folder456//===----------------------------------------------------------------------===//457 458OpFoldResult math::Log10Op::fold(FoldAdaptor adaptor) {459  return constFoldUnaryOpConditional<FloatAttr>(460      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {461        if (a.isNegative())462          return {};463 464        switch (a.getSizeInBits(a.getSemantics())) {465        case 64:466          return APFloat(log10(a.convertToDouble()));467        case 32:468          return APFloat(log10f(a.convertToFloat()));469        default:470          return {};471        }472      });473}474 475//===----------------------------------------------------------------------===//476// Log1pOp folder477//===----------------------------------------------------------------------===//478 479OpFoldResult math::Log1pOp::fold(FoldAdaptor adaptor) {480  return constFoldUnaryOpConditional<FloatAttr>(481      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {482        switch (a.getSizeInBits(a.getSemantics())) {483        case 64:484          if ((a + APFloat(1.0)).isNegative())485            return {};486          return APFloat(log1p(a.convertToDouble()));487        case 32:488          if ((a + APFloat(1.0f)).isNegative())489            return {};490          return APFloat(log1pf(a.convertToFloat()));491        default:492          return {};493        }494      });495}496 497//===----------------------------------------------------------------------===//498// PowFOp folder499//===----------------------------------------------------------------------===//500 501OpFoldResult math::PowFOp::fold(FoldAdaptor adaptor) {502  return constFoldBinaryOpConditional<FloatAttr>(503      adaptor.getOperands(),504      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {505        if (a.getSizeInBits(a.getSemantics()) == 64 &&506            b.getSizeInBits(b.getSemantics()) == 64)507          return APFloat(pow(a.convertToDouble(), b.convertToDouble()));508 509        if (a.getSizeInBits(a.getSemantics()) == 32 &&510            b.getSizeInBits(b.getSemantics()) == 32)511          return APFloat(powf(a.convertToFloat(), b.convertToFloat()));512 513        return {};514      });515}516 517//===----------------------------------------------------------------------===//518// SqrtOp folder519//===----------------------------------------------------------------------===//520 521OpFoldResult math::SqrtOp::fold(FoldAdaptor adaptor) {522  return constFoldUnaryOpConditional<FloatAttr>(523      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {524        if (a.isNegative())525          return {};526 527        switch (a.getSizeInBits(a.getSemantics())) {528        case 64:529          return APFloat(sqrt(a.convertToDouble()));530        case 32:531          return APFloat(sqrtf(a.convertToFloat()));532        default:533          return {};534        }535      });536}537 538//===----------------------------------------------------------------------===//539// ExpOp folder540//===----------------------------------------------------------------------===//541 542OpFoldResult math::ExpOp::fold(FoldAdaptor adaptor) {543  return constFoldUnaryOpConditional<FloatAttr>(544      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {545        switch (a.getSizeInBits(a.getSemantics())) {546        case 64:547          return APFloat(exp(a.convertToDouble()));548        case 32:549          return APFloat(expf(a.convertToFloat()));550        default:551          return {};552        }553      });554}555 556//===----------------------------------------------------------------------===//557// Exp2Op folder558//===----------------------------------------------------------------------===//559 560OpFoldResult math::Exp2Op::fold(FoldAdaptor adaptor) {561  return constFoldUnaryOpConditional<FloatAttr>(562      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {563        switch (a.getSizeInBits(a.getSemantics())) {564        case 64:565          return APFloat(exp2(a.convertToDouble()));566        case 32:567          return APFloat(exp2f(a.convertToFloat()));568        default:569          return {};570        }571      });572}573 574//===----------------------------------------------------------------------===//575// ExpM1Op folder576//===----------------------------------------------------------------------===//577 578OpFoldResult math::ExpM1Op::fold(FoldAdaptor adaptor) {579  return constFoldUnaryOpConditional<FloatAttr>(580      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {581        switch (a.getSizeInBits(a.getSemantics())) {582        case 64:583          return APFloat(expm1(a.convertToDouble()));584        case 32:585          return APFloat(expm1f(a.convertToFloat()));586        default:587          return {};588        }589      });590}591 592//===----------------------------------------------------------------------===//593// IsFiniteOp folder594//===----------------------------------------------------------------------===//595 596OpFoldResult math::IsFiniteOp::fold(FoldAdaptor adaptor) {597  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {598    return BoolAttr::get(val.getContext(), val.getValue().isFinite());599  }600  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {601    return DenseElementsAttr::get(602        cast<ShapedType>(getType()),603        APInt(1, splat.getSplatValue<APFloat>().isFinite()));604  }605  return {};606}607 608//===----------------------------------------------------------------------===//609// IsInfOp folder610//===----------------------------------------------------------------------===//611 612OpFoldResult math::IsInfOp::fold(FoldAdaptor adaptor) {613  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {614    return BoolAttr::get(val.getContext(), val.getValue().isInfinity());615  }616  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {617    return DenseElementsAttr::get(618        cast<ShapedType>(getType()),619        APInt(1, splat.getSplatValue<APFloat>().isInfinity()));620  }621  return {};622}623 624//===----------------------------------------------------------------------===//625// IsNaNOp folder626//===----------------------------------------------------------------------===//627 628OpFoldResult math::IsNaNOp::fold(FoldAdaptor adaptor) {629  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {630    return BoolAttr::get(val.getContext(), val.getValue().isNaN());631  }632  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {633    return DenseElementsAttr::get(634        cast<ShapedType>(getType()),635        APInt(1, splat.getSplatValue<APFloat>().isNaN()));636  }637  return {};638}639 640//===----------------------------------------------------------------------===//641// IsNormalOp folder642//===----------------------------------------------------------------------===//643 644OpFoldResult math::IsNormalOp::fold(FoldAdaptor adaptor) {645  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {646    return BoolAttr::get(val.getContext(), val.getValue().isNormal());647  }648  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {649    return DenseElementsAttr::get(650        cast<ShapedType>(getType()),651        APInt(1, splat.getSplatValue<APFloat>().isNormal()));652  }653  return {};654}655 656//===----------------------------------------------------------------------===//657// TanOp folder658//===----------------------------------------------------------------------===//659 660OpFoldResult math::TanOp::fold(FoldAdaptor adaptor) {661  return constFoldUnaryOpConditional<FloatAttr>(662      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {663        switch (a.getSizeInBits(a.getSemantics())) {664        case 64:665          return APFloat(tan(a.convertToDouble()));666        case 32:667          return APFloat(tanf(a.convertToFloat()));668        default:669          return {};670        }671      });672}673 674//===----------------------------------------------------------------------===//675// TanhOp folder676//===----------------------------------------------------------------------===//677 678OpFoldResult math::TanhOp::fold(FoldAdaptor adaptor) {679  return constFoldUnaryOpConditional<FloatAttr>(680      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {681        switch (a.getSizeInBits(a.getSemantics())) {682        case 64:683          return APFloat(tanh(a.convertToDouble()));684        case 32:685          return APFloat(tanhf(a.convertToFloat()));686        default:687          return {};688        }689      });690}691 692//===----------------------------------------------------------------------===//693// RoundEvenOp folder694//===----------------------------------------------------------------------===//695 696OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {697  return constFoldUnaryOp<FloatAttr>(698      adaptor.getOperands(), [](const APFloat &a) {699        APFloat result(a);700        result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);701        return result;702      });703}704 705//===----------------------------------------------------------------------===//706// FloorOp folder707//===----------------------------------------------------------------------===//708 709OpFoldResult math::FloorOp::fold(FoldAdaptor adaptor) {710  return constFoldUnaryOp<FloatAttr>(711      adaptor.getOperands(), [](const APFloat &a) {712        APFloat result(a);713        result.roundToIntegral(llvm::RoundingMode::TowardNegative);714        return result;715      });716}717 718//===----------------------------------------------------------------------===//719// RoundOp folder720//===----------------------------------------------------------------------===//721 722OpFoldResult math::RoundOp::fold(FoldAdaptor adaptor) {723  return constFoldUnaryOpConditional<FloatAttr>(724      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {725        switch (a.getSizeInBits(a.getSemantics())) {726        case 64:727          return APFloat(round(a.convertToDouble()));728        case 32:729          return APFloat(roundf(a.convertToFloat()));730        default:731          return {};732        }733      });734}735 736//===----------------------------------------------------------------------===//737// TruncOp folder738//===----------------------------------------------------------------------===//739 740OpFoldResult math::TruncOp::fold(FoldAdaptor adaptor) {741  return constFoldUnaryOpConditional<FloatAttr>(742      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {743        switch (a.getSizeInBits(a.getSemantics())) {744        case 64:745          return APFloat(trunc(a.convertToDouble()));746        case 32:747          return APFloat(truncf(a.convertToFloat()));748        default:749          return {};750        }751      });752}753 754/// Materialize an integer or floating point constant.755Operation *math::MathDialect::materializeConstant(OpBuilder &builder,756                                                  Attribute value, Type type,757                                                  Location loc) {758  if (auto poison = dyn_cast<ub::PoisonAttr>(value))759    return ub::PoisonOp::create(builder, loc, type, poison);760 761  return arith::ConstantOp::materialize(builder, value, type, loc);762}763