17#include "mlir/IR/PatternMatch.h"
24#include "circt/Dialect/AIG/AIG.cpp.inc"
26OpFoldResult AndInverterOp::fold(FoldAdaptor adaptor) {
27 if (getNumOperands() == 1 && !isInverted(0))
32LogicalResult AndInverterOp::canonicalize(AndInverterOp op,
33 PatternRewriter &rewriter) {
35 SmallVector<Value> uniqueValues;
36 SmallVector<bool> uniqueInverts;
39 APInt::getAllOnes(op.getResult().getType().getIntOrFloatBitWidth());
41 bool invertedConstFound =
false;
42 bool flippedFound =
false;
44 for (
auto [value, inverted] :
llvm::zip(op.getInputs(), op.getInverted())) {
45 bool newInverted = inverted;
48 constValue &= ~constOp.getValue();
49 invertedConstFound =
true;
51 constValue &= constOp.getValue();
56 if (
auto andInverterOp = value.getDefiningOp<aig::AndInverterOp>()) {
57 if (andInverterOp.getInputs().size() == 1 &&
58 andInverterOp.isInverted(0)) {
59 value = andInverterOp.getOperand(0);
60 newInverted = andInverterOp.isInverted(0) ^ inverted;
65 auto it = seen.find(value);
66 if (it == seen.end()) {
67 seen.insert({value, newInverted});
68 uniqueValues.push_back(value);
69 uniqueInverts.push_back(newInverted);
70 }
else if (it->second != newInverted) {
73 op, APInt::getZero(value.getType().getIntOrFloatBitWidth()));
79 if (constValue.isZero()) {
85 if ((uniqueValues.size() == op.getInputs().size() && !flippedFound) ||
86 (!constValue.isAllOnes() && !invertedConstFound &&
87 uniqueValues.size() + 1 == op.getInputs().size()))
90 if (!constValue.isAllOnes()) {
92 uniqueInverts.push_back(
false);
93 uniqueValues.push_back(constOp);
97 if (uniqueValues.empty()) {
103 replaceOpWithNewOpAndCopyNamehint<aig::AndInverterOp>(
104 rewriter, op, uniqueValues, uniqueInverts);
108APInt AndInverterOp::evaluate(ArrayRef<APInt> inputs) {
109 assert(inputs.size() == getNumOperands() &&
110 "Expected as many inputs as operands");
111 assert(!inputs.empty() &&
"Expected non-empty input list");
112 APInt result = APInt::getAllOnes(inputs.front().getBitWidth());
113 for (
auto [idx, input] :
llvm::enumerate(inputs)) {
123 OperandRange operands,
124 ArrayRef<bool> inverts,
125 PatternRewriter &rewriter) {
127 switch (operands.size()) {
129 assert(0 &&
"cannot be called with empty operand range");
133 return AndInverterOp::create(rewriter, op.getLoc(), operands[0],
true);
137 return AndInverterOp::create(rewriter, op.getLoc(), operands[0],
138 operands[1], inverts[0], inverts[1]);
140 auto firstHalf = operands.size() / 2;
143 inverts.take_front(firstHalf), rewriter);
146 inverts.drop_front(firstHalf), rewriter);
147 return AndInverterOp::create(rewriter, op.getLoc(), lhs, rhs);
154 aig::AndInverterOp op, PatternRewriter &rewriter)
const {
155 if (op.getInputs().size() <= 2)
162 op, op.getOperands(), op.getInverted(), rewriter));
static Value lowerVariadicAndInverterOp(aig::AndInverterOp op, OperandRange operands, ArrayRef< bool > inverts, PatternRewriter &rewriter)
assert(baseType &&"element must be base type")
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
mlir::LogicalResult matchAndRewrite(circt::aig::AndInverterOp op, mlir::PatternRewriter &rewriter) const override