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);
38#include "mlir/Dialect/Math/IR/MathOps.cpp.inc"
46 [](
const APFloat &a) { return abs(a); });
55 [](
const APInt &a) { return a.abs(); });
64 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
65 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
66 case APFloat::Semantics::S_IEEEdouble:
67 return APFloat(acos(a.convertToDouble()));
68 case APFloat::Semantics::S_IEEEsingle:
69 return APFloat(acosf(a.convertToFloat()));
82 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
83 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
84 case APFloat::Semantics::S_IEEEdouble:
85 return APFloat(acosh(a.convertToDouble()));
86 case APFloat::Semantics::S_IEEEsingle:
87 return APFloat(acoshf(a.convertToFloat()));
100 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
101 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
102 case APFloat::Semantics::S_IEEEdouble:
103 return APFloat(asin(a.convertToDouble()));
104 case APFloat::Semantics::S_IEEEsingle:
105 return APFloat(asinf(a.convertToFloat()));
118 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
119 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
120 case APFloat::Semantics::S_IEEEdouble:
121 return APFloat(asinh(a.convertToDouble()));
122 case APFloat::Semantics::S_IEEEsingle:
123 return APFloat(asinhf(a.convertToFloat()));
136 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
137 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
138 case APFloat::Semantics::S_IEEEdouble:
139 return APFloat(atan(a.convertToDouble()));
140 case APFloat::Semantics::S_IEEEsingle:
141 return APFloat(atanf(a.convertToFloat()));
154 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
155 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
156 case APFloat::Semantics::S_IEEEdouble:
157 return APFloat(atanh(a.convertToDouble()));
158 case APFloat::Semantics::S_IEEEsingle:
159 return APFloat(atanhf(a.convertToFloat()));
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());
177 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
178 case APFloat::Semantics::S_IEEEdouble:
179 return APFloat(atan2(a.convertToDouble(), b.convertToDouble()));
180 case APFloat::Semantics::S_IEEEsingle:
181 return APFloat(atan2f(a.convertToFloat(), b.convertToFloat()));
194 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
195 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
196 case APFloat::Semantics::S_IEEEdouble:
197 return APFloat(cbrt(a.convertToDouble()));
198 case APFloat::Semantics::S_IEEEsingle:
199 return APFloat(cbrtf(a.convertToFloat()));
212 adaptor.getOperands(), [](
const APFloat &a) {
214 result.roundToIntegral(llvm::RoundingMode::TowardPositive);
223OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {
225 [](
const APFloat &a,
const APFloat &
b) {
238 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
239 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
240 case APFloat::Semantics::S_IEEEdouble:
241 return APFloat(cos(a.convertToDouble()));
242 case APFloat::Semantics::S_IEEEsingle:
243 return APFloat(cosf(a.convertToFloat()));
256 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
257 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
258 case APFloat::Semantics::S_IEEEdouble:
259 return APFloat(cosh(a.convertToDouble()));
260 case APFloat::Semantics::S_IEEEsingle:
261 return APFloat(coshf(a.convertToFloat()));
274 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
275 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
276 case APFloat::Semantics::S_IEEEdouble:
277 return APFloat(sin(a.convertToDouble()));
278 case APFloat::Semantics::S_IEEEsingle:
279 return APFloat(sinf(a.convertToFloat()));
292 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
293 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
294 case APFloat::Semantics::S_IEEEdouble:
295 return APFloat(sinh(a.convertToDouble()));
296 case APFloat::Semantics::S_IEEEsingle:
297 return APFloat(sinhf(a.convertToFloat()));
308std::optional<SmallVector<int64_t, 4>> math::SincosOp::getShapeForUnroll() {
309 if (
auto vt = mlir::dyn_cast<VectorType>(getOperand().
getType()))
310 return llvm::to_vector<4>(vt.getShape());
314LogicalResult math::SincosOp::fold(FoldAdaptor adaptor,
316 auto foldSincos = [](
const APFloat &a, double (*fnDouble)(double),
317 float (*fnFloat)(float)) -> std::optional<APFloat> {
318 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
319 case APFloat::Semantics::S_IEEEdouble:
320 return APFloat(fnDouble(a.convertToDouble()));
321 case APFloat::Semantics::S_IEEEsingle:
322 return APFloat(fnFloat(a.convertToFloat()));
329 adaptor.getOperands(),
330 [&](
const APFloat &a) { return foldSincos(a, sin, sinf); });
332 adaptor.getOperands(),
333 [&](
const APFloat &a) { return foldSincos(a, cos, cosf); });
335 if (sinRes && cosRes) {
347OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {
349 adaptor.getOperands(),
350 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });
357OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {
359 adaptor.getOperands(),
360 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });
369 adaptor.getOperands(),
370 [](
const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });
379 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
380 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
381 case APFloat::Semantics::S_IEEEdouble:
382 return APFloat(erf(a.convertToDouble()));
383 case APFloat::Semantics::S_IEEEsingle:
384 return APFloat(erff(a.convertToFloat()));
397 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
398 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
399 case APFloat::Semantics::S_IEEEdouble:
400 return APFloat(erfc(a.convertToDouble()));
401 case APFloat::Semantics::S_IEEEsingle:
402 return APFloat(erfcf(a.convertToFloat()));
415 adaptor.getOperands(),
416 [](
const APInt &base,
const APInt &power) -> std::optional<APInt> {
417 unsigned width = base.getBitWidth();
418 auto zeroValue = APInt::getZero(width);
422 APInt oneValue{width, 1ULL, true};
423 APInt minusOneValue{width, -1ULL, true};
428 if (power.isNegative()) {
435 if (base.ne(minusOneValue))
441 return minusOneValue;
448 APInt curBase = base;
449 APInt curPower = power;
451 if (curPower[0] == 1)
453 curPower.lshrInPlace(1);
454 if (curPower.isZero())
467 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
471 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
472 case APFloat::Semantics::S_IEEEdouble:
473 return APFloat(log(a.convertToDouble()));
474 case APFloat::Semantics::S_IEEEsingle:
475 return APFloat(logf(a.convertToFloat()));
488 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
492 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
493 case APFloat::Semantics::S_IEEEdouble:
494 return APFloat(log2(a.convertToDouble()));
495 case APFloat::Semantics::S_IEEEsingle:
496 return APFloat(log2f(a.convertToFloat()));
509 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
513 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
514 case APFloat::Semantics::S_IEEEdouble:
515 return APFloat(log10(a.convertToDouble()));
516 case APFloat::Semantics::S_IEEEsingle:
517 return APFloat(log10f(a.convertToFloat()));
530 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
531 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
532 case APFloat::Semantics::S_IEEEdouble:
533 if ((a + APFloat(1.0)).isNegative())
535 return APFloat(log1p(a.convertToDouble()));
536 case APFloat::Semantics::S_IEEEsingle:
537 if ((a + APFloat(1.0f)).isNegative())
539 return APFloat(log1pf(a.convertToFloat()));
552 adaptor.getOperands(),
553 [](
const APFloat &a,
const APFloat &
b) -> std::optional<APFloat> {
554 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
555 case APFloat::Semantics::S_IEEEdouble:
556 return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
557 case APFloat::Semantics::S_IEEEsingle:
558 return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
571 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
575 APFloat one(a.getSemantics(), 1);
576 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
577 case APFloat::Semantics::S_IEEEdouble:
578 return one / APFloat(sqrt(a.convertToDouble()));
579 case APFloat::Semantics::S_IEEEsingle:
580 return one / APFloat(sqrtf(a.convertToFloat()));
593 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
597 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
598 case APFloat::Semantics::S_IEEEdouble:
599 return APFloat(sqrt(a.convertToDouble()));
600 case APFloat::Semantics::S_IEEEsingle:
601 return APFloat(sqrtf(a.convertToFloat()));
614 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
615 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
616 case APFloat::Semantics::S_IEEEdouble:
617 return APFloat(exp(a.convertToDouble()));
618 case APFloat::Semantics::S_IEEEsingle:
619 return APFloat(expf(a.convertToFloat()));
632 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
633 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
634 case APFloat::Semantics::S_IEEEdouble:
635 return APFloat(exp2(a.convertToDouble()));
636 case APFloat::Semantics::S_IEEEsingle:
637 return APFloat(exp2f(a.convertToFloat()));
650 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
651 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
652 case APFloat::Semantics::S_IEEEdouble:
653 return APFloat(expm1(a.convertToDouble()));
654 case APFloat::Semantics::S_IEEEsingle:
655 return APFloat(expm1f(a.convertToFloat()));
666OpFoldResult math::IsFiniteOp::fold(FoldAdaptor adaptor) {
667 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
668 return BoolAttr::get(val.getContext(), val.getValue().isFinite());
670 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
673 APInt(1, splat.getSplatValue<APFloat>().isFinite()));
683 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
684 return BoolAttr::get(val.getContext(), val.getValue().isInfinity());
686 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
689 APInt(1, splat.getSplatValue<APFloat>().isInfinity()));
699 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
700 return BoolAttr::get(val.getContext(), val.getValue().isNaN());
702 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
705 APInt(1, splat.getSplatValue<APFloat>().isNaN()));
714OpFoldResult math::IsNormalOp::fold(FoldAdaptor adaptor) {
715 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
716 return BoolAttr::get(val.getContext(), val.getValue().isNormal());
718 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
721 APInt(1, splat.getSplatValue<APFloat>().isNormal()));
732 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
733 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
734 case APFloat::Semantics::S_IEEEdouble:
735 return APFloat(tan(a.convertToDouble()));
736 case APFloat::Semantics::S_IEEEsingle:
737 return APFloat(tanf(a.convertToFloat()));
750 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
751 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
752 case APFloat::Semantics::S_IEEEdouble:
753 return APFloat(tanh(a.convertToDouble()));
754 case APFloat::Semantics::S_IEEEsingle:
755 return APFloat(tanhf(a.convertToFloat()));
766OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
768 adaptor.getOperands(), [](
const APFloat &a) {
770 result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
781 adaptor.getOperands(), [](
const APFloat &a) {
783 result.roundToIntegral(llvm::RoundingMode::TowardNegative);
794 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
795 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
796 case APFloat::Semantics::S_IEEEdouble:
797 return APFloat(round(a.convertToDouble()));
798 case APFloat::Semantics::S_IEEEsingle:
799 return APFloat(roundf(a.convertToFloat()));
812 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
813 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
814 case APFloat::Semantics::S_IEEEdouble:
815 return APFloat(trunc(a.convertToDouble()));
816 case APFloat::Semantics::S_IEEEsingle:
817 return APFloat(truncf(a.convertToFloat()));
830 adaptor.getOperands(),
831 [](
const APFloat &base,
const APInt &exp) -> std::optional<APFloat> {
832 switch (APFloat::SemanticsToEnum(base.getSemantics())) {
833 case APFloat::Semantics::S_IEEEdouble:
834 case APFloat::Semantics::S_IEEEsingle:
842 const llvm::fltSemantics &sem = base.getSemantics();
843 APInt magnitude = exp.abs();
844 APFloat res = APFloat::getOne(sem);
845 APFloat curSquare = base;
846 while (!magnitude.isZero()) {
848 res = res * curSquare;
849 curSquare = curSquare * curSquare;
850 magnitude.lshrInPlace(1);
852 if (exp.isNegative())
853 res = APFloat::getOne(sem) / res;
862 if (
auto poison = dyn_cast<ub::PoisonAttr>(value))
863 return ub::PoisonOp::create(builder, loc, type, poison);
865 return arith::ConstantOp::materialize(builder, value, type, loc);
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
static Type getI1SameShape(Type type)
Return the type of the same shape (scalar, vector or tensor) containing i1.
while(succeeded(parser.parseOptionalComma()))
Attributes are known-constant values of operations.
static BoolAttr get(MLIRContext *context, bool value)
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
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...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Include the generated interface declarations.
Attribute constFoldBinaryOpConditional(ArrayRef< Attribute > operands, Type resultType, CalculationT &&calculate)
Performs constant folding calculate with element-wise behavior on the two attributes in operands and ...
Attribute constFoldBinaryOp(ArrayRef< Attribute > operands, Type resultType, CalculationT &&calculate)
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Attribute constFoldUnaryOpConditional(ArrayRef< Attribute > operands, Type resultType, CalculationT &&calculate)
Performs constant folding calculate with element-wise behavior on the one attributes in operands and ...
Attribute constFoldUnaryOp(ArrayRef< Attribute > operands, Type resultType, CalculationT &&calculate)