19#define GEN_PASS_DEF_ARITHEXPANDOPSPASS
20#include "mlir/Dialect/Arith/Transforms/Passes.h.inc"
30 if (
auto shapedTy = dyn_cast<ShapedType>(type)) {
31 return arith::ConstantOp::create(rewriter, loc,
34 return arith::ConstantOp::create(rewriter, loc, attr);
41 if (
auto shapedTy = dyn_cast<ShapedType>(type)) {
42 return arith::ConstantOp::create(rewriter, loc,
46 return arith::ConstantOp::create(rewriter, loc, attr);
51 if (
auto shapedTy = dyn_cast<ShapedType>(cloneFrom)) {
52 return shapedTy.clone(cloneTo);
63 LogicalResult matchAndRewrite(arith::CeilDivUIOp op,
64 PatternRewriter &rewriter)
const final {
65 Location loc = op.getLoc();
66 Value a = op.getLhs();
67 Value
b = op.getRhs();
70 arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
72 Value minusOne = arith::SubIOp::create(rewriter, loc, a, one);
73 Value quotient = arith::DivUIOp::create(rewriter, loc, minusOne,
b);
74 Value plusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
75 rewriter.replaceOpWithNewOp<arith::SelectOp>(op,
compare, zero, plusOne);
89 LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
90 PatternRewriter &rewriter)
const final {
91 Location loc = op.getLoc();
92 Type type = op.getType();
93 Value a = op.getLhs();
94 Value
b = op.getRhs();
99 Value quotient = arith::DivSIOp::create(rewriter, loc, a,
b);
100 Value
product = arith::MulIOp::create(rewriter, loc, quotient,
b);
101 Value notEqualDivisor = arith::CmpIOp::create(
102 rewriter, loc, arith::CmpIPredicate::ne, a,
product);
104 Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
106 Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
109 Value signEqual = arith::CmpIOp::create(
110 rewriter, loc, arith::CmpIPredicate::eq, aNeg, bNeg);
112 arith::AndIOp::create(rewriter, loc, notEqualDivisor, signEqual);
114 Value quotientPlusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
116 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
129struct FloorDivSIOpConverter :
public OpRewritePattern<arith::FloorDivSIOp> {
131 LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
132 PatternRewriter &rewriter)
const final {
133 Location loc = op.getLoc();
134 Type type = op.getType();
135 Value a = op.getLhs();
136 Value
b = op.getRhs();
138 Value quotient = arith::DivSIOp::create(rewriter, loc, a,
b);
139 Value
product = arith::MulIOp::create(rewriter, loc, quotient,
b);
140 Value notEqualDivisor = arith::CmpIOp::create(
141 rewriter, loc, arith::CmpIPredicate::ne, a,
product);
144 Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
146 Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
149 Value signOpposite = arith::CmpIOp::create(
150 rewriter, loc, arith::CmpIPredicate::ne, aNeg, bNeg);
152 arith::AndIOp::create(rewriter, loc, notEqualDivisor, signOpposite);
154 Value minusOne =
createConst(loc, type, -1, rewriter);
155 Value quotientMinusOne =
156 arith::AddIOp::create(rewriter, loc, quotient, minusOne);
158 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
164template <
typename OpTy, arith::CmpIPredicate pred>
167 using OpRewritePattern<OpTy>::OpRewritePattern;
169 LogicalResult matchAndRewrite(OpTy op,
170 PatternRewriter &rewriter)
const final {
171 Value
lhs = op.getLhs();
172 Value
rhs = op.getRhs();
174 Value cmp = arith::CmpIOp::create(rewriter, op.getLoc(), pred,
lhs,
rhs);
175 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cmp,
lhs,
rhs);
180template <
typename OpTy, arith::CmpFPredicate pred>
183 using OpRewritePattern<OpTy>::OpRewritePattern;
185 LogicalResult matchAndRewrite(OpTy op,
186 PatternRewriter &rewriter)
const final {
187 Value
lhs = op.getLhs();
188 Value
rhs = op.getRhs();
190 Location loc = op.getLoc();
192 static_assert(pred == arith::CmpFPredicate::UGT ||
193 pred == arith::CmpFPredicate::ULT,
194 "pred must be either UGT or ULT");
195 Value cmp = arith::CmpFOp::create(rewriter, loc, pred,
lhs,
rhs);
196 Value select = arith::SelectOp::create(rewriter, loc, cmp,
lhs,
rhs);
199 Value isNaN = arith::CmpFOp::create(rewriter, loc,
200 arith::CmpFPredicate::UNO,
rhs,
rhs);
201 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, isNaN,
rhs, select);
206template <
typename OpTy, arith::CmpFPredicate pred>
209 using OpRewritePattern<OpTy>::OpRewritePattern;
211 LogicalResult matchAndRewrite(OpTy op,
212 PatternRewriter &rewriter)
const final {
213 Value
lhs = op.getLhs();
214 Value
rhs = op.getRhs();
216 Location loc = op.getLoc();
218 static_assert(pred == arith::CmpFPredicate::UGT ||
219 pred == arith::CmpFPredicate::ULT,
220 "pred must be either UGT or ULT");
221 Value cmp = arith::CmpFOp::create(rewriter, loc, pred,
lhs,
rhs);
222 Value select = arith::SelectOp::create(rewriter, loc, cmp,
lhs,
rhs);
225 Value isNaN = arith::CmpFOp::create(rewriter, loc,
226 arith::CmpFPredicate::UNO,
lhs,
lhs);
227 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, isNaN,
rhs, select);
234 LogicalResult matchAndRewrite(arith::ExtFOp op,
237 auto operand = op.getOperand();
238 Type operandTy = operand.getType();
244 return rewriter.notifyMatchFailure(op,
"not a ext of bf16 to f32.");
250 Value bitcast = arith::BitcastOp::create(
b, i16Ty, operand);
251 Value exti = arith::ExtUIOp::create(
b, i32Ty, bitcast);
254 Value shl = arith::ShLIOp::create(
b, exti, c16);
255 Value result = arith::BitcastOp::create(
b, resultTy, shl);
257 rewriter.replaceOp(op,
result);
262struct BFloat16TruncFOpConverter :
public OpRewritePattern<arith::TruncFOp> {
264 LogicalResult matchAndRewrite(arith::TruncFOp op,
267 auto operand = op.getOperand();
268 Type operandTy = operand.getType();
274 return rewriter.notifyMatchFailure(op,
"not a trunc of f32 to bf16.");
277 if (op.getRoundingmodeAttr()) {
278 return rewriter.notifyMatchFailure(
279 op,
"only applicable to default rounding mode.");
299 arith::CmpFOp::create(
b, arith::CmpFPredicate::UNE, operand, operand);
308 Value bitcast = arith::BitcastOp::create(
b, i32Ty, operand);
311 arith::AndIOp::create(
b, arith::ShRUIOp::create(
b, bitcast, c16), c1);
314 Value roundingBias = arith::AddIOp::create(
b, bit16, c7FFF);
321 Value biased = arith::AddIOp::create(
b, bitcast, roundingBias);
324 Value biasedAndShifted = arith::ShRUIOp::create(
b, biased, c16);
325 Value normalCaseResultI16 =
326 arith::TruncIOp::create(
b, i16Ty, biasedAndShifted);
330 arith::SelectOp::create(
b, isNan, c7FC0I16, normalCaseResultI16);
331 Value result = arith::BitcastOp::create(
b, resultTy, select);
332 rewriter.replaceOp(op,
result);
368 LogicalResult matchAndRewrite(arith::ExtFOp op,
372 Value operand = op.getOperand();
374 Type resultTy = op.getType();
378 if (!isa<Float4E2M1FNType>(operandETy))
379 return rewriter.notifyMatchFailure(op,
"not a ext of F4E2M1FN");
384 Value i4Bits = arith::BitcastOp::create(
b, i4Ty, operand);
392 Value i4BitsNoSign = arith::AndIOp::create(
b, i4Bits, c0x7);
396 Value bits1To24 = arith::ShLIOp::create(
b, i4BitsNoSign, c0x2);
398 arith::CmpIOp::create(
b, arith::CmpIPredicate::eq, i4BitsNoSign, c0x1);
399 bits1To24 = arith::SelectOp::create(
b, isHalf, c0x0, bits1To24);
400 bits1To24 = arith::ExtUIOp::create(
b, i32Ty, bits1To24);
401 bits1To24 = arith::ShLIOp::create(
b, bits1To24, c0x00000014);
408 arith::CmpIOp::create(
b, arith::CmpIPredicate::uge, i4BitsNoSign, c0x4);
410 arith::SelectOp::create(
b, useLargerExp, highExpBits, lowExpBits);
412 arith::CmpIOp::create(
b, arith::CmpIPredicate::eq, i4BitsNoSign, c0x0);
413 bits25To31 = arith::SelectOp::create(
b, zeroExp, zeroExpBits, bits25To31);
419 arith::CmpIOp::create(
b, arith::CmpIPredicate::uge, i4Bits, c0x8);
421 arith::SelectOp::create(
b, negative, c0x80000000, zeroExpBits);
424 Value bits1To31 = arith::AddIOp::create(
b, bits1To24, bits25To31);
425 Value bits1To32 = arith::AddIOp::create(
b, bits1To31, bit32);
426 Value result = arith::BitcastOp::create(
b, f32Ty, bits1To32);
427 if (!isa<Float32Type>(resultETy))
430 rewriter.replaceOp(op,
result);
437 LogicalResult matchAndRewrite(arith::ExtFOp op,
438 PatternRewriter &rewriter)
const final {
439 ImplicitLocOpBuilder
b(op.getLoc(), rewriter);
440 Value operand = op.getOperand();
441 Type operandTy = operand.
getType();
442 Type resultTy = op.getType();
446 if (!llvm::isa<Float8E8M0FNUType>(operandETy)) {
447 return rewriter.notifyMatchFailure(op,
"not a ext of F8E8M0FNU");
454 Value bitcast = arith::BitcastOp::create(
b, i8Ty, operand);
455 Value cF32MantissaWidth =
createConst(op->getLoc(), i32Ty, 23, rewriter);
456 Value exti = arith::ExtUIOp::create(
b, i32Ty, bitcast);
457 Value f32Bits = arith::ShLIOp::create(
b, exti, cF32MantissaWidth);
460 auto fastMath = op.getFastmathAttr();
461 bool NoNaN = fastMath
462 ? (fastMath.getValue() & arith::FastMathFlags::nnan) ==
463 arith::FastMathFlags::nnan
466 Value cF8NaN =
createConst(op.getLoc(), i8Ty, 0xff, rewriter);
467 Value cF32NaN =
createConst(op.getLoc(), i32Ty, 0xffffffff, rewriter);
469 arith::CmpIOp::create(
b, arith::CmpIPredicate::eq, bitcast, cF8NaN);
471 f32Bits = arith::SelectOp::create(
b, isNan, cF32NaN, f32Bits);
474 Value
result = arith::BitcastOp::create(
b, f32Ty, f32Bits);
476 result = arith::TruncFOp::create(
b, resultTy,
result,
nullptr,
477 op.getFastmathAttr());
479 result = arith::ExtFOp::create(
b, resultTy,
result, op.getFastmathAttr());
481 rewriter.replaceOp(op,
result);
516 LogicalResult matchAndRewrite(arith::TruncFOp op,
517 PatternRewriter &rewriter)
const final {
518 Location loc = op.getLoc();
519 ImplicitLocOpBuilder
b(loc, rewriter);
520 Value operand = op.getOperand();
521 Type operandTy = operand.
getType();
522 Type resultTy = op.getType();
531 if (!isa<Float4E2M1FNType>(resultETy))
532 return rewriter.notifyMatchFailure(op,
"not a trunc of F4E2M1FN");
533 if (!isa<Float32Type>(operandETy))
534 operand = arith::ExtFOp::create(
b, f32Ty, operand);
538 Value c0x00000016 =
createConst(loc, i32Ty, 22, rewriter);
539 Value c0x00 =
createConst(loc, i8Ty, 0x00, rewriter);
540 Value c0xff =
createConst(loc, i8Ty, 0xff, rewriter);
541 Value zeroExpBits =
createConst(loc, i32Ty, 0, rewriter);
546 Value operandClamped = arith::MinNumFOp::create(
b, cHigherBound, operand);
547 operandClamped = arith::MaxNumFOp::create(
b, cLowerBound, operandClamped);
548 Value f32Bits = arith::BitcastOp::create(
b, i32Ty, operandClamped);
551 Value cF32ExpManWidth =
createConst(loc, i32Ty, 31, rewriter);
552 Value f32Sign = arith::ShRUIOp::create(
b, f32Bits, cF32ExpManWidth);
553 Value f4Sign = arith::TruncIOp::create(
b, i4Ty, f32Sign);
554 Value f4Bits = arith::ShLIOp::create(
b, f4Sign, c0x3);
557 Value biasAdjustment =
createConst(loc, i32Ty, 0x7e, rewriter);
558 Value cF4MantissaWidth = c0x1;
559 Value cF32MantissaWidth =
createConst(loc, i32Ty, 23, rewriter);
560 Value f32SignExp = arith::ShRUIOp::create(
b, f32Bits, cF32MantissaWidth);
561 Value biasAdjustedSignExp =
562 arith::SubIOp::create(
b, f32SignExp, biasAdjustment);
563 Value f4Exp = arith::TruncIOp::create(
b, i4Ty, biasAdjustedSignExp);
564 f4Exp = arith::ShLIOp::create(
b, f4Exp, cF4MantissaWidth);
565 f4Bits = arith::AddIOp::create(
b, f4Bits, f4Exp);
568 Value cF32FirstBitMask =
createConst(loc, i32Ty, 0x400000, rewriter);
569 Value man1Bit = arith::AndIOp::create(
b, f32Bits, cF32FirstBitMask);
570 man1Bit = arith::ShRUIOp::create(
b, man1Bit, c0x00000016);
571 Value f4Man = arith::TruncIOp::create(
b, i4Ty, man1Bit);
572 f4Bits = arith::AddIOp::create(
b, f4Bits, f4Man);
575 Value cF32MantissaMask =
createConst(loc, i32Ty, 0x7fffff, rewriter);
576 Value f8Exp = arith::TruncIOp::create(
b, i8Ty, biasAdjustedSignExp);
578 arith::CmpIOp::create(
b, arith::CmpIPredicate::sle, f8Exp, c0x00);
580 arith::CmpIOp::create(
b, arith::CmpIPredicate::eq, f8Exp, c0xff);
581 Value man23Bits = arith::AndIOp::create(
b, f32Bits, cF32MantissaMask);
582 Value isNonZeroMan = arith::CmpIOp::create(
b, arith::CmpIPredicate::ugt,
583 man23Bits, zeroExpBits);
584 Value roundToHalf = arith::AndIOp::create(
b, isNegOneExp, isNonZeroMan);
586 arith::CmpIOp::create(
b, arith::CmpIPredicate::eq, f8Exp, c0x00);
587 Value subnormalF4Bits =
createConst(loc, i4Ty, 0xf, rewriter);
588 Value halfF4Bits =
createConst(loc, i4Ty, 0x0, rewriter);
590 arith::SelectOp::create(
b, isSubnormal, subnormalF4Bits, f4Bits);
591 subResult = arith::SelectOp::create(
b, roundToHalf, halfF4Bits, subResult);
592 f4Bits = arith::SelectOp::create(
b, isZeroExp, f4Bits, subResult);
595 Value cF32Last22BitMask =
createConst(loc, i32Ty, 0x3fffff, rewriter);
596 Value cRound =
createConst(loc, i32Ty, 0x200000, rewriter);
597 Value man22Bits = arith::AndIOp::create(
b, f32Bits, cF32Last22BitMask);
599 arith::CmpIOp::create(
b, arith::CmpIPredicate::uge, man22Bits, cRound);
600 shouldRound = arith::OrIOp::create(
b, shouldRound, isSubnormal);
601 Value roundedF4Bits = arith::AddIOp::create(
b, f4Bits, c0x1);
602 f4Bits = arith::SelectOp::create(
b, shouldRound, roundedF4Bits, f4Bits);
604 Value
result = arith::BitcastOp::create(
b, resultTy, f4Bits);
605 rewriter.replaceOp(op,
result);
617 LogicalResult matchAndRewrite(arith::TruncFOp op,
618 PatternRewriter &rewriter)
const final {
619 ImplicitLocOpBuilder
b(op.getLoc(), rewriter);
620 Value operand = op.getOperand();
621 Type operandTy = operand.
getType();
623 Type resultTy = op.getType();
625 if (!llvm::isa<Float8E8M0FNUType>(resultETy)) {
626 return rewriter.notifyMatchFailure(op,
"not a truncf to f8E8M0FNU");
629 if (op.getRoundingmodeAttr()) {
630 return rewriter.notifyMatchFailure(
631 op,
"only applicable to default rounding mode.");
639 operand = arith::ExtFOp::create(
b, f32Ty, operand, op.getFastmathAttr());
641 operand = arith::TruncFOp::create(
642 b, f32Ty, operand, op.getRoundingmodeAttr(), op.getFastmathAttr());
644 Value f32Bits = arith::BitcastOp::create(
b, i32Ty, operand);
645 Value cF32MantissaWidth =
createConst(op->getLoc(), i32Ty, 23, rewriter);
646 Value f32SignExp = arith::ShRUIOp::create(
b, f32Bits, cF32MantissaWidth);
647 Value exp8Bits = arith::TruncIOp::create(
b, i8Ty, f32SignExp);
648 Value
result = arith::BitcastOp::create(
b, resultTy, exp8Bits);
649 rewriter.replaceOp(op,
result);
654struct ScalingExtFOpConverter :
public OpRewritePattern<arith::ScalingExtFOp> {
656 LogicalResult matchAndRewrite(arith::ScalingExtFOp op,
657 PatternRewriter &rewriter)
const final {
658 ImplicitLocOpBuilder
b(op.getLoc(), rewriter);
659 Value inputOperand = op.getIn();
660 Value scaleOperand = op.getScale();
661 Type scaleTy = scaleOperand.
getType();
665 scaleETy =
b.getF8E8M0Type();
667 scaleOperand = arith::TruncFOp::create(
b, scaleTy, scaleOperand,
nullptr,
668 op.getFastmathAttr());
671 if (!llvm::isa<Float8E8M0FNUType>(scaleETy)) {
672 return rewriter.notifyMatchFailure(
673 op,
"scaling_extf is using scales of type which can not be converted "
676 Type resultTy = op.getType();
680 arith::ExtFOp::create(
b, resultTy, scaleOperand, op.getFastmathAttr());
682 arith::ExtFOp::create(
b, resultTy, inputOperand, op.getFastmathAttr());
684 arith::MulFOp::create(
b, inputExt, scaleExt, op.getFastmathAttr());
685 rewriter.replaceOp(op,
result);
695struct ScalingTruncFOpConverter
698 LogicalResult matchAndRewrite(arith::ScalingTruncFOp op,
699 PatternRewriter &rewriter)
const final {
700 ImplicitLocOpBuilder
b(op.getLoc(), rewriter);
701 Value inputOperand = op.getIn();
702 Value scaleOperand = op.getScale();
703 Type scaleTy = scaleOperand.
getType();
707 scaleETy =
b.getF8E8M0Type();
709 scaleOperand = arith::TruncFOp::create(
b, scaleTy, scaleOperand,
nullptr,
710 op.getFastmathAttr());
712 if (!llvm::isa<Float8E8M0FNUType>(scaleETy)) {
713 return rewriter.notifyMatchFailure(
714 op,
"scaling_truncf is using scales type which can not be converted "
717 Type resultTy = op.getType();
718 Type inputTy = inputOperand.
getType();
722 arith::ExtFOp::create(
b, inputTy, scaleOperand, op.getFastmathAttr());
723 Value
result = arith::DivFOp::create(
b, inputOperand, scaleOperand,
724 op.getFastmathAttr());
725 Value resultCast = arith::TruncFOp::create(
726 b, resultTy,
result, op.getRoundingmodeAttr(), op.getFastmathAttr());
727 rewriter.replaceOp(op, resultCast);
732struct ArithExpandOpsPass
734 using ArithExpandOpsPassBase::ArithExpandOpsPassBase;
736 void runOnOperation()
override {
740 arith::populateArithExpandOpsPatterns(
patterns);
742 target.addLegalDialect<arith::ArithDialect>();
743 target.addLegalDialect<vector::VectorDialect>();
758 arith::ScalingExtFOp,
759 arith::ScalingTruncFOp
763 arith::populateExpandBFloat16Patterns(
patterns);
765 arith::populateExpandF8E8M0Patterns(
patterns);
767 arith::populateExpandF4E2M1Patterns(
patterns);
769 target.addDynamicallyLegalOp<arith::ExtFOp>(
770 [=](arith::ExtFOp op) {
773 bool legalTypes =
true;
777 legalTypes &= !llvm::isa<Float8E8M0FNUType>(inETy);
779 legalTypes &= !llvm::isa<Float4E2M1FNType>(inETy);
783 target.addDynamicallyLegalOp<arith::TruncFOp>(
784 [=](arith::TruncFOp op) {
787 bool legalTypes =
true;
791 legalTypes &= !(llvm::isa<Float8E8M0FNUType>(outETy));
793 legalTypes &= !llvm::isa<Float4E2M1FNType>(outETy);
798 if (
failed(applyPartialConversion(getOperation(),
target,
809 .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
814 patterns.add<BFloat16ExtFOpConverter, BFloat16TruncFOpConverter>(
819 patterns.add<F4E2M1ExtFOpConverter, F4E2M1TruncFOpConverter>(
824 patterns.add<F8E8M0ExtFOpConverter, F8E8M0TruncFOpConverter>(
830 patterns.add<ScalingExtFOpConverter, ScalingTruncFOpConverter>(
839 MaxMinIOpConverter<MaxSIOp, arith::CmpIPredicate::sgt>,
840 MaxMinIOpConverter<MaxUIOp, arith::CmpIPredicate::ugt>,
841 MaxMinIOpConverter<MinSIOp, arith::CmpIPredicate::slt>,
842 MaxMinIOpConverter<MinUIOp, arith::CmpIPredicate::ult>,
843 MaximumMinimumFOpConverter<MaximumFOp, arith::CmpFPredicate::UGT>,
844 MaximumMinimumFOpConverter<MinimumFOp, arith::CmpFPredicate::ULT>,
845 MaxNumMinNumFOpConverter<MaxNumFOp, arith::CmpFPredicate::UGT>,
846 MaxNumMinNumFOpConverter<MinNumFOp, arith::CmpFPredicate::ULT>
static int64_t product(ArrayRef< int64_t > vals)
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
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...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
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 represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
ArithExpandOpsPassBase Base
void populateExpandBFloat16Patterns(RewritePatternSet &patterns)
Add patterns to expand Arith bf16 patterns to lower level bitcasts/shifts.
void populateExpandScalingExtTruncPatterns(RewritePatternSet &patterns)
Add patterns to expand scaling ExtF/TruncF ops to equivalent arith ops.
void populateExpandF8E8M0Patterns(RewritePatternSet &patterns)
Add patterns to expand Arith f8e8m0 patterns to lower level bitcasts/shifts.
void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns)
Add patterns to expand Arith ceil/floor division ops.
void populateExpandF4E2M1Patterns(RewritePatternSet &patterns)
Add patterns to expand Arith f4e2m1 patterns to lower level bitcasts/shifts.
void populateArithExpandOpsPatterns(RewritePatternSet &patterns)
Add patterns to expand Arith ops.
int compare(const Fraction &x, const Fraction &y)
Three-way comparison between two fractions.
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
const FrozenRewritePatternSet & patterns
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...