16#include "mlir/IR/PatternMatch.h"
23#include "circt/Dialect/AIG/AIG.cpp.inc"
25OpFoldResult AndInverterOp::fold(FoldAdaptor adaptor) {
26 if (getNumOperands() == 1 && !isInverted(0))
31LogicalResult AndInverterOp::canonicalize(AndInverterOp op,
32 PatternRewriter &rewriter) {
34 SmallVector<Value> uniqueValues;
35 SmallVector<bool> uniqueInverts;
38 APInt::getAllOnes(op.getResult().getType().getIntOrFloatBitWidth());
40 bool invertedConstFound =
false;
41 bool flippedFound =
false;
43 for (
auto [value, inverted] :
llvm::zip(op.getInputs(), op.getInverted())) {
44 bool newInverted = inverted;
47 constValue &= ~constOp.getValue();
48 invertedConstFound =
true;
50 constValue &= constOp.getValue();
55 if (
auto andInverterOp = value.getDefiningOp<aig::AndInverterOp>()) {
56 if (andInverterOp.getInputs().size() == 1 &&
57 andInverterOp.isInverted(0)) {
58 value = andInverterOp.getOperand(0);
59 newInverted = andInverterOp.isInverted(0) ^ inverted;
64 auto it = seen.find(value);
65 if (it == seen.end()) {
66 seen.insert({value, newInverted});
67 uniqueValues.push_back(value);
68 uniqueInverts.push_back(newInverted);
69 }
else if (it->second != newInverted) {
72 op, APInt::getZero(value.getType().getIntOrFloatBitWidth()));
78 if (constValue.isZero()) {
84 if ((uniqueValues.size() == op.getInputs().size() && !flippedFound) ||
85 (!constValue.isAllOnes() && !invertedConstFound &&
86 uniqueValues.size() + 1 == op.getInputs().size()))
89 if (!constValue.isAllOnes()) {
90 auto constOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), constValue);
91 uniqueInverts.push_back(
false);
92 uniqueValues.push_back(constOp);
96 if (uniqueValues.empty()) {
102 replaceOpWithNewOpAndCopyNamehint<aig::AndInverterOp>(
103 rewriter, op, uniqueValues, uniqueInverts);
107ParseResult AndInverterOp::parse(OpAsmParser &parser, OperationState &result) {
108 SmallVector<OpAsmParser::UnresolvedOperand> operands;
109 SmallVector<bool> inverts;
110 auto loc = parser.getCurrentLocation();
113 inverts.push_back(succeeded(parser.parseOptionalKeyword(
"not")));
114 operands.push_back(OpAsmParser::UnresolvedOperand());
116 if (parser.parseOperand(operands.back()))
118 if (parser.parseOptionalComma())
123 if (parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
124 parser.parseCustomTypeWithFallback(type))
127 result.addTypes({type});
128 result.addAttribute(
"inverted",
129 parser.getBuilder().getDenseBoolArrayAttr(inverts));
130 if (parser.resolveOperands(operands, type, loc, result.operands))
135void AndInverterOp::print(OpAsmPrinter &odsPrinter) {
137 llvm::interleaveComma(llvm::zip(getInverted(), getInputs()), odsPrinter,
139 auto [invert, input] = pair;
141 odsPrinter <<
"not ";
145 odsPrinter.printOptionalAttrDict((*this)->getAttrs(), {
"inverted"});
146 odsPrinter <<
" : " << getResult().getType();
149APInt AndInverterOp::evaluate(ArrayRef<APInt> inputs) {
150 assert(inputs.size() == getNumOperands() &&
151 "Expected as many inputs as operands");
152 assert(!inputs.empty() &&
"Expected non-empty input list");
153 APInt result = APInt::getAllOnes(inputs.front().getBitWidth());
154 for (
auto [idx, input] :
llvm::enumerate(inputs)) {
163LogicalResult CutOp::verify() {
164 auto *block = getBody();
175 if (getInputs().size() != block->getNumArguments())
176 return emitOpError(
"the number of inputs and the number of block arguments "
177 "do not match. Expected ")
178 << getInputs().size() <<
" but got " << block->getNumArguments();
181 for (
auto [input, arg] :
llvm::zip(getInputs(), block->getArguments()))
182 if (input.getType() != arg.getType())
183 return emitOpError(
"input type ")
184 << input.getType() <<
" does not match "
185 <<
"block argument type " << arg.getType();
187 if (getNumResults() != block->getTerminator()->getNumOperands())
188 return emitOpError(
"the number of results and the number of terminator "
189 "operands do not match. Expected ")
190 << getNumResults() <<
" but got "
191 << block->getTerminator()->getNumOperands();
194 for (
auto [result, arg] :
195 llvm::zip(getResults(), block->getTerminator()->getOperands()))
196 if (result.getType() != arg.getType())
197 return emitOpError(
"result type ")
198 << result.getType() <<
" does not match "
199 <<
"terminator operand type " << arg.getType();
assert(baseType &&"element must be base type")
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.