CIRCT 24.0.0git
Loading...
Searching...
No Matches
SimplifyTruthTable.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//
9// This file implements the SimplifyTruthTable pass, which simplifies truth
10// tables that depend on one or fewer inputs.
11//
12//===----------------------------------------------------------------------===//
13
19#include "mlir/IR/PatternMatch.h"
20#include "mlir/Transforms/WalkPatternRewriteDriver.h"
21#include "llvm/Support/LogicalResult.h"
22
23using namespace circt;
24using namespace comb;
25
26namespace circt {
27namespace comb {
28#define GEN_PASS_DEF_SIMPLIFYTRUTHTABLE
29#include "circt/Dialect/Comb/Passes.h.inc"
30} // namespace comb
31} // namespace circt
32
33namespace {
34
35// Helper to check if operation is trivially recursive
36static bool isOpTriviallyRecursive(Operation *op) {
37 return llvm::any_of(op->getOperands(), [op](auto operand) {
38 return operand.getDefiningOp() == op;
39 });
40}
41
42// Pattern to simplify truth tables
43struct SimplifyTruthTable : public OpRewritePattern<TruthTableOp> {
44 using OpRewritePattern::OpRewritePattern;
45
46 LogicalResult matchAndRewrite(TruthTableOp op,
47 PatternRewriter &rewriter) const override {
49 return failure();
50
51 const auto inputs = op.getInputs();
52 const auto table = op.getLookupTable();
53 size_t numInputs = inputs.size();
54
55 // Check if all table entries are the same (constant output)
56 bool allSame = llvm::all_equal(table);
57 if (allSame) {
58 bool firstValue = table[0];
59 auto constOp =
60 hw::ConstantOp::create(rewriter, op.getLoc(), APInt(1, firstValue));
61 replaceOpAndCopyNamehint(rewriter, op, constOp);
62 return success();
63 }
64
65 // Convert truth table to APInt for cofactor computation
66 APInt truthTable(table.size(), 0);
67 for (size_t i = 0; i < table.size(); ++i)
68 truthTable.setBitVal(i, table[i]);
69
70 // Use cofactors to detect which inputs the function depends on
71 // A function depends on variable i if its cofactors differ
72 // The cofactor function uses bit position indexing (LSB=0),
73 // but inputs are indexed with input 0 being the MSB in the truth table
74 int dependentInput = -1;
75 unsigned numDependencies = 0;
76 APInt negativeCofactor, positiveCofactor;
77
78 for (size_t bitPos = 0; bitPos < numInputs; ++bitPos) {
79 std::tie(negativeCofactor, positiveCofactor) =
80 computeCofactors(truthTable, numInputs, bitPos);
81
82 // If cofactors differ, the function depends on this variable
83 if (negativeCofactor != positiveCofactor) {
84 // Convert bit position to input index: bitPos 0 (LSB) = last input
85 dependentInput = numInputs - 1 - bitPos;
86 numDependencies++;
87
88 // Exit early if we found more than one dependency
89 if (numDependencies > 1)
90 break;
91 }
92 }
93
94 // Only simplify if exactly one input dependency found
95 if (numDependencies != 1)
96 return failure();
97
98 // Determine if the truth table is identity or inverted
99 // Check the output when the dependent input is 1 (all other inputs at 0)
100 size_t bitPositionInTable = numInputs - 1 - dependentInput;
101 size_t idxWhen1 = 1ull << bitPositionInTable;
102 bool isIdentity = table[idxWhen1];
103
104 // A single-input negation is already in its simplest form
105 if (!isIdentity && numInputs == 1)
106 return failure();
107
108 // Replace with the input or a simpler truth table for negation
109 Value input = inputs[dependentInput];
110 if (isIdentity) {
111 // Identity case: just replace with the input directly
112 replaceOpAndCopyNamehint(rewriter, op, input);
113 } else {
114 // Inverted case: replace with a single-input truth table for negation
115 // This avoids introducing comb.xor, which is useful for LUT mapping
117 rewriter, op, ValueRange{input}, ArrayRef<bool>{true, false});
118 }
119 return success();
120 }
121};
122
123class SimplifyTruthTablePass
124 : public impl::SimplifyTruthTableBase<SimplifyTruthTablePass> {
125public:
126 using SimplifyTruthTableBase::SimplifyTruthTableBase;
127 void runOnOperation() override;
128};
129
130} // namespace
131
132void SimplifyTruthTablePass::runOnOperation() {
133 Operation *op = getOperation();
134 MLIRContext *context = op->getContext();
135 RewritePatternSet patterns(context);
136 patterns.add<SimplifyTruthTable>(context);
137 walkAndApplyPatterns(op, std::move(patterns));
138}
static bool isOpTriviallyRecursive(Operation *op)
Definition CombFolds.cpp:29
static std::unique_ptr< Context > context
false return failure()
Parse an optional keyword or string and set instance into 'result'.
return success()
create(data_type, value)
Definition hw.py:433
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
static OpTy replaceOpWithNewOpAndCopyNamehint(PatternRewriter &rewriter, Operation *op, Args &&...args)
A wrapper of PatternRewriter::replaceOpWithNewOp to propagate "sv.namehint" attribute.
Definition Naming.h:41
void replaceOpAndCopyNamehint(PatternRewriter &rewriter, Operation *op, Value newValue)
A wrapper of PatternRewriter::replaceOp to propagate "sv.namehint" attribute.
Definition Naming.cpp:73
std::pair< llvm::APInt, llvm::APInt > computeCofactors(const llvm::APInt &f, unsigned numVars, unsigned varIndex)
Compute cofactor of a Boolean function for a given variable.
Definition comb.py:1