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>>
309math::SincosOp::getIterationShapeToUnroll() {
310 if (
auto vt = mlir::dyn_cast<VectorType>(getOperand().
getType()))
311 return llvm::to_vector<4>(vt.getShape());
315LogicalResult math::SincosOp::fold(FoldAdaptor adaptor,
317 auto foldSincos = [](
const APFloat &a, double (*fnDouble)(double),
318 float (*fnFloat)(float)) -> std::optional<APFloat> {
319 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
320 case APFloat::Semantics::S_IEEEdouble:
321 return APFloat(fnDouble(a.convertToDouble()));
322 case APFloat::Semantics::S_IEEEsingle:
323 return APFloat(fnFloat(a.convertToFloat()));
330 adaptor.getOperands(),
331 [&](
const APFloat &a) { return foldSincos(a, sin, sinf); });
333 adaptor.getOperands(),
334 [&](
const APFloat &a) { return foldSincos(a, cos, cosf); });
336 if (sinRes && cosRes) {
348OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {
350 adaptor.getOperands(),
351 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });
358OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {
360 adaptor.getOperands(),
361 [](
const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });
370 adaptor.getOperands(),
371 [](
const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });
380 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
381 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
382 case APFloat::Semantics::S_IEEEdouble:
383 return APFloat(erf(a.convertToDouble()));
384 case APFloat::Semantics::S_IEEEsingle:
385 return APFloat(erff(a.convertToFloat()));
398 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
399 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
400 case APFloat::Semantics::S_IEEEdouble:
401 return APFloat(erfc(a.convertToDouble()));
402 case APFloat::Semantics::S_IEEEsingle:
403 return APFloat(erfcf(a.convertToFloat()));
416 adaptor.getOperands(),
417 [](
const APInt &base,
const APInt &power) -> std::optional<APInt> {
418 unsigned width = base.getBitWidth();
419 auto zeroValue = APInt::getZero(width);
423 APInt oneValue{width, 1ULL, true};
424 APInt minusOneValue{width, -1ULL, true};
429 if (power.isNegative()) {
436 if (base.ne(minusOneValue))
442 return minusOneValue;
449 APInt curBase = base;
450 APInt curPower = power;
452 if (curPower[0] == 1)
454 curPower.lshrInPlace(1);
455 if (curPower.isZero())
468 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
472 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
473 case APFloat::Semantics::S_IEEEdouble:
474 return APFloat(log(a.convertToDouble()));
475 case APFloat::Semantics::S_IEEEsingle:
476 return APFloat(logf(a.convertToFloat()));
489 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
493 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
494 case APFloat::Semantics::S_IEEEdouble:
495 return APFloat(log2(a.convertToDouble()));
496 case APFloat::Semantics::S_IEEEsingle:
497 return APFloat(log2f(a.convertToFloat()));
510 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
514 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
515 case APFloat::Semantics::S_IEEEdouble:
516 return APFloat(log10(a.convertToDouble()));
517 case APFloat::Semantics::S_IEEEsingle:
518 return APFloat(log10f(a.convertToFloat()));
531 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
532 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
533 case APFloat::Semantics::S_IEEEdouble:
534 if ((a + APFloat(1.0)).isNegative())
536 return APFloat(log1p(a.convertToDouble()));
537 case APFloat::Semantics::S_IEEEsingle:
538 if ((a + APFloat(1.0f)).isNegative())
540 return APFloat(log1pf(a.convertToFloat()));
553 adaptor.getOperands(),
554 [](
const APFloat &a,
const APFloat &
b) -> std::optional<APFloat> {
555 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
556 case APFloat::Semantics::S_IEEEdouble:
557 return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
558 case APFloat::Semantics::S_IEEEsingle:
559 return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
572 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
576 APFloat one(a.getSemantics(), 1);
577 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
578 case APFloat::Semantics::S_IEEEdouble:
579 return one / APFloat(sqrt(a.convertToDouble()));
580 case APFloat::Semantics::S_IEEEsingle:
581 return one / APFloat(sqrtf(a.convertToFloat()));
594 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
598 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
599 case APFloat::Semantics::S_IEEEdouble:
600 return APFloat(sqrt(a.convertToDouble()));
601 case APFloat::Semantics::S_IEEEsingle:
602 return APFloat(sqrtf(a.convertToFloat()));
615 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
616 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
617 case APFloat::Semantics::S_IEEEdouble:
618 return APFloat(exp(a.convertToDouble()));
619 case APFloat::Semantics::S_IEEEsingle:
620 return APFloat(expf(a.convertToFloat()));
633 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
634 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
635 case APFloat::Semantics::S_IEEEdouble:
636 return APFloat(exp2(a.convertToDouble()));
637 case APFloat::Semantics::S_IEEEsingle:
638 return APFloat(exp2f(a.convertToFloat()));
651 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
652 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
653 case APFloat::Semantics::S_IEEEdouble:
654 return APFloat(expm1(a.convertToDouble()));
655 case APFloat::Semantics::S_IEEEsingle:
656 return APFloat(expm1f(a.convertToFloat()));
667OpFoldResult math::IsFiniteOp::fold(FoldAdaptor adaptor) {
668 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
669 return BoolAttr::get(val.getContext(), val.getValue().isFinite());
671 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
674 APInt(1, splat.getSplatValue<APFloat>().isFinite()));
684 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
685 return BoolAttr::get(val.getContext(), val.getValue().isInfinity());
687 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
690 APInt(1, splat.getSplatValue<APFloat>().isInfinity()));
700 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
701 return BoolAttr::get(val.getContext(), val.getValue().isNaN());
703 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
706 APInt(1, splat.getSplatValue<APFloat>().isNaN()));
715OpFoldResult math::IsNormalOp::fold(FoldAdaptor adaptor) {
716 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
717 return BoolAttr::get(val.getContext(), val.getValue().isNormal());
719 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
722 APInt(1, splat.getSplatValue<APFloat>().isNormal()));
733 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
734 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
735 case APFloat::Semantics::S_IEEEdouble:
736 return APFloat(tan(a.convertToDouble()));
737 case APFloat::Semantics::S_IEEEsingle:
738 return APFloat(tanf(a.convertToFloat()));
751 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
752 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
753 case APFloat::Semantics::S_IEEEdouble:
754 return APFloat(tanh(a.convertToDouble()));
755 case APFloat::Semantics::S_IEEEsingle:
756 return APFloat(tanhf(a.convertToFloat()));
767OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
769 adaptor.getOperands(), [](
const APFloat &a) {
771 result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
782 adaptor.getOperands(), [](
const APFloat &a) {
784 result.roundToIntegral(llvm::RoundingMode::TowardNegative);
795 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
796 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
797 case APFloat::Semantics::S_IEEEdouble:
798 return APFloat(round(a.convertToDouble()));
799 case APFloat::Semantics::S_IEEEsingle:
800 return APFloat(roundf(a.convertToFloat()));
813 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
814 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
815 case APFloat::Semantics::S_IEEEdouble:
816 return APFloat(trunc(a.convertToDouble()));
817 case APFloat::Semantics::S_IEEEsingle:
818 return APFloat(truncf(a.convertToFloat()));
831 adaptor.getOperands(),
832 [](
const APFloat &base,
const APInt &exp) -> std::optional<APFloat> {
833 switch (APFloat::SemanticsToEnum(base.getSemantics())) {
834 case APFloat::Semantics::S_IEEEdouble:
835 case APFloat::Semantics::S_IEEEsingle:
843 const llvm::fltSemantics &sem = base.getSemantics();
844 APInt magnitude = exp.abs();
845 APFloat res = APFloat::getOne(sem);
846 APFloat curSquare = base;
847 while (!magnitude.isZero()) {
849 res = res * curSquare;
850 curSquare = curSquare * curSquare;
851 magnitude.lshrInPlace(1);
853 if (exp.isNegative())
854 res = APFloat::getOne(sem) / res;
863 if (
auto poison = dyn_cast<ub::PoisonAttr>(value))
864 return ub::PoisonOp::create(builder, loc, type, poison);
866 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)