CIRCT 22.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 if (numInputs <= 1)
56 return failure();
57
58 // Check if all table entries are the same (constant output)
59 bool allSame = llvm::all_equal(table);
60 if (allSame) {
61 bool firstValue = table[0];
62 auto constOp =
63 hw::ConstantOp::create(rewriter, op.getLoc(), APInt(1, firstValue));
64 replaceOpAndCopyNamehint(rewriter, op, constOp);
65 return success();
66 }
67
68 // Convert truth table to APInt for cofactor computation
69 APInt truthTable(table.size(), 0);
70 for (size_t i = 0; i < table.size(); ++i)
71 truthTable.setBitVal(i, table[i]);
72
73 // Use cofactors to detect which inputs the function depends on
74 // A function depends on variable i if its cofactors differ
75 // The cofactor function uses bit position indexing (LSB=0),
76 // but inputs are indexed with input 0 being the MSB in the truth table
77 int dependentInput = -1;
78 unsigned numDependencies = 0;
79 APInt negativeCofactor, positiveCofactor;
80
81 for (size_t bitPos = 0; bitPos < numInputs; ++bitPos) {
82 std::tie(negativeCofactor, positiveCofactor) =
83 computeCofactors(truthTable, numInputs, bitPos);
84
85 // If cofactors differ, the function depends on this variable
86 if (negativeCofactor != positiveCofactor) {
87 // Convert bit position to input index: bitPos 0 (LSB) = last input
88 dependentInput = numInputs - 1 - bitPos;
89 numDependencies++;
90
91 // Exit early if we found more than one dependency
92 if (numDependencies > 1)
93 break;
94 }
95 }
96
97 // Only simplify if exactly one input dependency found
98 if (numDependencies != 1)
99 return failure();
100
101 // Determine if the truth table is identity or inverted
102 // Check the output when the dependent input is 1 (all other inputs at 0)
103 size_t bitPositionInTable = numInputs - 1 - dependentInput;
104 size_t idxWhen1 = 1ull << bitPositionInTable;
105 bool isIdentity = table[idxWhen1];
106
107 // Replace with the input or a simpler truth table for negation
108 Value input = inputs[dependentInput];
109 if (isIdentity) {
110 // Identity case: just replace with the input directly
111 replaceOpAndCopyNamehint(rewriter, op, input);
112 } else {
113 // Inverted case: replace with a single-input truth table for negation
114 // This avoids introducing comb.xor, which is useful for LUT mapping
115 replaceOpWithNewOpAndCopyNamehint<TruthTableOp>(
116 rewriter, op, ValueRange{input}, ArrayRef<bool>{true, false});
117 }
118 return success();
119 }
120};
121
122class SimplifyTruthTablePass
123 : public impl::SimplifyTruthTableBase<SimplifyTruthTablePass> {
124public:
125 using SimplifyTruthTableBase::SimplifyTruthTableBase;
126 void runOnOperation() override;
127};
128
129} // namespace
130
131void SimplifyTruthTablePass::runOnOperation() {
132 Operation *op = getOperation();
133 MLIRContext *context = op->getContext();
134 RewritePatternSet patterns(context);
135 patterns.add<SimplifyTruthTable>(context);
136 walkAndApplyPatterns(op, std::move(patterns));
137}
static bool isOpTriviallyRecursive(Operation *op)
Definition CombFolds.cpp:27
static std::unique_ptr< Context > context
create(data_type, value)
Definition hw.py:433
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
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