18#include "mlir/IR/Builders.h"
19#include "mlir/IR/PatternMatch.h"
20#include "mlir/Transforms/DialectConversion.h"
38 SmallVector<Value> result;
39 for (
const auto &vals : values)
40 llvm::append_range(result, vals);
46class PruneTypeConverter :
public mlir::TypeConverter {
48 PruneTypeConverter() {
49 addConversion([&](Type type, SmallVectorImpl<Type> &results) {
51 results.push_back(type);
57template <
typename TOp>
65 matchAndRewrite(TOp op, OneToNOpAdaptor adaptor,
66 ConversionPatternRewriter &rewriter)
const override {
67 SmallVector<Value> flattenedOperands =
flattenValues(adaptor.getOperands());
72 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
81template <
typename... TOp>
82static void addNoI0OperandsLegalizationPattern(ConversionTarget &target) {
83 target.addDynamicallyLegalOp<TOp...>(
88struct 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));
137struct NoI0OperandsConversionPattern<
comb::ParityOp>
142 using OneToNOpAdaptor =
147 ConversionPatternRewriter &rewriter)
const override {
148 SmallVector<Value> flattenedOperands =
flattenValues(adaptor.getOperands());
149 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
154 op, APInt(1, 0,
false));
160struct 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);
197template <
typename TOp>
198struct NoI0OperandPruningPattern {
199 using ConversionPattern = NoI0OperandsConversionPattern<TOp>;
200 static void addLegalizer(ConversionTarget &target) {
201 addNoI0OperandsLegalizationPattern<TOp>(target);
208template <
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));
229template <
typename... TOp>
230static void addNoI0ResultsLegalizationPattern(ConversionTarget &target) {
231 target.addDynamicallyLegalOp<TOp...>(
237template <
typename TOp>
238struct NoI0ResultPruningPattern {
239 using ConversionPattern = NoI0ResultsConversionPattern<TOp>;
240 static void addLegalizer(ConversionTarget &target) {
241 addNoI0ResultsLegalizationPattern<TOp>(target);
247template <
typename... TPattern>
248static void addPruningPattern(ConversionTarget &target,
250 PruneTypeConverter &typeConverter) {
251 (
patterns.add<
typename TPattern::ConversionPattern>(typeConverter,
254 (TPattern::addLegalizer(target), ...);
257template <
typename... TOp>
258static 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 bool noI0Type(TypeRange types)
static SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten the given value ranges into a single vector of values.
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.