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())
469 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
473 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
474 case APFloat::Semantics::S_IEEEdouble:
475 return APFloat(log(a.convertToDouble()));
476 case APFloat::Semantics::S_IEEEsingle:
477 return APFloat(logf(a.convertToFloat()));
490 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
494 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
495 case APFloat::Semantics::S_IEEEdouble:
496 return APFloat(log2(a.convertToDouble()));
497 case APFloat::Semantics::S_IEEEsingle:
498 return APFloat(log2f(a.convertToFloat()));
511 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
515 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
516 case APFloat::Semantics::S_IEEEdouble:
517 return APFloat(log10(a.convertToDouble()));
518 case APFloat::Semantics::S_IEEEsingle:
519 return APFloat(log10f(a.convertToFloat()));
532 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
533 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
534 case APFloat::Semantics::S_IEEEdouble:
535 if ((a + APFloat(1.0)).isNegative())
537 return APFloat(log1p(a.convertToDouble()));
538 case APFloat::Semantics::S_IEEEsingle:
539 if ((a + APFloat(1.0f)).isNegative())
541 return APFloat(log1pf(a.convertToFloat()));
554 adaptor.getOperands(),
555 [](
const APFloat &a,
const APFloat &
b) -> std::optional<APFloat> {
556 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
557 case APFloat::Semantics::S_IEEEdouble:
558 return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
559 case APFloat::Semantics::S_IEEEsingle:
560 return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
573 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
577 APFloat one(a.getSemantics(), 1);
578 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
579 case APFloat::Semantics::S_IEEEdouble:
580 return one / APFloat(sqrt(a.convertToDouble()));
581 case APFloat::Semantics::S_IEEEsingle:
582 return one / APFloat(sqrtf(a.convertToFloat()));
595 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
599 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
600 case APFloat::Semantics::S_IEEEdouble:
601 return APFloat(sqrt(a.convertToDouble()));
602 case APFloat::Semantics::S_IEEEsingle:
603 return APFloat(sqrtf(a.convertToFloat()));
616 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
617 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
618 case APFloat::Semantics::S_IEEEdouble:
619 return APFloat(exp(a.convertToDouble()));
620 case APFloat::Semantics::S_IEEEsingle:
621 return APFloat(expf(a.convertToFloat()));
634 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
635 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
636 case APFloat::Semantics::S_IEEEdouble:
637 return APFloat(exp2(a.convertToDouble()));
638 case APFloat::Semantics::S_IEEEsingle:
639 return APFloat(exp2f(a.convertToFloat()));
652 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
653 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
654 case APFloat::Semantics::S_IEEEdouble:
655 return APFloat(expm1(a.convertToDouble()));
656 case APFloat::Semantics::S_IEEEsingle:
657 return APFloat(expm1f(a.convertToFloat()));
668OpFoldResult math::IsFiniteOp::fold(FoldAdaptor adaptor) {
669 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
670 return BoolAttr::get(val.getContext(), val.getValue().isFinite());
672 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
675 APInt(1, splat.getSplatValue<APFloat>().isFinite()));
685 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
686 return BoolAttr::get(val.getContext(), val.getValue().isInfinity());
688 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
691 APInt(1, splat.getSplatValue<APFloat>().isInfinity()));
701 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
702 return BoolAttr::get(val.getContext(), val.getValue().isNaN());
704 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
707 APInt(1, splat.getSplatValue<APFloat>().isNaN()));
716OpFoldResult math::IsNormalOp::fold(FoldAdaptor adaptor) {
717 if (
auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
718 return BoolAttr::get(val.getContext(), val.getValue().isNormal());
720 if (
auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
723 APInt(1, splat.getSplatValue<APFloat>().isNormal()));
734 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
735 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
736 case APFloat::Semantics::S_IEEEdouble:
737 return APFloat(tan(a.convertToDouble()));
738 case APFloat::Semantics::S_IEEEsingle:
739 return APFloat(tanf(a.convertToFloat()));
752 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
753 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
754 case APFloat::Semantics::S_IEEEdouble:
755 return APFloat(tanh(a.convertToDouble()));
756 case APFloat::Semantics::S_IEEEsingle:
757 return APFloat(tanhf(a.convertToFloat()));
768OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
770 adaptor.getOperands(), [](
const APFloat &a) {
772 result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
783 adaptor.getOperands(), [](
const APFloat &a) {
785 result.roundToIntegral(llvm::RoundingMode::TowardNegative);
796 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
797 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
798 case APFloat::Semantics::S_IEEEdouble:
799 return APFloat(round(a.convertToDouble()));
800 case APFloat::Semantics::S_IEEEsingle:
801 return APFloat(roundf(a.convertToFloat()));
814 adaptor.getOperands(), [](
const APFloat &a) -> std::optional<APFloat> {
815 switch (APFloat::SemanticsToEnum(a.getSemantics())) {
816 case APFloat::Semantics::S_IEEEdouble:
817 return APFloat(trunc(a.convertToDouble()));
818 case APFloat::Semantics::S_IEEEsingle:
819 return APFloat(truncf(a.convertToFloat()));
832 adaptor.getOperands(),
833 [](
const APFloat &base,
const APInt &exp) -> std::optional<APFloat> {
834 const llvm::fltSemantics &sem = base.getSemantics();
838 if (fExp.convertFromAPInt(exp, true,
839 APFloat::rmNearestTiesToEven) !=
843 switch (APFloat::SemanticsToEnum(sem)) {
844 case APFloat::Semantics::S_IEEEdouble:
845 return APFloat(pow(base.convertToDouble(), fExp.convertToDouble()));
846 case APFloat::Semantics::S_IEEEsingle:
847 return APFloat(powf(base.convertToFloat(), fExp.convertToFloat()));
858 if (
auto poison = dyn_cast<ub::PoisonAttr>(value))
859 return ub::PoisonOp::create(builder, loc, type, poison);
861 return arith::ConstantOp::materialize(builder, value, type, loc);
static Type getI1SameShape(Type type)
Return the type of the same shape (scalar, vector or tensor) containing i1.
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)