19#include "mlir/IR/Builders.h"
20#include "mlir/IR/PatternMatch.h"
21#include "mlir/Transforms/DialectConversion.h"
37 SmallVector<Value> result;
38 for (
const auto &vals : values)
39 llvm::append_range(result, vals);
45class PruneTypeConverter :
public mlir::TypeConverter {
47 PruneTypeConverter() {
48 addConversion([&](Type type, SmallVectorImpl<Type> &results) {
50 results.push_back(type);
56template <
typename TOp>
64 matchAndRewrite(TOp op, OneToNOpAdaptor adaptor,
65 ConversionPatternRewriter &rewriter)
const override {
66 SmallVector<Value> flattenedOperands =
flattenValues(adaptor.getOperands());
71 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
80template <
typename... TOp>
81static void addNoI0OperandsLegalizationPattern(ConversionTarget &target) {
82 target.addDynamicallyLegalOp<TOp...>(
87struct NoI0OperandsConversionPattern<
comb::ICmpOp>
92 using OneToNOpAdaptor =
100 case circt::comb::ICmpPredicate::eq:
101 case circt::comb::ICmpPredicate::sle:
102 case circt::comb::ICmpPredicate::sge:
103 case circt::comb::ICmpPredicate::ule:
104 case circt::comb::ICmpPredicate::uge:
105 case circt::comb::ICmpPredicate::ceq:
106 case circt::comb::ICmpPredicate::weq:
108 case circt::comb::ICmpPredicate::ne:
109 case circt::comb::ICmpPredicate::slt:
110 case circt::comb::ICmpPredicate::sgt:
111 case circt::comb::ICmpPredicate::ult:
112 case circt::comb::ICmpPredicate::ugt:
113 case circt::comb::ICmpPredicate::cne:
114 case circt::comb::ICmpPredicate::wne:
117 llvm_unreachable(
"unknown comparison predicate");
121 matchAndRewrite(comb::ICmpOp op, OneToNOpAdaptor adaptor,
122 ConversionPatternRewriter &rewriter)
const override {
130 op, APInt(1, result,
false));
136struct NoI0OperandsConversionPattern<
comb::ParityOp>
141 using OneToNOpAdaptor =
146 ConversionPatternRewriter &rewriter)
const override {
147 SmallVector<Value> flattenedOperands =
flattenValues(adaptor.getOperands());
148 if (!flattenedOperands.empty() &&
noI0TypedValue(flattenedOperands))
153 op, APInt(1, 0,
false));
159struct NoI0OperandsConversionPattern<
comb::ConcatOp>
164 using OneToNOpAdaptor =
169 ConversionPatternRewriter &rewriter)
const override {
171 if (op.getType().isInteger(0)) {
173 op, APInt(1, 0,
false));
177 SmallVector<Value> materializedOperands =
184 if (materializedOperands.size() == adaptor.getOperands().size())
188 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, materializedOperands);
196template <
typename TOp>
197struct NoI0OperandPruningPattern {
198 using ConversionPattern = NoI0OperandsConversionPattern<TOp>;
199 static void addLegalizer(ConversionTarget &target) {
200 addNoI0OperandsLegalizationPattern<TOp>(target);
207template <
typename TOp>
214 matchAndRewrite(TOp op, OneToNOpAdaptor adaptor,
215 ConversionPatternRewriter &rewriter)
const override {
220 assert(op->getNumResults() == 1 &&
221 "expected single result if using rewriter.replaceOpWith");
223 op, APInt(0, 0,
false));
228template <
typename... TOp>
229static void addNoI0ResultsLegalizationPattern(ConversionTarget &target) {
230 target.addDynamicallyLegalOp<TOp...>(
236template <
typename TOp>
237struct NoI0ResultPruningPattern {
238 using ConversionPattern = NoI0ResultsConversionPattern<TOp>;
239 static void addLegalizer(ConversionTarget &target) {
240 addNoI0ResultsLegalizationPattern<TOp>(target);
246template <
typename... TPattern>
247static void addPruningPattern(ConversionTarget &target,
249 PruneTypeConverter &typeConverter) {
250 (
patterns.add<
typename TPattern::ConversionPattern>(typeConverter,
253 (TPattern::addLegalizer(target), ...);
256template <
typename... TOp>
257static void addNoI0ResultPruningPattern(ConversionTarget &target,
259 PruneTypeConverter &typeConverter) {
260 (
patterns.add<
typename NoI0ResultPruningPattern<TOp>::ConversionPattern>(
261 typeConverter,
patterns.getContext()),
263 (NoI0ResultPruningPattern<TOp>::addLegalizer(target), ...);
269 ConversionTarget target(*module->getContext());
270 RewritePatternSet
patterns(module->getContext());
271 PruneTypeConverter typeConverter;
273 target.addLegalDialect<sv::SVDialect, comb::CombDialect, hw::HWDialect>();
274 addPruningPattern<NoI0OperandPruningPattern<sv::PAssignOp>,
275 NoI0OperandPruningPattern<sv::BPAssignOp>,
276 NoI0OperandPruningPattern<sv::AssignOp>,
277 NoI0OperandPruningPattern<comb::ICmpOp>,
278 NoI0OperandPruningPattern<comb::ParityOp>,
279 NoI0OperandPruningPattern<comb::ConcatOp>>(target,
patterns,
282 addNoI0ResultPruningPattern<
291 (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.