37 LogicalResult matchAndRewrite(math::PowFOp op,
38 PatternRewriter &rewriter)
const final;
43PowFStrengthReduction::matchAndRewrite(math::PowFOp op,
45 Location loc = op.getLoc();
46 Value x = op.getLhs();
47 arith::FastMathFlags fmf = op.getFastmathAttr().getValue();
49 FloatAttr scalarExponent;
50 DenseFPElementsAttr vectorExponent;
56 auto isExponentValue = [&](
double value) ->
bool {
58 return scalarExponent.getValue().isExactlyValue(value);
60 if (isVector && vectorExponent.isSplat())
61 return vectorExponent.getSplatValue<FloatAttr>()
63 .isExactlyValue(value);
69 auto bcast = [&](Value value) -> Value {
70 if (
auto vec = dyn_cast<VectorType>(op.getType()))
71 return vector::BroadcastOp::create(rewriter, loc, vec, value);
76 if (isExponentValue(1.0)) {
82 if (isExponentValue(2.0)) {
88 if (isExponentValue(3.0)) {
89 Value square = arith::MulFOp::create(rewriter, loc, x, x, fmf);
95 if (isExponentValue(-1.0)) {
96 Value one = arith::ConstantOp::create(
104 if (isExponentValue(0.5)) {
110 if (isExponentValue(-0.5)) {
116 if (isExponentValue(0.75)) {
117 Value powHalf = math::SqrtOp::create(rewriter, loc, x, fmf);
118 Value powQuarter = math::SqrtOp::create(rewriter, loc, powHalf, fmf);
131template <
typename PowIOpTy,
typename DivOpTy,
typename MulOpTy>
132struct PowIStrengthReduction :
public OpRewritePattern<PowIOpTy> {
134 unsigned exponentThreshold;
137 PowIStrengthReduction(MLIRContext *context,
unsigned exponentThreshold = 3,
138 PatternBenefit benefit = 1,
139 ArrayRef<StringRef> generatedNames = {})
140 : OpRewritePattern<PowIOpTy>(context, benefit, generatedNames),
141 exponentThreshold(exponentThreshold) {}
143 LogicalResult matchAndRewrite(PowIOpTy op,
144 PatternRewriter &rewriter)
const final;
148template <
typename PowIOpTy,
typename DivOpTy,
typename MulOpTy>
150PowIStrengthReduction<PowIOpTy, DivOpTy, MulOpTy>::matchAndRewrite(
151 PowIOpTy op, PatternRewriter &rewriter)
const {
152 Location loc = op.getLoc();
153 Value base = op.getLhs();
155 IntegerAttr scalarExponent;
156 DenseIntElementsAttr vectorExponent;
162 int64_t exponentValue = 0;
164 exponentValue = scalarExponent.getInt();
165 else if (isVector && vectorExponent.isSplat())
166 exponentValue = vectorExponent.getSplatValue<IntegerAttr>().getInt();
172 bool exponentIsNegative =
false;
173 if (exponentValue < 0) {
174 exponentIsNegative =
true;
181 if constexpr (std::is_same_v<PowIOpTy, math::IPowIOp>)
187 if (exponentValue == std::numeric_limits<int64_t>::min())
193 if (exponentValue != 0 && exponentValue > exponentThreshold)
197 auto bcast = [&loc, &op, &rewriter](Value value) -> Value {
198 if (
auto vec = dyn_cast<VectorType>(op.getType()))
199 return vector::BroadcastOp::create(rewriter, loc, vec, value);
205 if constexpr (std::is_same_v<PowIOpTy, math::FPowIOp>) {
206 one = arith::ConstantOp::create(rewriter, loc,
208 }
else if constexpr (std::is_same_v<PowIOpTy, complex::PowiOp>) {
209 auto complexTy = cast<ComplexType>(opType);
210 Type elementType = complexTy.getElementType();
211 auto realPart = rewriter.
getFloatAttr(elementType, 1.0);
212 auto imagPart = rewriter.
getFloatAttr(elementType, 0.0);
213 one = complex::ConstantOp::create(
214 rewriter, loc, complexTy, rewriter.
getArrayAttr({realPart, imagPart}));
216 one = arith::ConstantOp::create(rewriter, loc,
221 if (exponentValue == 0) {
236 auto buildMul = [&](Value
lhs, Value
rhs) {
237 if constexpr (std::is_same_v<PowIOpTy, complex::PowiOp>)
238 return MulOpTy::create(rewriter, loc, op.getType(),
lhs,
rhs,
239 op.getFastmathAttr());
241 return MulOpTy::create(rewriter, loc,
lhs,
rhs);
243 for (
unsigned i = 1; i < exponentValue; ++i)
248 if (exponentIsNegative) {
249 if constexpr (std::is_same_v<PowIOpTy, complex::PowiOp>)
250 result = DivOpTy::create(rewriter, loc, op.getType(), bcast(one),
result,
251 op.getFastmathAttr());
253 result = DivOpTy::create(rewriter, loc, bcast(one),
result);
267template <
typename ExpOpTy>
268struct ExpQuotientStrengthReduction :
public OpRewritePattern<arith::DivFOp> {
272 LogicalResult matchAndRewrite(arith::DivFOp op,
273 PatternRewriter &rewriter)
const final {
274 auto numerator = op.getLhs().getDefiningOp<ExpOpTy>();
275 auto denominator = op.getRhs().getDefiningOp<ExpOpTy>();
276 if (!numerator || !denominator)
287 arith::FastMathFlags fmf = op.getFastmath();
288 if (!bitEnumContainsAll(fmf, arith::FastMathFlags::arcp |
289 arith::FastMathFlags::reassoc))
297 Operation *divOp = op;
298 auto diesWithDivision = [divOp](Operation *exp) {
299 return llvm::all_of(exp->getUsers(),
300 [divOp](Operation *user) { return user == divOp; });
302 if (!diesWithDivision(numerator) && !diesWithDivision(denominator))
316 constexpr arith::FastMathFlags valueAssumptions =
317 arith::FastMathFlags::nnan | arith::FastMathFlags::ninf;
320 arith::FastMathFlags subFmf = bitEnumClear(fmf, valueAssumptions);
324 arith::FastMathFlags expFmf = bitEnumClear(
325 numerator.getFastmath() & denominator.getFastmath(), valueAssumptions);
328 arith::SubFOp::create(rewriter, op.getLoc(), numerator.getOperand(),
329 denominator.getOperand(), subFmf);
341 PowFStrengthReduction,
342 PowIStrengthReduction<math::IPowIOp, arith::DivSIOp, arith::MulIOp>,
343 PowIStrengthReduction<math::FPowIOp, arith::DivFOp, arith::MulFOp>,
344 PowIStrengthReduction<complex::PowiOp, complex::DivOp, complex::MulOp>>(
346 patterns.
add<ExpQuotientStrengthReduction<math::ExpOp>,
347 ExpQuotientStrengthReduction<math::Exp2Op>>(
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
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...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
void populateMathAlgebraicSimplificationPatterns(RewritePatternSet &patterns)
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...