MLIR 24.0.0git
CeilFloorDivExpansion.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13
14using namespace mlir;
15
16/// Create an integer or index constant.
17static Value createConst(Location loc, Type type, int value,
18 PatternRewriter &rewriter) {
19 auto attr = rewriter.getIntegerAttr(getElementTypeOrSelf(type), value);
20 if (auto shapedTy = dyn_cast<ShapedType>(type)) {
21 return arith::ConstantOp::create(rewriter, loc,
22 DenseElementsAttr::get(shapedTy, attr));
23 }
24 return arith::ConstantOp::create(rewriter, loc, attr);
25}
26
27namespace {
28/// Expands CeilDivUIOp (n, m) into
29/// n == 0 ? 0 : ((n-1) / m) + 1
30struct CeilDivUIOpConverter : public OpRewritePattern<arith::CeilDivUIOp> {
31 using Base::Base;
32 LogicalResult matchAndRewrite(arith::CeilDivUIOp op,
33 PatternRewriter &rewriter) const final {
34 Location loc = op.getLoc();
35 Value a = op.getLhs();
36 Value b = op.getRhs();
37 Value zero = createConst(loc, a.getType(), 0, rewriter);
38 Value compare =
39 arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::eq, a, zero);
40 Value one = createConst(loc, a.getType(), 1, rewriter);
41 Value minusOne = arith::SubIOp::create(rewriter, loc, a, one);
42 Value quotient = arith::DivUIOp::create(rewriter, loc, minusOne, b);
43 Value plusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
44 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, compare, zero, plusOne);
45 return success();
46 }
47};
48
49/// Expands CeilDivSIOp (a, b) into
50/// z = a / b
51/// if (z * b != a && (a < 0) == (b < 0)) {
52/// return z + 1;
53/// } else {
54/// return z;
55/// }
56struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> {
57 using Base::Base;
58 LogicalResult matchAndRewrite(arith::CeilDivSIOp op,
59 PatternRewriter &rewriter) const final {
60 Location loc = op.getLoc();
61 Type type = op.getType();
62 Value a = op.getLhs();
63 Value b = op.getRhs();
64
65 Value zero = createConst(loc, type, 0, rewriter);
66 Value one = createConst(loc, type, 1, rewriter);
67
68 Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
69 Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
70 Value notEqualDivisor = arith::CmpIOp::create(
71 rewriter, loc, arith::CmpIPredicate::ne, a, product);
72
73 Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
74 a, zero);
75 Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
76 b, zero);
77
78 Value signEqual = arith::CmpIOp::create(
79 rewriter, loc, arith::CmpIPredicate::eq, aNeg, bNeg);
80 Value cond =
81 arith::AndIOp::create(rewriter, loc, notEqualDivisor, signEqual);
82
83 Value quotientPlusOne = arith::AddIOp::create(rewriter, loc, quotient, one);
84
85 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientPlusOne,
86 quotient);
87 return success();
88 }
89};
90
91/// Expands FloorDivSIOp (x, y) into
92/// z = x / y
93/// if (z * y != x && (x < 0) != (y < 0)) {
94/// return z - 1;
95/// } else {
96/// return z;
97/// }
98struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> {
99 using Base::Base;
100 LogicalResult matchAndRewrite(arith::FloorDivSIOp op,
101 PatternRewriter &rewriter) const final {
102 Location loc = op.getLoc();
103 Type type = op.getType();
104 Value a = op.getLhs();
105 Value b = op.getRhs();
106
107 Value quotient = arith::DivSIOp::create(rewriter, loc, a, b);
108 Value product = arith::MulIOp::create(rewriter, loc, quotient, b);
109 Value notEqualDivisor = arith::CmpIOp::create(
110 rewriter, loc, arith::CmpIPredicate::ne, a, product);
111 Value zero = createConst(loc, type, 0, rewriter);
112
113 Value aNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
114 a, zero);
115 Value bNeg = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
116 b, zero);
117
118 Value signOpposite = arith::CmpIOp::create(
119 rewriter, loc, arith::CmpIPredicate::ne, aNeg, bNeg);
120 Value cond =
121 arith::AndIOp::create(rewriter, loc, notEqualDivisor, signOpposite);
122
123 Value minusOne = createConst(loc, type, -1, rewriter);
124 Value quotientMinusOne =
125 arith::AddIOp::create(rewriter, loc, quotient, minusOne);
126
127 rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne,
128 quotient);
129 return success();
130 }
131};
132} // namespace
133
135 RewritePatternSet &patterns) {
136 patterns
137 .add<CeilDivSIOpConverter, CeilDivUIOpConverter, FloorDivSIOpConverter>(
138 patterns.getContext());
139}
return success()
static Value createConst(Location loc, Type type, int value, PatternRewriter &rewriter)
Create an integer or index constant.
static int64_t product(ArrayRef< int64_t > vals)
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition Builders.cpp:237
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...
Definition Location.h:76
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.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
void populateCeilFloorDivExpandOpsPatterns(RewritePatternSet &patterns)
int compare(const Fraction &x, const Fraction &y)
Three-way comparison between two fractions.
Definition Fraction.h:68
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...