18 #include "mlir/IR/Builders.h"
19 #include "mlir/IR/PatternMatch.h"
20 #include "mlir/Transforms/DialectConversion.h"
24 using namespace circt;
38 SmallVector<Value> result;
39 for (
const auto &vals : values)
40 llvm::append_range(result, vals);
46 class PruneTypeConverter :
public mlir::TypeConverter {
48 PruneTypeConverter() {
49 addConversion([&](Type type, SmallVectorImpl<Type> &results) {
51 results.push_back(type);
57 template <
typename TOp>
65 matchAndRewrite(TOp op, OneToNOpAdaptor adaptor,
66 ConversionPatternRewriter &rewriter)
const override {
67 ValueRange flattenedOperands =
flattenValues(adaptor.getOperands());
72 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
81 template <
typename... TOp>
82 static void addNoI0OperandsLegalizationPattern(ConversionTarget &target) {
83 target.addDynamicallyLegalOp<TOp...>(
88 struct NoI0OperandsConversionPattern<
comb::ICmpOp>
93 using OneToNOpAdaptor =
101 case circt::comb::ICmpPredicate::eq:
102 case circt::comb::ICmpPredicate::sle:
103 case circt::comb::ICmpPredicate::sge:
104 case circt::comb::ICmpPredicate::ule:
105 case circt::comb::ICmpPredicate::uge:
106 case circt::comb::ICmpPredicate::ceq:
107 case circt::comb::ICmpPredicate::weq:
109 case circt::comb::ICmpPredicate::ne:
110 case circt::comb::ICmpPredicate::slt:
111 case circt::comb::ICmpPredicate::sgt:
112 case circt::comb::ICmpPredicate::ult:
113 case circt::comb::ICmpPredicate::ugt:
114 case circt::comb::ICmpPredicate::cne:
115 case circt::comb::ICmpPredicate::wne:
118 llvm_unreachable(
"unknown comparison predicate");
122 matchAndRewrite(comb::ICmpOp op, OneToNOpAdaptor adaptor,
123 ConversionPatternRewriter &rewriter)
const override {
131 op, APInt(1, result,
false));
137 struct NoI0OperandsConversionPattern<
comb::ParityOp>
142 using OneToNOpAdaptor =
147 ConversionPatternRewriter &rewriter)
const override {
148 ValueRange flattenedOperands =
flattenValues(adaptor.getOperands());
149 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
154 op, APInt(1, 0,
false));
160 struct NoI0OperandsConversionPattern<
comb::ConcatOp>
165 using OneToNOpAdaptor =
170 ConversionPatternRewriter &rewriter)
const override {
172 if (op.getType().isInteger(0)) {
174 op, APInt(1, 0,
false));
178 SmallVector<Value> materializedOperands =
185 if (materializedOperands.size() == adaptor.getOperands().size())
189 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, materializedOperands);
197 template <
typename TOp>
198 struct NoI0OperandPruningPattern {
199 using ConversionPattern = NoI0OperandsConversionPattern<TOp>;
200 static void addLegalizer(ConversionTarget &target) {
201 addNoI0OperandsLegalizationPattern<TOp>(target);
208 template <
typename TOp>
215 matchAndRewrite(TOp op, OneToNOpAdaptor adaptor,
216 ConversionPatternRewriter &rewriter)
const override {
221 assert(op->getNumResults() == 1 &&
222 "expected single result if using rewriter.replaceOpWith");
224 op, APInt(0, 0,
false));
229 template <
typename... TOp>
230 static void addNoI0ResultsLegalizationPattern(ConversionTarget &target) {
231 target.addDynamicallyLegalOp<TOp...>(
237 template <
typename TOp>
238 struct NoI0ResultPruningPattern {
239 using ConversionPattern = NoI0ResultsConversionPattern<TOp>;
240 static void addLegalizer(ConversionTarget &target) {
241 addNoI0ResultsLegalizationPattern<TOp>(target);
247 template <
typename... TPattern>
248 static void addPruningPattern(ConversionTarget &target,
250 PruneTypeConverter &typeConverter) {
251 (
patterns.add<
typename TPattern::ConversionPattern>(typeConverter,
254 (TPattern::addLegalizer(target), ...);
257 template <
typename... TOp>
258 static void addNoI0ResultPruningPattern(ConversionTarget &target,
260 PruneTypeConverter &typeConverter) {
261 (
patterns.add<
typename NoI0ResultPruningPattern<TOp>::ConversionPattern>(
262 typeConverter,
patterns.getContext()),
264 (NoI0ResultPruningPattern<TOp>::addLegalizer(target), ...);
270 ConversionTarget target(*module->getContext());
271 RewritePatternSet
patterns(module->getContext());
272 PruneTypeConverter typeConverter;
274 target.addLegalDialect<sv::SVDialect, comb::CombDialect, hw::HWDialect>();
275 addPruningPattern<NoI0OperandPruningPattern<sv::PAssignOp>,
276 NoI0OperandPruningPattern<sv::BPAssignOp>,
277 NoI0OperandPruningPattern<sv::AssignOp>,
278 NoI0OperandPruningPattern<comb::ICmpOp>,
279 NoI0OperandPruningPattern<comb::ParityOp>,
280 NoI0OperandPruningPattern<comb::ConcatOp>>(target,
patterns,
283 addNoI0ResultPruningPattern<
292 (void)applyPartialConversion(module, target, std::move(
patterns));
assert(baseType &&"element must be base type")
static bool applyCmpPredicateToEqualOperands(ICmpPredicate predicate)
static bool noI0TypedValue(ValueRange values)
static SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten the given value ranges into a single vector of values.
static bool noI0Type(TypeRange types)
void pruneZeroValuedLogic(hw::HWEmittableModuleLike module)
bool isZeroBitType(Type type)
Return true if this is a zero bit type, e.g.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.