17#include "mlir/Dialect/Arith/IR/Arith.h"
18#include "mlir/Pass/Pass.h"
19#include "mlir/Transforms/DialectConversion.h"
22#define GEN_PASS_DEF_MAPARITHTOCOMBPASS
23#include "circt/Transforms/Passes.h.inc"
33class MapArithTypeConverter :
public mlir::TypeConverter {
35 MapArithTypeConverter() {
36 addConversion([](Type type) {
37 if (hw::isHWValueType(type))
45template <
typename TFrom,
typename TTo>
48 using OpConversionPattern<TFrom>::OpConversionPattern;
49 using OpAdaptor =
typename TFrom::Adaptor;
52 matchAndRewrite(TFrom op, OpAdaptor adaptor,
53 ConversionPatternRewriter &rewriter)
const override {
54 typename TTo::Properties properties{};
55 TTo::populateDefaultProperties(
56 OperationName(TTo::getOperationName(), rewriter.getContext()),
59 TTo::create(rewriter, op.getLoc(), adaptor.getOperands(), properties);
60 rewriter.replaceOp(op, newOp);
67 using OpConversionPattern<arith::ExtSIOp>::OpConversionPattern;
68 using OpAdaptor =
typename arith::ExtSIOp::Adaptor;
71 matchAndRewrite(arith::ExtSIOp op, OpAdaptor adaptor,
72 ConversionPatternRewriter &rewriter)
const override {
73 size_t outWidth = op.getType().getIntOrFloatBitWidth();
75 op, comb::createOrFoldSExt(rewriter, op.getLoc(), op.getOperand(),
76 rewriter.getIntegerType(outWidth)));
83 using OpConversionPattern<arith::ExtUIOp>::OpConversionPattern;
84 using OpAdaptor =
typename arith::ExtUIOp::Adaptor;
87 matchAndRewrite(arith::ExtUIOp op, OpAdaptor adaptor,
88 ConversionPatternRewriter &rewriter)
const override {
89 auto loc = op.getLoc();
90 size_t outWidth = op.getOut().getType().getIntOrFloatBitWidth();
91 size_t inWidth = adaptor.getIn().getType().getIntOrFloatBitWidth();
93 rewriter.replaceOp(op, comb::ConcatOp::create(
96 rewriter, loc, APInt(outWidth - inWidth, 0)),
104 using OpConversionPattern<arith::TruncIOp>::OpConversionPattern;
105 using OpAdaptor =
typename arith::TruncIOp::Adaptor;
108 matchAndRewrite(arith::TruncIOp op, OpAdaptor adaptor,
109 ConversionPatternRewriter &rewriter)
const override {
110 size_t outWidth = op.getType().getIntOrFloatBitWidth();
111 rewriter.replaceOpWithNewOp<comb::ExtractOp>(op, adaptor.getIn(), 0,
119 using OpConversionPattern<arith::CmpIOp>::OpConversionPattern;
120 using OpAdaptor =
typename arith::CmpIOp::Adaptor;
122 static comb::ICmpPredicate
123 arithToCombPredicate(arith::CmpIPredicate predicate) {
125 case arith::CmpIPredicate::eq:
126 return comb::ICmpPredicate::eq;
127 case arith::CmpIPredicate::ne:
128 return comb::ICmpPredicate::ne;
129 case arith::CmpIPredicate::slt:
130 return comb::ICmpPredicate::slt;
131 case arith::CmpIPredicate::ult:
132 return comb::ICmpPredicate::ult;
133 case arith::CmpIPredicate::sle:
134 return comb::ICmpPredicate::sle;
135 case arith::CmpIPredicate::ule:
136 return comb::ICmpPredicate::ule;
137 case arith::CmpIPredicate::sgt:
138 return comb::ICmpPredicate::sgt;
139 case arith::CmpIPredicate::ugt:
140 return comb::ICmpPredicate::ugt;
141 case arith::CmpIPredicate::sge:
142 return comb::ICmpPredicate::sge;
143 case arith::CmpIPredicate::uge:
144 return comb::ICmpPredicate::uge;
146 llvm_unreachable(
"Unknown predicate");
150 matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,
151 ConversionPatternRewriter &rewriter)
const override {
152 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
153 op, arithToCombPredicate(op.getPredicate()), adaptor.getLhs(),
159struct ConstantConversionPattern
161 using OpConversionPattern::OpConversionPattern;
164 matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,
165 ConversionPatternRewriter &rewriter)
const override {
167 if (!isa<IntegerType>(op.getType()))
170 rewriter.replaceOpWithNewOp<hw::ConstantOp>(
171 op, cast<IntegerAttr>(adaptor.getValue()));
178template <
typename ArithOp, comb::ICmpPredicate pred>
181 using OpConversionPattern<ArithOp>::OpConversionPattern;
182 using OpAdaptor =
typename ArithOp::Adaptor;
185 matchAndRewrite(ArithOp op, OpAdaptor adaptor,
186 ConversionPatternRewriter &rewriter)
const override {
189 auto cmp = comb::ICmpOp::create(rewriter, op.getLoc(), pred,
190 adaptor.getLhs(), adaptor.getRhs());
191 rewriter.replaceOpWithNewOp<comb::MuxOp>(op, cmp, adaptor.getLhs(),
197struct MapArithToCombPass
198 :
public circt::impl::MapArithToCombPassBase<MapArithToCombPass> {
200 MapArithToCombPass(
bool enableBestEffortLowering) {
201 this->enableBestEffortLowering = enableBestEffortLowering;
204 void runOnOperation()
override {
205 auto *ctx = &getContext();
207 ConversionTarget target(*ctx);
208 target.addLegalDialect<comb::CombDialect, hw::HWDialect>();
209 if (!enableBestEffortLowering) {
210 target.addIllegalDialect<arith::ArithDialect>();
214 target.addIllegalOp<arith::AddIOp>();
215 target.addIllegalOp<arith::SubIOp>();
216 target.addIllegalOp<arith::MulIOp>();
217 target.addIllegalOp<arith::DivSIOp>();
218 target.addIllegalOp<arith::DivUIOp>();
219 target.addIllegalOp<arith::RemSIOp>();
220 target.addIllegalOp<arith::RemUIOp>();
221 target.addIllegalOp<arith::AndIOp>();
222 target.addIllegalOp<arith::OrIOp>();
223 target.addIllegalOp<arith::XOrIOp>();
224 target.addIllegalOp<arith::ShLIOp>();
225 target.addIllegalOp<arith::ShRSIOp>();
226 target.addIllegalOp<arith::ShRUIOp>();
227 target.addIllegalOp<arith::ExtSIOp>();
228 target.addIllegalOp<arith::ExtUIOp>();
229 target.addIllegalOp<arith::TruncIOp>();
230 target.addIllegalOp<arith::CmpIOp>();
231 target.addIllegalOp<arith::MaxSIOp>();
232 target.addIllegalOp<arith::MaxUIOp>();
233 target.addIllegalOp<arith::MinSIOp>();
234 target.addIllegalOp<arith::MinUIOp>();
237 target.addDynamicallyLegalOp<arith::ConstantOp>([](Operation *op) {
238 return !isa<IntegerType>(op->getResult(0).getType());
241 target.addDynamicallyLegalOp<arith::SelectOp>(
242 [](arith::SelectOp op) {
return !hw::isHWValueType(op.getType()); });
244 MapArithTypeConverter typeConverter;
245 RewritePatternSet patterns(ctx);
248 if (failed(applyPartialConversion(getOperation(), target,
249 std::move(patterns))))
257 TypeConverter &typeConverter) {
259 OneToOnePattern<arith::AddIOp, comb::AddOp>,
260 OneToOnePattern<arith::SubIOp, comb::SubOp>,
261 OneToOnePattern<arith::MulIOp, comb::MulOp>,
262 OneToOnePattern<arith::DivSIOp, comb::DivSOp>,
263 OneToOnePattern<arith::DivUIOp, comb::DivUOp>,
264 OneToOnePattern<arith::RemSIOp, comb::ModSOp>,
265 OneToOnePattern<arith::RemUIOp, comb::ModUOp>,
266 OneToOnePattern<arith::AndIOp, comb::AndOp>,
267 OneToOnePattern<arith::OrIOp, comb::OrOp>,
268 OneToOnePattern<arith::XOrIOp, comb::XorOp>,
269 OneToOnePattern<arith::ShLIOp, comb::ShlOp>,
270 OneToOnePattern<arith::ShRSIOp, comb::ShrSOp>,
271 OneToOnePattern<arith::ShRUIOp, comb::ShrUOp>,
272 OneToOnePattern<arith::SelectOp, comb::MuxOp>,
273 MinMaxConversionPattern<arith::MaxSIOp, comb::ICmpPredicate::sge>,
274 MinMaxConversionPattern<arith::MaxUIOp, comb::ICmpPredicate::uge>,
275 MinMaxConversionPattern<arith::MinSIOp, comb::ICmpPredicate::sle>,
276 MinMaxConversionPattern<arith::MinUIOp, comb::ICmpPredicate::ule>,
277 ExtSConversionPattern, ExtZConversionPattern, TruncateConversionPattern,
278 CompConversionPattern, ConstantConversionPattern>(typeConverter,
282std::unique_ptr<mlir::Pass>
284 return std::make_unique<MapArithToCombPass>(enableBestEffortLowering);
false return failure()
Parse an optional keyword or string and set instance into 'result'.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createMapArithToCombPass(bool enableBestEffortLowering=false)
void populateArithToCombPatterns(mlir::RewritePatternSet &patterns, TypeConverter &typeConverter)