30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/Support/MathExtras.h"
46 if (
auto vectorType = dyn_cast<VectorType>(type)) {
47 return VectorShape{vectorType.getShape(), vectorType.getScalableDims()};
62 assert(!isa<VectorType>(type) &&
"must be scalar type");
63 return shape ? VectorType::get(
shape->sizes, type,
shape->scalableFlags)
69 std::optional<VectorShape>
shape) {
70 assert(!isa<VectorType>(value.
getType()) &&
"must be scalar value");
72 return shape ? BroadcastOp::create(builder, type, value) : value;
80 return arith::ConstantOp::create(builder, builder.
getBoolAttr(value));
85 assert((elementType.
isF16() || elementType.
isF32()) &&
86 "x must be f16 or f32 type.");
87 return arith::ConstantOp::create(builder,
92 return arith::ConstantOp::create(builder, builder.
getF32FloatAttr(value));
100 Value i32Value =
i32Cst(builder,
static_cast<int32_t
>(bits));
101 return arith::BitcastOp::create(builder, builder.
getF32Type(), i32Value);
110 return arith::SelectOp::create(
112 arith::CmpFOp::create(builder, arith::CmpFPredicate::ULT, value, bound),
118 return arith::SelectOp::create(
120 arith::CmpFOp::create(builder, arith::CmpFPredicate::UGT, value, bound),
127 return max(builder,
min(builder, value, upperBound), lowerBound);
133 bool isPositive =
false) {
150 Value i32Half = arith::BitcastOp::create(builder, i32, cstHalf);
151 Value i32InvMantMask = arith::BitcastOp::create(builder, i32, cstInvMantMask);
152 Value i32Arg = arith::BitcastOp::create(builder, i32Vec, arg);
155 Value tmp0 = arith::AndIOp::create(builder, i32Arg, bcast(i32InvMantMask));
156 Value tmp1 = arith::OrIOp::create(builder, tmp0, bcast(i32Half));
157 Value normalizedFraction = arith::BitcastOp::create(builder, f32Vec, tmp1);
160 Value arg0 = isPositive ? arg : math::AbsFOp::create(builder, arg);
161 Value biasedExponentBits = arith::ShRUIOp::create(
162 builder, arith::BitcastOp::create(builder, i32Vec, arg0),
163 bcast(
i32Cst(builder, 23)));
164 Value biasedExponent =
165 arith::SIToFPOp::create(builder, f32Vec, biasedExponentBits);
167 arith::SubFOp::create(builder, biasedExponent, bcast(cst126f));
169 return {normalizedFraction, exponent};
183 auto exponetBitLocation = bcast(
i32Cst(builder, 23));
185 auto bias = bcast(
i32Cst(builder, 127));
187 Value biasedArg = arith::AddIOp::create(builder, arg, bias);
189 arith::ShLIOp::create(builder, biasedArg, exponetBitLocation);
190 Value exp2ValueF32 = arith::BitcastOp::create(builder, f32Vec, exp2ValueInt);
199 assert((elementType.
isF32() || elementType.
isF16()) &&
200 "x must be f32 or f16 type");
206 if (coeffs.size() == 1)
209 Value res = math::FmaOp::create(builder, x, coeffs[coeffs.size() - 1],
210 coeffs[coeffs.size() - 2]);
211 for (
auto i = ptrdiff_t(coeffs.size()) - 3; i >= 0; --i) {
212 res = math::FmaOp::create(builder, x, res, coeffs[i]);
240 if (
auto shaped = dyn_cast<ShapedType>(origType)) {
241 newType = shaped.clone(rewriter.
getF32Type());
242 }
else if (isa<FloatType>(origType)) {
246 "unable to find F32 equivalent type");
252 operands.push_back(arith::ExtFOp::create(rewriter, loc,
TypeRange{newType},
254 arith::ExtFOp::Properties{}));
256 cast<T>(op).getProperties(),
271 using OpRewritePattern<T>::OpRewritePattern;
272 LogicalResult matchAndRewrite(T op, PatternRewriter &rewriter)
const final {
274 T::template hasTrait<mlir::OpTrait::SameOperandsAndResultType>(),
275 "requires same operands and result types");
290 LogicalResult matchAndRewrite(math::AtanOp op,
291 PatternRewriter &rewriter)
const final;
296AtanApproximation::matchAndRewrite(math::AtanOp op,
298 auto operand = op.getOperand();
302 std::optional<VectorShape> shape =
vectorShape(op.getOperand());
304 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
305 Value
abs = math::AbsFOp::create(builder, operand);
312 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, abs, twoThirds);
313 Value addone = arith::AddFOp::create(builder, abs, one);
314 Value subone = arith::SubFOp::create(builder, abs, one);
315 Value xnum = arith::SelectOp::create(builder, cmp2, subone, abs);
316 Value xden = arith::SelectOp::create(builder, cmp2, addone, one);
318 auto bcast = [&](Value value) -> Value {
323 auto tan3pio8 = bcast(
f32Cst(builder, 2.41421356237309504880));
325 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, abs, tan3pio8);
326 xnum = arith::SelectOp::create(builder, cmp1, one, xnum);
327 xden = arith::SelectOp::create(builder, cmp1, abs, xden);
329 Value x = arith::DivFOp::create(builder, xnum, xden);
330 Value xx = arith::MulFOp::create(builder, x, x);
334 auto p0 = bcast(
f32Cst(builder, -8.750608600031904122785e-01));
335 auto p1 = bcast(
f32Cst(builder, -1.615753718733365076637e+01));
336 auto p2 = bcast(
f32Cst(builder, -7.500855792314704667340e+01));
337 auto p3 = bcast(
f32Cst(builder, -1.228866684490136173410e+02));
338 auto p4 = bcast(
f32Cst(builder, -6.485021904942025371773e+01));
339 auto q0 = bcast(
f32Cst(builder, +2.485846490142306297962e+01));
340 auto q1 = bcast(
f32Cst(builder, +1.650270098316988542046e+02));
341 auto q2 = bcast(
f32Cst(builder, +4.328810604912902668951e+02));
342 auto q3 = bcast(
f32Cst(builder, +4.853903996359136964868e+02));
343 auto q4 = bcast(
f32Cst(builder, +1.945506571482613964425e+02));
347 n = math::FmaOp::create(builder, xx, n, p1);
348 n = math::FmaOp::create(builder, xx, n, p2);
349 n = math::FmaOp::create(builder, xx, n, p3);
350 n = math::FmaOp::create(builder, xx, n, p4);
351 n = arith::MulFOp::create(builder, n, xx);
355 d = math::FmaOp::create(builder, xx, d, q1);
356 d = math::FmaOp::create(builder, xx, d, q2);
357 d = math::FmaOp::create(builder, xx, d, q3);
358 d = math::FmaOp::create(builder, xx, d, q4);
361 Value ans0 = arith::DivFOp::create(builder, n, d);
362 ans0 = math::FmaOp::create(builder, ans0, x, x);
365 Value mpi4 = bcast(
f32Cst(builder, llvm::numbers::pi / 4));
366 Value ans2 = arith::AddFOp::create(builder, mpi4, ans0);
367 Value ans = arith::SelectOp::create(builder, cmp2, ans2, ans0);
369 Value mpi2 = bcast(
f32Cst(builder, llvm::numbers::pi / 2));
370 Value ans1 = arith::SubFOp::create(builder, mpi2, ans0);
371 ans = arith::SelectOp::create(builder, cmp1, ans1, ans);
383struct Atan2Approximation :
public OpRewritePattern<math::Atan2Op> {
387 LogicalResult matchAndRewrite(math::Atan2Op op,
388 PatternRewriter &rewriter)
const final;
393Atan2Approximation::matchAndRewrite(math::Atan2Op op,
394 PatternRewriter &rewriter)
const {
395 auto y = op.getOperand(0);
396 auto x = op.getOperand(1);
400 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
401 std::optional<VectorShape> shape =
vectorShape(op.getResult());
404 auto div = arith::DivFOp::create(builder, y, x);
405 auto atan = math::AtanOp::create(builder,
div);
410 auto addPi = arith::AddFOp::create(builder, atan, pi);
411 auto subPi = arith::SubFOp::create(builder, atan, pi);
413 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, atan, zero);
414 auto flippedAtan = arith::SelectOp::create(builder, atanGt, subPi, addPi);
417 auto xGt = arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, x, zero);
418 Value
result = arith::SelectOp::create(builder, xGt, atan, flippedAtan);
422 arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ, x, zero);
424 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, y, zero);
425 Value isHalfPi = arith::AndIOp::create(builder, xZero, yGt);
426 auto halfPi =
broadcast(builder,
f32Cst(builder, 1.57079632679f), shape);
427 result = arith::SelectOp::create(builder, isHalfPi, halfPi,
result);
431 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, y, zero);
432 Value isNegativeHalfPiPi = arith::AndIOp::create(builder, xZero, yLt);
433 auto negativeHalfPiPi =
435 result = arith::SelectOp::create(builder, isNegativeHalfPiPi,
436 negativeHalfPiPi,
result);
440 arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ, y, zero);
441 Value isNan = arith::AndIOp::create(builder, xZero, yZero);
443 result = arith::SelectOp::create(builder, isNan, cstNan,
result);
454struct TanhApproximation :
public OpRewritePattern<math::TanhOp> {
458 LogicalResult matchAndRewrite(math::TanhOp op,
459 PatternRewriter &rewriter)
const final;
464TanhApproximation::matchAndRewrite(math::TanhOp op,
465 PatternRewriter &rewriter)
const {
469 std::optional<VectorShape> shape =
vectorShape(op.getOperand());
471 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
472 auto bcast = [&](Value value) -> Value {
477 Value minusClamp = bcast(
f32Cst(builder, -7.99881172180175781f));
478 Value plusClamp = bcast(
f32Cst(builder, 7.99881172180175781f));
479 Value x =
clamp(builder, op.getOperand(), minusClamp, plusClamp);
482 Value tiny = bcast(
f32Cst(builder, 0.0004f));
483 Value tinyMask = arith::CmpFOp::create(
484 builder, arith::CmpFPredicate::OLT,
485 math::AbsFOp::create(builder, op.getOperand()), tiny);
488 Value alpha1 = bcast(
f32Cst(builder, 4.89352455891786e-03f));
489 Value alpha3 = bcast(
f32Cst(builder, 6.37261928875436e-04f));
490 Value alpha5 = bcast(
f32Cst(builder, 1.48572235717979e-05f));
491 Value alpha7 = bcast(
f32Cst(builder, 5.12229709037114e-08f));
492 Value alpha9 = bcast(
f32Cst(builder, -8.60467152213735e-11f));
493 Value alpha11 = bcast(
f32Cst(builder, 2.00018790482477e-13f));
494 Value alpha13 = bcast(
f32Cst(builder, -2.76076847742355e-16f));
497 Value beta0 = bcast(
f32Cst(builder, 4.89352518554385e-03f));
498 Value beta2 = bcast(
f32Cst(builder, 2.26843463243900e-03f));
499 Value beta4 = bcast(
f32Cst(builder, 1.18534705686654e-04f));
500 Value beta6 = bcast(
f32Cst(builder, 1.19825839466702e-06f));
503 Value x2 = arith::MulFOp::create(builder, x, x);
506 Value p = math::FmaOp::create(builder, x2, alpha13, alpha11);
507 p = math::FmaOp::create(builder, x2, p, alpha9);
508 p = math::FmaOp::create(builder, x2, p, alpha7);
509 p = math::FmaOp::create(builder, x2, p, alpha5);
510 p = math::FmaOp::create(builder, x2, p, alpha3);
511 p = math::FmaOp::create(builder, x2, p, alpha1);
512 p = arith::MulFOp::create(builder, x, p);
515 Value q = math::FmaOp::create(builder, x2, beta6, beta4);
516 q = math::FmaOp::create(builder, x2, q, beta2);
517 q = math::FmaOp::create(builder, x2, q, beta0);
520 Value res = arith::SelectOp::create(builder, tinyMask, x,
521 arith::DivFOp::create(builder, p, q));
529 0.693147180559945309417232121458176568075500134360255254120680009493393621L
531 1.442695040888963407359924681001892137426645954152985934135449406931109219L
538template <
typename Op>
550template <
typename Op>
552LogApproximationBase<Op>::logMatchAndRewrite(Op op, PatternRewriter &rewriter,
557 std::optional<VectorShape> shape =
vectorShape(op.getOperand());
559 ImplicitLocOpBuilder builder(op->
getLoc(), rewriter);
560 auto bcast = [&](Value value) -> Value {
564 Value cstZero = bcast(
f32Cst(builder, 0.0f));
565 Value cstOne = bcast(
f32Cst(builder, 1.0f));
566 Value cstNegHalf = bcast(
f32Cst(builder, -0.5f));
569 Value cstMinNormPos = bcast(
f32FromBits(builder, 0x00800000u));
570 Value cstMinusInf = bcast(
f32FromBits(builder, 0xff800000u));
571 Value cstPosInf = bcast(
f32FromBits(builder, 0x7f800000u));
572 Value cstNan = bcast(
f32FromBits(builder, 0x7fc00000));
575 Value cstCephesSQRTHF = bcast(
f32Cst(builder, 0.707106781186547524f));
576 Value cstCephesLogP0 = bcast(
f32Cst(builder, 7.0376836292E-2f));
577 Value cstCephesLogP1 = bcast(
f32Cst(builder, -1.1514610310E-1f));
578 Value cstCephesLogP2 = bcast(
f32Cst(builder, 1.1676998740E-1f));
579 Value cstCephesLogP3 = bcast(
f32Cst(builder, -1.2420140846E-1f));
580 Value cstCephesLogP4 = bcast(
f32Cst(builder, +1.4249322787E-1f));
581 Value cstCephesLogP5 = bcast(
f32Cst(builder, -1.6668057665E-1f));
582 Value cstCephesLogP6 = bcast(
f32Cst(builder, +2.0000714765E-1f));
583 Value cstCephesLogP7 = bcast(
f32Cst(builder, -2.4999993993E-1f));
584 Value cstCephesLogP8 = bcast(
f32Cst(builder, +3.3333331174E-1f));
586 Value x = op.getOperand();
589 x =
max(builder, x, cstMinNormPos);
592 std::pair<Value, Value> pair =
frexp(builder, x,
true);
594 Value e = pair.second;
604 Value mask = arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, x,
606 Value tmp = arith::SelectOp::create(builder, mask, x, cstZero);
608 x = arith::SubFOp::create(builder, x, cstOne);
609 e = arith::SubFOp::create(
610 builder, e, arith::SelectOp::create(builder, mask, cstOne, cstZero));
611 x = arith::AddFOp::create(builder, x, tmp);
613 Value x2 = arith::MulFOp::create(builder, x, x);
614 Value x3 = arith::MulFOp::create(builder, x2, x);
618 y0 = math::FmaOp::create(builder, cstCephesLogP0, x, cstCephesLogP1);
619 y1 = math::FmaOp::create(builder, cstCephesLogP3, x, cstCephesLogP4);
620 y2 = math::FmaOp::create(builder, cstCephesLogP6, x, cstCephesLogP7);
621 y0 = math::FmaOp::create(builder, y0, x, cstCephesLogP2);
622 y1 = math::FmaOp::create(builder, y1, x, cstCephesLogP5);
623 y2 = math::FmaOp::create(builder, y2, x, cstCephesLogP8);
624 y0 = math::FmaOp::create(builder, y0, x3, y1);
625 y0 = math::FmaOp::create(builder, y0, x3, y2);
626 y0 = arith::MulFOp::create(builder, y0, x3);
628 y0 = math::FmaOp::create(builder, cstNegHalf, x2, y0);
629 x = arith::AddFOp::create(builder, x, y0);
633 x = math::FmaOp::create(builder, x, cstLog2e, e);
636 x = math::FmaOp::create(builder, e, cstLn2, x);
639 Value invalidMask = arith::CmpFOp::create(builder, arith::CmpFPredicate::ULT,
640 op.getOperand(), cstZero);
641 Value zeroMask = arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ,
642 op.getOperand(), cstZero);
643 Value posInfMask = arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ,
644 op.getOperand(), cstPosInf);
650 Value aproximation = arith::SelectOp::create(
651 builder, zeroMask, cstMinusInf,
652 arith::SelectOp::create(
653 builder, invalidMask, cstNan,
654 arith::SelectOp::create(builder, posInfMask, cstPosInf, x)));
662struct LogApproximation :
public LogApproximationBase<math::LogOp> {
663 using LogApproximationBase::LogApproximationBase;
665 LogicalResult matchAndRewrite(math::LogOp op,
666 PatternRewriter &rewriter)
const final {
667 return logMatchAndRewrite(op, rewriter,
false);
673struct Log2Approximation :
public LogApproximationBase<math::Log2Op> {
674 using LogApproximationBase::LogApproximationBase;
676 LogicalResult matchAndRewrite(math::Log2Op op,
677 PatternRewriter &rewriter)
const final {
678 return logMatchAndRewrite(op, rewriter,
true);
688struct Log1pApproximation :
public OpRewritePattern<math::Log1pOp> {
692 LogicalResult matchAndRewrite(math::Log1pOp op,
693 PatternRewriter &rewriter)
const final;
699Log1pApproximation::matchAndRewrite(math::Log1pOp op,
700 PatternRewriter &rewriter)
const {
704 std::optional<VectorShape> shape =
vectorShape(op.getOperand());
706 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
707 auto bcast = [&](Value value) -> Value {
717 Value cstOne = bcast(
f32Cst(builder, 1.0f));
718 Value x = op.getOperand();
719 Value u = arith::AddFOp::create(builder, x, cstOne);
721 arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ, u, cstOne);
722 Value logU = math::LogOp::create(builder, u);
724 arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ, u, logU);
725 Value logLarge = arith::MulFOp::create(
727 arith::DivFOp::create(builder, logU,
728 arith::SubFOp::create(builder, u, cstOne)));
729 Value approximation = arith::SelectOp::create(
730 builder, arith::OrIOp::create(builder, uSmall, uInf), x, logLarge);
743struct AsinPolynomialApproximation :
public OpRewritePattern<math::AsinOp> {
747 LogicalResult matchAndRewrite(math::AsinOp op,
748 PatternRewriter &rewriter)
const final;
752AsinPolynomialApproximation::matchAndRewrite(math::AsinOp op,
753 PatternRewriter &rewriter)
const {
754 Value operand = op.getOperand();
757 if (!(elementType.
isF32() || elementType.
isF16()))
759 "only f32 and f16 type is supported.");
760 std::optional<VectorShape> shape =
vectorShape(operand);
762 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
763 auto bcast = [&](Value value) -> Value {
767 auto fma = [&](Value a, Value
b, Value c) -> Value {
768 return math::FmaOp::create(builder, a,
b, c);
771 auto mul = [&](Value a, Value
b) -> Value {
772 return arith::MulFOp::create(builder, a,
b);
775 auto sub = [&](Value a, Value
b) -> Value {
776 return arith::SubFOp::create(builder, a,
b);
779 auto abs = [&](Value a) -> Value {
return math::AbsFOp::create(builder, a); };
781 auto sqrt = [&](Value a) -> Value {
782 return math::SqrtOp::create(builder, a);
785 auto scopy = [&](Value a, Value
b) -> Value {
786 return math::CopySignOp::create(builder, a,
b);
789 auto sel = [&](Value a, Value
b, Value c) -> Value {
790 return arith::SelectOp::create(builder, a,
b, c);
793 Value abso =
abs(operand);
794 Value aa =
mul(operand, operand);
795 Value opp = sqrt(sub(bcast(
floatCst(builder, 1.0, elementType)), aa));
797 Value gt = arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, aa,
798 bcast(
floatCst(builder, 0.5, elementType)));
800 Value x = sel(gt, opp, abso);
805 Value r = bcast(
floatCst(builder, 5.5579749017470502e-2, elementType));
806 Value t = bcast(
floatCst(builder, -6.2027913464120114e-2, elementType));
808 r = fma(r, q, bcast(
floatCst(builder, 5.4224464349245036e-2, elementType)));
809 t = fma(t, q, bcast(
floatCst(builder, -1.1326992890324464e-2, elementType)));
810 r = fma(r, q, bcast(
floatCst(builder, 1.5268872539397656e-2, elementType)));
811 t = fma(t, q, bcast(
floatCst(builder, 1.0493798473372081e-2, elementType)));
812 r = fma(r, q, bcast(
floatCst(builder, 1.4106045900607047e-2, elementType)));
813 t = fma(t, q, bcast(
floatCst(builder, 1.7339776384962050e-2, elementType)));
814 r = fma(r, q, bcast(
floatCst(builder, 2.2372961589651054e-2, elementType)));
815 t = fma(t, q, bcast(
floatCst(builder, 3.0381912707941005e-2, elementType)));
816 r = fma(r, q, bcast(
floatCst(builder, 4.4642857881094775e-2, elementType)));
817 t = fma(t, q, bcast(
floatCst(builder, 7.4999999991367292e-2, elementType)));
819 r = fma(r, s, bcast(
floatCst(builder, 1.6666666666670193e-1, elementType)));
823 Value rsub = sub(bcast(
floatCst(builder, 1.57079632679, elementType)), r);
824 r = sel(gt, rsub, r);
825 r = scopy(r, operand);
839struct AcosPolynomialApproximation :
public OpRewritePattern<math::AcosOp> {
843 LogicalResult matchAndRewrite(math::AcosOp op,
844 PatternRewriter &rewriter)
const final;
848AcosPolynomialApproximation::matchAndRewrite(math::AcosOp op,
849 PatternRewriter &rewriter)
const {
850 Value operand = op.getOperand();
853 if (!(elementType.
isF32() || elementType.
isF16()))
855 "only f32 and f16 type is supported.");
856 std::optional<VectorShape> shape =
vectorShape(operand);
858 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
859 auto bcast = [&](Value value) -> Value {
863 auto fma = [&](Value a, Value
b, Value c) -> Value {
864 return math::FmaOp::create(builder, a,
b, c);
867 auto mul = [&](Value a, Value
b) -> Value {
868 return arith::MulFOp::create(builder, a,
b);
871 Value negOperand = arith::NegFOp::create(builder, operand);
872 Value zero = bcast(
floatCst(builder, 0.0, elementType));
873 Value half = bcast(
floatCst(builder, 0.5, elementType));
874 Value negOne = bcast(
floatCst(builder, -1.0, elementType));
876 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, operand, zero);
877 Value r = arith::SelectOp::create(builder, selR, negOperand, operand);
878 Value chkConst = bcast(
floatCst(builder, -0.5625, elementType));
880 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, r, chkConst);
883 fma(bcast(
floatCst(builder, 9.3282184640716537e-1, elementType)),
884 bcast(
floatCst(builder, 1.6839188885261840e+0, elementType)),
885 math::AsinOp::create(builder, r));
887 Value falseVal = math::SqrtOp::create(builder, fma(half, r, half));
888 falseVal = math::AsinOp::create(builder, falseVal);
889 falseVal =
mul(bcast(
floatCst(builder, 2.0, elementType)), falseVal);
891 r = arith::SelectOp::create(builder, firstPred, trueVal, falseVal);
894 Value greaterThanNegOne = arith::CmpFOp::create(
895 builder, arith::CmpFPredicate::OGE, operand, negOne);
898 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, operand, zero);
900 Value betweenNegOneZero =
901 arith::AndIOp::create(builder, greaterThanNegOne, lessThanZero);
903 trueVal = fma(bcast(
floatCst(builder, 1.8656436928143307e+0, elementType)),
904 bcast(
floatCst(builder, 1.6839188885261840e+0, elementType)),
905 arith::NegFOp::create(builder, r));
908 arith::SelectOp::create(builder, betweenNegOneZero, trueVal, r);
928 Value operand = op.getOperand();
931 if (!(elementType.
isF32() || elementType.
isF16()))
933 "only f32 and f16 type is supported.");
941 const int intervalsCount = 3;
942 const int polyDegree = 4;
946 Value pp[intervalsCount][polyDegree + 1];
947 pp[0][0] = bcast(
floatCst(builder, +0.00000000000000000e+00f, elementType));
948 pp[0][1] = bcast(
floatCst(builder, +1.12837916222975858e+00f, elementType));
949 pp[0][2] = bcast(
floatCst(builder, -5.23018562988006470e-01f, elementType));
950 pp[0][3] = bcast(
floatCst(builder, +2.09741709609267072e-01f, elementType));
951 pp[0][4] = bcast(
floatCst(builder, +2.58146801602987875e-02f, elementType));
952 pp[1][0] = bcast(
floatCst(builder, +0.00000000000000000e+00f, elementType));
953 pp[1][1] = bcast(
floatCst(builder, +1.12750687816789140e+00f, elementType));
954 pp[1][2] = bcast(
floatCst(builder, -3.64721408487825775e-01f, elementType));
955 pp[1][3] = bcast(
floatCst(builder, +1.18407396425136952e-01f, elementType));
956 pp[1][4] = bcast(
floatCst(builder, +3.70645533056476558e-02f, elementType));
957 pp[2][0] = bcast(
floatCst(builder, -3.30093071049483172e-03f, elementType));
958 pp[2][1] = bcast(
floatCst(builder, +3.51961938357697011e-03f, elementType));
959 pp[2][2] = bcast(
floatCst(builder, -1.41373622814988039e-03f, elementType));
960 pp[2][3] = bcast(
floatCst(builder, +2.53447094961941348e-04f, elementType));
961 pp[2][4] = bcast(
floatCst(builder, -1.71048029455037401e-05f, elementType));
963 Value qq[intervalsCount][polyDegree + 1];
964 qq[0][0] = bcast(
floatCst(builder, +1.000000000000000000e+00f, elementType));
965 qq[0][1] = bcast(
floatCst(builder, -4.635138185962547255e-01f, elementType));
966 qq[0][2] = bcast(
floatCst(builder, +5.192301327279782447e-01f, elementType));
967 qq[0][3] = bcast(
floatCst(builder, -1.318089722204810087e-01f, elementType));
968 qq[0][4] = bcast(
floatCst(builder, +7.397964654672315005e-02f, elementType));
969 qq[1][0] = bcast(
floatCst(builder, +1.00000000000000000e+00f, elementType));
970 qq[1][1] = bcast(
floatCst(builder, -3.27607011824493086e-01f, elementType));
971 qq[1][2] = bcast(
floatCst(builder, +4.48369090658821977e-01f, elementType));
972 qq[1][3] = bcast(
floatCst(builder, -8.83462621207857930e-02f, elementType));
973 qq[1][4] = bcast(
floatCst(builder, +5.72442770283176093e-02f, elementType));
974 qq[2][0] = bcast(
floatCst(builder, +1.00000000000000000e+00f, elementType));
975 qq[2][1] = bcast(
floatCst(builder, -2.06069165953913769e+00f, elementType));
976 qq[2][2] = bcast(
floatCst(builder, +1.62705939945477759e+00f, elementType));
977 qq[2][3] = bcast(
floatCst(builder, -5.83389859211130017e-01f, elementType));
978 qq[2][4] = bcast(
floatCst(builder, +8.21908939856640930e-02f, elementType));
980 Value offsets[intervalsCount];
981 offsets[0] = bcast(
floatCst(builder, 0.0f, elementType));
982 offsets[1] = bcast(
floatCst(builder, 0.0f, elementType));
983 offsets[2] = bcast(
floatCst(builder, 1.0f, elementType));
985 Value bounds[intervalsCount];
986 bounds[0] = bcast(
floatCst(builder, 0.8f, elementType));
987 bounds[1] = bcast(
floatCst(builder, 2.0f, elementType));
988 bounds[2] = bcast(
floatCst(builder, 3.75f, elementType));
990 Value isNegativeArg =
991 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, operand, zero);
992 Value negArg = arith::NegFOp::create(builder, operand);
993 Value x = arith::SelectOp::create(builder, isNegativeArg, negArg, operand);
995 Value offset = offsets[0];
996 Value p[polyDegree + 1];
997 Value q[polyDegree + 1];
998 for (
int i = 0; i <= polyDegree; ++i) {
1004 Value isLessThanBound[intervalsCount];
1005 for (
int j = 0;
j < intervalsCount - 1; ++
j) {
1006 isLessThanBound[
j] =
1007 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, x, bounds[
j]);
1008 for (
int i = 0; i <= polyDegree; ++i) {
1009 p[i] = arith::SelectOp::create(builder, isLessThanBound[
j], p[i],
1011 q[i] = arith::SelectOp::create(builder, isLessThanBound[
j], q[i],
1014 offset = arith::SelectOp::create(builder, isLessThanBound[
j], offset,
1017 isLessThanBound[intervalsCount - 1] = arith::CmpFOp::create(
1018 builder, arith::CmpFPredicate::ULT, x, bounds[intervalsCount - 1]);
1020 Value pPoly = makePolynomialCalculation(builder, p, x);
1021 Value qPoly = makePolynomialCalculation(builder, q, x);
1022 Value rationalPoly = arith::DivFOp::create(builder, pPoly, qPoly);
1023 Value formula = arith::AddFOp::create(builder, offset, rationalPoly);
1024 formula = arith::SelectOp::create(
1025 builder, isLessThanBound[intervalsCount - 1], formula, one);
1028 Value negFormula = arith::NegFOp::create(builder, formula);
1030 arith::SelectOp::create(builder, isNegativeArg, negFormula, formula);
1049 Value x = op.getOperand();
1071 Value a = math::AbsFOp::create(builder, x);
1072 Value p = arith::AddFOp::create(builder, a, pos2);
1073 Value r = arith::DivFOp::create(builder, one, p);
1074 Value q = math::FmaOp::create(builder, neg4, r, one);
1075 Value t = math::FmaOp::create(builder, arith::AddFOp::create(builder, q, one),
1078 math::FmaOp::create(builder, arith::NegFOp::create(builder, a), q, t);
1079 q = math::FmaOp::create(builder, r, e, q);
1081 p = bcast(
floatCst(builder, -0x1.a4a000p-12f, et));
1083 p = math::FmaOp::create(builder, p, q, c1);
1085 p = math::FmaOp::create(builder, p, q, c2);
1087 p = math::FmaOp::create(builder, p, q, c3);
1089 p = math::FmaOp::create(builder, p, q, c4);
1091 p = math::FmaOp::create(builder, p, q, c5);
1093 p = math::FmaOp::create(builder, p, q, c6);
1095 p = math::FmaOp::create(builder, p, q, c7);
1097 p = math::FmaOp::create(builder, p, q, c8);
1099 p = math::FmaOp::create(builder, p, q, c9);
1101 Value d = math::FmaOp::create(builder, pos2, a, one);
1102 r = arith::DivFOp::create(builder, one, d);
1103 q = math::FmaOp::create(builder, p, r, r);
1104 Value negfa = arith::NegFOp::create(builder, a);
1105 Value fmaqah = math::FmaOp::create(builder, q, negfa, onehalf);
1106 Value psubq = arith::SubFOp::create(builder, p, q);
1107 e = math::FmaOp::create(builder, fmaqah, pos2, psubq);
1108 r = math::FmaOp::create(builder, e, r, q);
1110 Value s = arith::MulFOp::create(builder, a, a);
1111 e = math::ExpOp::create(builder, arith::NegFOp::create(builder, s));
1113 t = math::FmaOp::create(builder, arith::NegFOp::create(builder, a), a, s);
1114 r = math::FmaOp::create(
1116 arith::MulFOp::create(builder, arith::MulFOp::create(builder, r, e), t));
1118 Value isNotLessThanInf = arith::XOrIOp::create(
1120 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, a, posInf),
1122 r = arith::SelectOp::create(builder, isNotLessThanInf,
1123 arith::AddFOp::create(builder, x, x), r);
1124 Value isGreaterThanClamp =
1125 arith::CmpFOp::create(builder, arith::CmpFPredicate::OGT, a, clampVal);
1126 r = arith::SelectOp::create(builder, isGreaterThanClamp, zero, r);
1129 arith::CmpFOp::create(builder, arith::CmpFPredicate::OLT, x, zero);
1130 r = arith::SelectOp::create(builder, isNegative,
1131 arith::SubFOp::create(builder, pos2, r), r);
1143 const std::optional<VectorShape>
shape,
Value value,
1144 float lowerBound,
float upperBound) {
1145 assert(!std::isnan(lowerBound));
1146 assert(!std::isnan(upperBound));
1152 auto selectCmp = [&builder](
auto pred,
Value value,
Value bound) {
1153 return arith::SelectOp::create(
1154 builder, arith::CmpFOp::create(builder, pred, value, bound), value,
1161 value = selectCmp(arith::CmpFPredicate::UGE, value,
1162 bcast(
f32Cst(builder, lowerBound)));
1163 value = selectCmp(arith::CmpFPredicate::ULE, value,
1164 bcast(
f32Cst(builder, upperBound)));
1168struct ExpApproximation :
public OpRewritePattern<math::ExpOp> {
1172 LogicalResult matchAndRewrite(math::ExpOp op,
1173 PatternRewriter &rewriter)
const final;
1177ExpApproximation::matchAndRewrite(math::ExpOp op,
1178 PatternRewriter &rewriter)
const {
1179 auto shape =
vectorShape(op.getOperand().getType());
1181 if (!elementTy.isF32())
1184 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
1186 auto add = [&](Value a, Value
b) -> Value {
1187 return arith::AddFOp::create(builder, a,
b);
1189 auto bcast = [&](Value value) -> Value {
1190 return broadcast(builder, value, shape);
1192 auto floor = [&](Value a) {
return math::FloorOp::create(builder, a); };
1193 auto fmla = [&](Value a, Value
b, Value c) {
1194 return math::FmaOp::create(builder, a,
b, c);
1196 auto mul = [&](Value a, Value
b) -> Value {
1197 return arith::MulFOp::create(builder, a,
b);
1221 Value cstHalf = bcast(
f32Cst(builder, 0.5f));
1222 Value cstOne = bcast(
f32Cst(builder, 1.0f));
1225 Value cstLog2ef = bcast(
f32Cst(builder, 1.44269504088896341f));
1227 Value cstExpC1 = bcast(
f32Cst(builder, -0.693359375f));
1228 Value cstExpC2 = bcast(
f32Cst(builder, 2.12194440e-4f));
1229 Value cstExpP0 = bcast(
f32Cst(builder, 1.9875691500E-4f));
1230 Value cstExpP1 = bcast(
f32Cst(builder, 1.3981999507E-3f));
1231 Value cstExpP2 = bcast(
f32Cst(builder, 8.3334519073E-3f));
1232 Value cstExpP3 = bcast(
f32Cst(builder, 4.1665795894E-2f));
1233 Value cstExpP4 = bcast(
f32Cst(builder, 1.6666665459E-1f));
1234 Value cstExpP5 = bcast(
f32Cst(builder, 5.0000001201E-1f));
1241 Value x = op.getOperand();
1242 x = clampWithNormals(builder, shape, x, -87.8f, 88.8f);
1243 Value n =
floor(fmla(x, cstLog2ef, cstHalf));
1284 n = clampWithNormals(builder, shape, n, -127.0f, 127.0f);
1287 x = fmla(cstExpC1, n, x);
1288 x = fmla(cstExpC2, n, x);
1291 Value z = fmla(x, cstExpP0, cstExpP1);
1292 z = fmla(z, x, cstExpP2);
1293 z = fmla(z, x, cstExpP3);
1294 z = fmla(z, x, cstExpP4);
1295 z = fmla(z, x, cstExpP5);
1296 z = fmla(z,
mul(x, x), x);
1301 Value nI32 = arith::FPToSIOp::create(builder, i32Vec, n);
1304 Value pow2 =
exp2I32(builder, nI32);
1307 Value ret =
mul(z, pow2);
1310 return mlir::success();
1321struct ExpM1Approximation :
public OpRewritePattern<math::ExpM1Op> {
1325 LogicalResult matchAndRewrite(math::ExpM1Op op,
1326 PatternRewriter &rewriter)
const final;
1331ExpM1Approximation::matchAndRewrite(math::ExpM1Op op,
1332 PatternRewriter &rewriter)
const {
1336 std::optional<VectorShape> shape =
vectorShape(op.getOperand());
1338 ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
1339 auto bcast = [&](Value value) -> Value {
1340 return broadcast(builder, value, shape);
1346 Value cstOne = bcast(
f32Cst(builder, 1.0f));
1347 Value cstNegOne = bcast(
f32Cst(builder, -1.0f));
1348 Value x = op.getOperand();
1349 Value u = math::ExpOp::create(builder, x);
1351 arith::CmpFOp::create(builder, arith::CmpFPredicate::UEQ, u, cstOne);
1352 Value uMinusOne = arith::SubFOp::create(builder, u, cstOne);
1353 Value uMinusOneEqNegOne = arith::CmpFOp::create(
1354 builder, arith::CmpFPredicate::OEQ, uMinusOne, cstNegOne);
1356 Value logU = math::LogOp::create(builder, u);
1360 arith::CmpFOp::create(builder, arith::CmpFPredicate::OEQ, logU, u);
1363 Value expm1 = arith::MulFOp::create(builder, uMinusOne,
1364 arith::DivFOp::create(builder, x, logU));
1365 expm1 = arith::SelectOp::create(builder, isInf, u, expm1);
1366 Value approximation = arith::SelectOp::create(
1367 builder, uEqOneOrNaN, x,
1368 arith::SelectOp::create(builder, uMinusOneEqNegOne, cstNegOne, expm1));
1379template <
bool isSine,
typename OpTy>
1380struct SinAndCosApproximation :
public OpRewritePattern<OpTy> {
1382 using OpRewritePattern<OpTy>::OpRewritePattern;
1384 LogicalResult matchAndRewrite(OpTy op, PatternRewriter &rewriter)
const final;
1388#define TWO_OVER_PI \
1389 0.6366197723675813430755350534900574481378385829618257949906693762L
1391 1.5707963267948966192313216916397514420985846996875529104874722961L
1396template <
bool isSine,
typename OpTy>
1397LogicalResult SinAndCosApproximation<isSine, OpTy>::matchAndRewrite(
1400 llvm::is_one_of<OpTy, math::SinOp, math::CosOp>::value,
1401 "SinAndCosApproximation pattern expects math::SinOp or math::CosOp");
1413 return arith::MulFOp::create(builder, a,
b);
1416 return arith::SubFOp::create(builder, a,
b);
1418 auto floor = [&](
Value a) {
return math::FloorOp::create(builder, a); };
1421 auto fPToSingedInteger = [&](
Value a) ->
Value {
1422 return arith::FPToSIOp::create(builder, i32Vec, a);
1426 return arith::AndIOp::create(builder, a, bcast(
i32Cst(builder, 3)));
1430 return arith::CmpIOp::create(builder, arith::CmpIPredicate::eq, a,
b);
1434 return arith::CmpIOp::create(builder, arith::CmpIPredicate::sgt, a,
b);
1438 return arith::SelectOp::create(builder, cond, t, f);
1442 return math::FmaOp::create(builder, a,
b, c);
1446 return arith::OrIOp::create(builder, a,
b);
1452 Value x = op.getOperand();
1454 Value k = floor(
mul(x, twoOverPi));
1456 Value y = sub(x,
mul(k, piOverTwo));
1459 Value cstNegativeOne = bcast(
f32Cst(builder, -1.0));
1461 Value cstSC2 = bcast(
f32Cst(builder, -0.16666667163372039794921875f));
1462 Value cstSC4 = bcast(
f32Cst(builder, 8.333347737789154052734375e-3f));
1463 Value cstSC6 = bcast(
f32Cst(builder, -1.9842604524455964565277099609375e-4f));
1465 bcast(
f32Cst(builder, 2.760012648650445044040679931640625e-6f));
1467 bcast(
f32Cst(builder, -2.50293279435709337121807038784027099609375e-8f));
1470 Value cstCC4 = bcast(
f32Cst(builder, 4.166664183139801025390625e-2f));
1471 Value cstCC6 = bcast(
f32Cst(builder, -1.388833043165504932403564453125e-3f));
1472 Value cstCC8 = bcast(
f32Cst(builder, 2.47562347794882953166961669921875e-5f));
1474 bcast(
f32Cst(builder, -2.59630184018533327616751194000244140625e-7f));
1476 Value kMod4 = modulo4(fPToSingedInteger(k));
1478 Value kR0 = isEqualTo(kMod4, bcast(
i32Cst(builder, 0)));
1479 Value kR1 = isEqualTo(kMod4, bcast(
i32Cst(builder, 1)));
1480 Value kR2 = isEqualTo(kMod4, bcast(
i32Cst(builder, 2)));
1481 Value kR3 = isEqualTo(kMod4, bcast(
i32Cst(builder, 3)));
1483 Value sinuseCos = isSine ? bitwiseOr(kR1, kR3) : bitwiseOr(kR0, kR2);
1484 Value negativeRange = isSine ? isGreaterThan(kMod4, bcast(
i32Cst(builder, 1)))
1485 : bitwiseOr(kR1, kR2);
1489 Value base = select(sinuseCos, cstOne, y);
1490 Value cstC2 = select(sinuseCos, cstCC2, cstSC2);
1491 Value cstC4 = select(sinuseCos, cstCC4, cstSC4);
1492 Value cstC6 = select(sinuseCos, cstCC6, cstSC6);
1493 Value cstC8 = select(sinuseCos, cstCC8, cstSC8);
1494 Value cstC10 = select(sinuseCos, cstCC10, cstSC10);
1496 Value v1 = fmla(y2, cstC10, cstC8);
1497 Value v2 = fmla(y2, v1, cstC6);
1498 Value v3 = fmla(y2, v2, cstC4);
1499 Value v4 = fmla(y2, v3, cstC2);
1500 Value v5 = fmla(y2, v4, cstOne);
1503 Value approximation = select(negativeRange,
mul(cstNegativeOne, v6), v6);
1515struct CbrtApproximation :
public OpRewritePattern<math::CbrtOp> {
1518 LogicalResult matchAndRewrite(math::CbrtOp op,
1519 PatternRewriter &rewriter)
const final;
1526CbrtApproximation::matchAndRewrite(math::CbrtOp op,
1527 PatternRewriter &rewriter)
const {
1528 auto operand = op.getOperand();
1532 ImplicitLocOpBuilder
b(op->getLoc(), rewriter);
1533 std::optional<VectorShape> shape =
vectorShape(operand);
1542 auto bconst = [&](TypedAttr attr) -> Value {
1543 Value value = arith::ConstantOp::create(
b, attr);
1548 Value intTwo = bconst(
b.getI32IntegerAttr(2));
1549 Value intFour = bconst(
b.getI32IntegerAttr(4));
1550 Value intEight = bconst(
b.getI32IntegerAttr(8));
1551 Value intMagic = bconst(
b.getI32IntegerAttr(0x2a5137a0));
1552 Value fpThird = bconst(
b.getF32FloatAttr(0.33333333f));
1553 Value fpTwo = bconst(
b.getF32FloatAttr(2.0f));
1554 Value fpZero = bconst(
b.getF32FloatAttr(0.0f));
1560 Value absValue = math::AbsFOp::create(
b, operand);
1561 Value intValue = arith::BitcastOp::create(
b, intTy, absValue);
1562 Value divideBy4 = arith::ShRSIOp::create(
b, intValue, intTwo);
1563 Value divideBy16 = arith::ShRSIOp::create(
b, intValue, intFour);
1564 intValue = arith::AddIOp::create(
b, divideBy4, divideBy16);
1567 divideBy16 = arith::ShRSIOp::create(
b, intValue, intFour);
1568 intValue = arith::AddIOp::create(
b, intValue, divideBy16);
1571 Value divideBy256 = arith::ShRSIOp::create(
b, intValue, intEight);
1572 intValue = arith::AddIOp::create(
b, intValue, divideBy256);
1575 intValue = arith::AddIOp::create(
b, intValue, intMagic);
1579 Value floatValue = arith::BitcastOp::create(
b, floatTy, intValue);
1580 Value squared = arith::MulFOp::create(
b, floatValue, floatValue);
1581 Value mulTwo = arith::MulFOp::create(
b, floatValue, fpTwo);
1582 Value divSquared = arith::DivFOp::create(
b, absValue, squared);
1583 floatValue = arith::AddFOp::create(
b, mulTwo, divSquared);
1584 floatValue = arith::MulFOp::create(
b, floatValue, fpThird);
1587 squared = arith::MulFOp::create(
b, floatValue, floatValue);
1588 mulTwo = arith::MulFOp::create(
b, floatValue, fpTwo);
1589 divSquared = arith::DivFOp::create(
b, absValue, squared);
1590 floatValue = arith::AddFOp::create(
b, mulTwo, divSquared);
1591 floatValue = arith::MulFOp::create(
b, floatValue, fpThird);
1595 arith::CmpFOp::create(
b, arith::CmpFPredicate::OEQ, absValue, fpZero);
1596 floatValue = arith::SelectOp::create(
b, isZero, fpZero, floatValue);
1597 floatValue = math::CopySignOp::create(
b, floatValue, operand);
1620template <
typename OpType>
1625 if (predicate(OpType::getOperationName())) {
1626 patterns.
add<ReuseF32Expansion<OpType>>(patterns.
getContext(), benefit);
1661template <
typename OpType,
typename PatternType>
1665 if (predicate(OpType::getOperationName())) {
1674 AcosPolynomialApproximation>(
1675 patterns, predicate, benefit);
1677 AsinPolynomialApproximation>(
1678 patterns, predicate, benefit);
1680 patterns, predicate, benefit);
1682 patterns, predicate, benefit);
1684 patterns, predicate, benefit);
1686 CosOp, SinAndCosApproximation<false, math::CosOp>>(patterns, predicate,
1689 patterns, predicate, benefit);
1692 patterns, predicate, benefit);
1694 patterns, predicate, benefit);
1696 patterns, predicate, benefit);
1698 patterns, predicate, benefit);
1700 patterns, predicate, benefit);
1702 patterns, predicate, benefit);
1704 SinOp, SinAndCosApproximation<true, math::SinOp>>(patterns, predicate,
1707 patterns, predicate, benefit);
1713 return llvm::is_contained(
1714 {math::AtanOp::getOperationName(), math::Atan2Op::getOperationName(),
1715 math::TanhOp::getOperationName(), math::LogOp::getOperationName(),
1716 math::Log2Op::getOperationName(), math::Log1pOp::getOperationName(),
1717 math::ErfOp::getOperationName(), math::ErfcOp::getOperationName(),
1718 math::ExpOp::getOperationName(), math::ExpM1Op::getOperationName(),
1719 math::CbrtOp::getOperationName(), math::SinOp::getOperationName(),
1720 math::CosOp::getOperationName()},
1725 patterns, [](StringRef name) ->
bool {
1726 return llvm::is_contained(
1727 {math::AtanOp::getOperationName(),
1728 math::Atan2Op::getOperationName(),
1729 math::TanhOp::getOperationName(), math::LogOp::getOperationName(),
1730 math::Log2Op::getOperationName(),
1731 math::Log1pOp::getOperationName(), math::ErfOp::getOperationName(),
1732 math::ErfcOp::getOperationName(), math::AsinOp::getOperationName(),
1733 math::AcosOp::getOperationName(), math::ExpOp::getOperationName(),
1734 math::ExpM1Op::getOperationName(),
1735 math::CbrtOp::getOperationName(), math::SinOp::getOperationName(),
1736 math::CosOp::getOperationName()},
static Value exp2I32(ImplicitLocOpBuilder &builder, Value arg)
static void populateMathF32ExpansionPattern(RewritePatternSet &patterns, llvm::function_ref< bool(StringRef)> predicate, PatternBenefit benefit)
static Value boolCst(ImplicitLocOpBuilder &builder, bool value)
static Value floatCst(ImplicitLocOpBuilder &builder, float value, Type elementType)
LogicalResult insertCasts(Operation *op, PatternRewriter &rewriter)
static Value clamp(ImplicitLocOpBuilder &builder, Value value, Value lowerBound, Value upperBound)
static std::pair< Value, Value > frexp(ImplicitLocOpBuilder &builder, Value arg, bool isPositive=false)
static std::optional< VectorShape > vectorShape(Type type)
static Value i32Cst(ImplicitLocOpBuilder &builder, int32_t value)
static Type broadcast(Type type, std::optional< VectorShape > shape)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value f32FromBits(ImplicitLocOpBuilder &builder, uint32_t bits)
static Value f32Cst(ImplicitLocOpBuilder &builder, double value)
static void populateMathPolynomialApproximationPattern(RewritePatternSet &patterns, llvm::function_ref< bool(StringRef)> predicate, PatternBenefit benefit)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value broadcast(Location loc, Value toBroadcast, unsigned numElements, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter)
Broadcasts the value to vector with numElements number of elements.
IntegerAttr getI32IntegerAttr(int32_t value)
FloatAttr getFloatAttr(Type type, double value)
IntegerType getIntegerType(unsigned width)
BoolAttr getBoolAttr(bool value)
FloatAttr getF32FloatAttr(float value)
ImplicitLocOpBuilder maintains a 'current location', allowing use of the create<> method without spec...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Location getLoc()
The source location the operation was defined or derived from.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
operand_type_range getOperandTypes()
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
Type front()
Return first type in the range.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
DynamicAPInt floor(const Fraction &f)
Fraction abs(const Fraction &f)
Include the generated interface declarations.
void populatePolynomialApproximateErfcPattern(RewritePatternSet &patterns)
void populateMathF32ExpansionPatterns(RewritePatternSet &patterns, llvm::function_ref< bool(StringRef)> predicate, PatternBenefit=1)
void populatePolynomialApproximateErfPattern(RewritePatternSet &patterns)
void populatePolynomialApproximateTanhPattern(RewritePatternSet &patterns)
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
void populateMathPolynomialApproximationPatterns(RewritePatternSet &patterns, llvm::function_ref< bool(StringRef)> predicate, PatternBenefit=1)
ArrayRef< int64_t > sizes
ArrayRef< bool > scalableFlags
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
LogicalResult matchAndRewrite(math::ErfOp op, PatternRewriter &rewriter) const final
LogicalResult matchAndRewrite(math::ErfcOp op, PatternRewriter &rewriter) const final
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.