20#include "mlir/IR/IRMapping.h"
21#include "mlir/IR/Matchers.h"
22#include "mlir/IR/PatternMatch.h"
23#include "mlir/Pass/Pass.h"
24#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
25#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "arc-canonicalizer"
31#define GEN_PASS_DEF_ARCCANONICALIZER
32#include "circt/Dialect/Arc/ArcPasses.h.inc"
50 ArrayRef<Operation *> getUsers(Operation *symbol)
const {
51 auto it = userMap.find(symbol);
52 return it != userMap.
end() ? it->second.getArrayRef()
53 : ArrayRef<Operation *>();
57 bool useEmpty(Operation *symbol) {
58 return !userMap.count(symbol) || userMap[symbol].empty();
61 void addUser(Operation *def, Operation *user) {
62 assert(isa<mlir::SymbolOpInterface>(def));
63 if (!symbolCache.contains(cast<mlir::SymbolOpInterface>(def).getNameAttr()))
65 {cast<mlir::SymbolOpInterface>(def).getNameAttr(), def});
66 userMap[def].insert(user);
69 void removeUser(Operation *def, Operation *user) {
70 assert(isa<mlir::SymbolOpInterface>(def));
71 if (symbolCache.contains(cast<mlir::SymbolOpInterface>(def).getNameAttr()))
72 userMap[def].remove(user);
73 if (userMap[def].
empty())
77 void removeDefinitionAndAllUsers(Operation *def) {
78 assert(isa<mlir::SymbolOpInterface>(def));
79 symbolCache.erase(cast<mlir::SymbolOpInterface>(def).getNameAttr());
83 void collectAllSymbolUses(Operation *symbolTableOp,
84 SymbolTableCollection &symbolTable) {
88 SmallVector<Operation *> symbols;
89 auto walkFn = [&](Operation *symbolTableOp,
bool allUsesVisible) {
90 for (Operation &nestedOp : symbolTableOp->getRegion(0).getOps()) {
91 auto symbolUses = SymbolTable::getSymbolUses(&nestedOp);
92 assert(symbolUses &&
"expected uses to be valid");
94 for (
const SymbolTable::SymbolUse &use : *symbolUses) {
96 (void)symbolTable.lookupSymbolIn(symbolTableOp, use.getSymbolRef(),
98 for (Operation *symbolOp : symbols)
99 userMap[symbolOp].insert(use.getUser());
105 SymbolTable::walkSymbolTables(symbolTableOp,
false,
110 DenseMap<Operation *, SetVector<Operation *>> userMap;
116class ArcListener :
public mlir::RewriterBase::Listener {
118 explicit ArcListener(SymbolHandler *handler) : Listener(), handler(handler) {}
120 void notifyOperationReplaced(Operation *op, Operation *replacement)
override {
123 auto symOp = dyn_cast<mlir::SymbolOpInterface>(op);
124 auto symReplacement = dyn_cast<mlir::SymbolOpInterface>(replacement);
125 if (symOp && symReplacement &&
126 symOp.getNameAttr() == symReplacement.getNameAttr())
135 void notifyOperationReplaced(Operation *op, ValueRange replacement)
override {
139 void notifyOperationErased(Operation *op)
override { remove(op); }
141 void notifyOperationInserted(Operation *op,
142 mlir::IRRewriter::InsertPoint)
override {
149 FailureOr<Operation *> maybeGetDefinition(Operation *op) {
150 if (
auto callOp = dyn_cast<mlir::CallOpInterface>(op)) {
152 dyn_cast<mlir::SymbolRefAttr>(callOp.getCallableForCallee());
155 if (
auto *def = handler->getDefinition(symAttr.getLeafReference()))
161 void remove(Operation *op) {
162 auto maybeDef = maybeGetDefinition(op);
163 if (!failed(maybeDef))
164 handler->removeUser(*maybeDef, op);
166 if (isa<mlir::SymbolOpInterface>(op))
167 handler->removeDefinitionAndAllUsers(op);
170 void add(Operation *op) {
171 auto maybeDef = maybeGetDefinition(op);
172 if (!failed(maybeDef))
173 handler->addUser(*maybeDef, op);
175 if (
auto defOp = dyn_cast<mlir::SymbolOpInterface>(op))
176 handler->addDefinition(defOp.getNameAttr(), op);
179 SymbolHandler *handler;
182struct PatternStatistics {
183 unsigned removeUnusedArcArgumentsPatternNumArgsRemoved = 0;
197template <
typename SourceOp>
200 SymOpRewritePattern(MLIRContext *ctxt, SymbolHandler &symbolCache,
201 Namespace &names, PatternStatistics &stats,
202 mlir::PatternBenefit benefit = 1,
203 ArrayRef<StringRef> generatedNames = {})
205 symbolCache(symbolCache), statistics(stats) {}
209 SymbolHandler &symbolCache;
210 PatternStatistics &statistics;
213class MemWritePortEnableAndMaskCanonicalizer
214 :
public SymOpRewritePattern<MemoryWritePortOp> {
216 MemWritePortEnableAndMaskCanonicalizer(
217 MLIRContext *ctxt, SymbolHandler &symbolCache,
Namespace &names,
218 PatternStatistics &stats, DenseMap<StringAttr, StringAttr> &arcMapping)
219 : SymOpRewritePattern<MemoryWritePortOp>(ctxt, symbolCache, names, stats),
220 arcMapping(arcMapping) {}
221 LogicalResult matchAndRewrite(MemoryWritePortOp op,
222 PatternRewriter &rewriter)
const final;
225 DenseMap<StringAttr, StringAttr> &arcMapping;
228struct CallPassthroughArc :
public SymOpRewritePattern<CallOp> {
229 using SymOpRewritePattern::SymOpRewritePattern;
230 LogicalResult matchAndRewrite(CallOp op,
231 PatternRewriter &rewriter)
const final;
234struct RemoveUnusedArcs :
public SymOpRewritePattern<DefineOp> {
235 using SymOpRewritePattern::SymOpRewritePattern;
236 LogicalResult matchAndRewrite(DefineOp op,
237 PatternRewriter &rewriter)
const final;
241 using OpRewritePattern::OpRewritePattern;
242 LogicalResult matchAndRewrite(comb::ICmpOp op,
243 PatternRewriter &rewriter)
const final;
247 using OpRewritePattern::OpRewritePattern;
249 PatternRewriter &rewriter)
const final;
252struct RemoveUnusedArcArgumentsPattern :
public SymOpRewritePattern<DefineOp> {
253 using SymOpRewritePattern::SymOpRewritePattern;
254 LogicalResult matchAndRewrite(DefineOp op,
255 PatternRewriter &rewriter)
const final;
258struct SinkArcInputsPattern :
public SymOpRewritePattern<DefineOp> {
259 using SymOpRewritePattern::SymOpRewritePattern;
260 LogicalResult matchAndRewrite(DefineOp op,
261 PatternRewriter &rewriter)
const final;
265 using OpRewritePattern::OpRewritePattern;
266 LogicalResult matchAndRewrite(VectorizeOp op,
267 PatternRewriter &rewriter)
const final;
271 using OpRewritePattern::OpRewritePattern;
272 LogicalResult matchAndRewrite(VectorizeOp op,
273 PatternRewriter &rewriter)
const final;
283 SymbolHandler &symbolCache,
284 PatternRewriter &rewriter) {
285 auto defOp = cast<DefineOp>(symbolCache.getDefinition(
286 llvm::cast<SymbolRefAttr>(callOp.getCallableForCallee())
287 .getLeafReference()));
288 if (defOp.isPassthrough()) {
289 symbolCache.removeUser(defOp, callOp);
290 rewriter.replaceOp(callOp, callOp.getArgOperands());
297 const SmallVector<Value> &newOperands) {
299 unsigned groupSize = vecOp.getResults().size();
300 unsigned numOfGroups = newOperands.size() / groupSize;
301 SmallVector<int32_t> newAttr(numOfGroups, groupSize);
302 vecOp.setInputOperandSegments(newAttr);
303 vecOp.getOperation()->setOperands(ValueRange(newOperands));
311LogicalResult MemWritePortEnableAndMaskCanonicalizer::matchAndRewrite(
312 MemoryWritePortOp op, PatternRewriter &rewriter)
const {
313 auto defOp = cast<DefineOp>(symbolCache.getDefinition(op.getArcAttr()));
316 if (op.getEnable() &&
318 defOp.getBodyBlock().getTerminator()->getOperand(op.getEnableIdx()),
319 mlir::m_ConstantInt(&enable))) {
320 if (enable.isZero()) {
321 symbolCache.removeUser(defOp, op);
322 rewriter.eraseOp(op);
323 if (symbolCache.useEmpty(defOp)) {
324 symbolCache.removeDefinitionAndAllUsers(defOp);
325 rewriter.eraseOp(defOp);
329 if (enable.isAllOnes()) {
330 if (arcMapping.count(defOp.getNameAttr())) {
331 auto arcWithoutEnable = arcMapping[defOp.getNameAttr()];
333 rewriter.modifyOpInPlace(op, [&]() {
335 op.setArc(arcWithoutEnable.getValue());
337 symbolCache.removeUser(defOp, op);
338 symbolCache.addUser(symbolCache.getDefinition(arcWithoutEnable), op);
342 auto newName = names.newName(defOp.getName());
343 auto users = SmallVector<Operation *>(symbolCache.getUsers(defOp));
344 symbolCache.removeDefinitionAndAllUsers(defOp);
347 rewriter.modifyOpInPlace(op, [&]() {
352 auto newResultTypes = op.getArcResultTypes();
355 rewriter.setInsertionPoint(defOp);
356 auto newDefOp = rewriter.cloneWithoutRegions(defOp);
357 auto *block = rewriter.createBlock(
358 &newDefOp.getBody(), newDefOp.getBody().end(),
359 newDefOp.getArgumentTypes(),
360 SmallVector<Location>(newDefOp.getNumArguments(), defOp.getLoc()));
361 auto callOp = CallOp::create(rewriter, newDefOp.getLoc(), newResultTypes,
362 newName, block->getArguments());
363 SmallVector<Value> results(callOp->getResults());
365 rewriter.getI1Type(), 1);
366 results.insert(results.begin() + op.getEnableIdx(), constTrue);
367 OutputOp::create(rewriter, newDefOp.getLoc(), results);
370 auto *terminator = defOp.getBodyBlock().getTerminator();
371 rewriter.modifyOpInPlace(
372 terminator, [&]() { terminator->eraseOperand(op.getEnableIdx()); });
373 rewriter.modifyOpInPlace(defOp, [&]() {
374 defOp.setName(newName);
375 defOp.setFunctionType(
376 rewriter.getFunctionType(defOp.getArgumentTypes(), newResultTypes));
380 symbolCache.addDefinition(defOp.getNameAttr(), defOp);
381 symbolCache.addDefinition(newDefOp.getNameAttr(), newDefOp);
382 symbolCache.addUser(defOp, callOp);
383 for (
auto *user : users)
384 symbolCache.addUser(user == op ? defOp : newDefOp, user);
386 arcMapping[newDefOp.getNameAttr()] = defOp.getNameAttr();
394CallPassthroughArc::matchAndRewrite(CallOp op,
395 PatternRewriter &rewriter)
const {
400RemoveUnusedArcs::matchAndRewrite(DefineOp op,
401 PatternRewriter &rewriter)
const {
402 if (symbolCache.useEmpty(op)) {
403 op.getBody().walk([&](mlir::CallOpInterface user) {
404 if (
auto symbol = dyn_cast<SymbolRefAttr>(user.getCallableForCallee()))
405 if (
auto *defOp = symbolCache.getDefinition(symbol.getLeafReference()))
406 symbolCache.removeUser(defOp, user);
408 symbolCache.removeDefinitionAndAllUsers(op);
409 rewriter.eraseOp(op);
416ICMPCanonicalizer::matchAndRewrite(comb::ICmpOp op,
417 PatternRewriter &rewriter)
const {
418 auto getConstant = [&](
const APInt &constant) -> Value {
421 auto sameWidthIntegers = [](TypeRange types) -> std::optional<unsigned> {
422 if (llvm::all_equal(types) && !types.empty())
423 if (
auto intType = dyn_cast<IntegerType>(*types.begin()))
424 return intType.getWidth();
427 auto negate = [&](Value input) -> Value {
429 return comb::XorOp::create(rewriter, op.getLoc(), input, constTrue,
434 if (matchPattern(op.getRhs(), mlir::m_ConstantInt(&rhs))) {
435 if (
auto concatOp = op.getLhs().getDefiningOp<
comb::ConcatOp>()) {
436 if (
auto optionalWidth =
437 sameWidthIntegers(concatOp->getOperands().getTypes())) {
438 if ((op.getPredicate() == comb::ICmpPredicate::eq ||
439 op.getPredicate() == comb::ICmpPredicate::ne) &&
441 Value andOp = comb::AndOp::create(
442 rewriter, op.getLoc(), concatOp.getInputs(), op.getTwoState());
443 if (*optionalWidth == 1) {
444 if (op.getPredicate() == comb::ICmpPredicate::ne)
445 andOp = negate(andOp);
446 rewriter.replaceOp(op, andOp);
449 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
450 op, op.getPredicate(), andOp,
451 getConstant(APInt(*optionalWidth, rhs.getZExtValue(),
457 if ((op.getPredicate() == comb::ICmpPredicate::ne ||
458 op.getPredicate() == comb::ICmpPredicate::eq) &&
460 Value orOp = comb::OrOp::create(
461 rewriter, op.getLoc(), concatOp.getInputs(), op.getTwoState());
462 if (*optionalWidth == 1) {
463 if (op.getPredicate() == comb::ICmpPredicate::eq)
465 rewriter.replaceOp(op, orOp);
468 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
469 op, op.getPredicate(), orOp,
470 getConstant(APInt(*optionalWidth, rhs.getZExtValue(),
481LogicalResult RemoveUnusedArcArgumentsPattern::matchAndRewrite(
482 DefineOp op, PatternRewriter &rewriter)
const {
483 BitVector toDelete(op.getNumArguments());
484 for (
auto [i, arg] :
llvm::enumerate(op.getArguments()))
494 SmallVector<mlir::CallOpInterface> mutableUsers;
495 for (
auto *user : symbolCache.getUsers(op)) {
496 auto callOpMutable = dyn_cast<mlir::CallOpInterface>(user);
499 mutableUsers.push_back(callOpMutable);
503 for (
auto user : mutableUsers)
504 for (int i = toDelete.size() - 1; i >= 0; --i)
506 rewriter.modifyOpInPlace(
507 user, [&]() { user.getArgOperandsMutable().erase(i); });
509 bool matchFailure =
false;
510 rewriter.modifyOpInPlace(op, [&]() {
511 if (failed(op.eraseArguments(toDelete))) {
517 rewriter.getFunctionType(op.getArgumentTypes(), op.getResultTypes()));
521 return rewriter.notifyMatchFailure(op,
"failed to erase arguments");
523 statistics.removeUnusedArcArgumentsPatternNumArgsRemoved += toDelete.count();
528SinkArcInputsPattern::matchAndRewrite(DefineOp op,
529 PatternRewriter &rewriter)
const {
532 auto users = symbolCache.getUsers(op);
534 users, [](
auto *user) {
return !isa<mlir::CallOpInterface>(user); }))
538 SmallVector<Operation *> stateConsts(op.getNumArguments());
540 for (
auto *user : users) {
541 auto callOp = cast<mlir::CallOpInterface>(user);
542 for (
auto [constArg, input] :
543 llvm::zip(stateConsts, callOp.getArgOperands())) {
544 if (
auto *constOp = input.getDefiningOp();
545 constOp && constOp->template hasTrait<OpTrait::ConstantLike>()) {
551 constArg->getName() == input.getDefiningOp()->getName() &&
552 constArg->getAttrDictionary() ==
553 input.getDefiningOp()->getAttrDictionary())
562 rewriter.setInsertionPointToStart(&op.getBodyBlock());
563 llvm::BitVector toDelete(op.getBodyBlock().getNumArguments());
564 for (
auto [constArg, arg] :
llvm::zip(stateConsts, op.getArguments())) {
567 auto *inlinedConst = rewriter.clone(*constArg);
568 rewriter.replaceAllUsesWith(arg, inlinedConst->getResult(0));
569 toDelete.set(arg.getArgNumber());
571 op.getBodyBlock().eraseArguments(toDelete);
572 op.setType(rewriter.getFunctionType(op.getBodyBlock().getArgumentTypes(),
573 op.getResultTypes()));
576 for (
auto *user : users) {
577 auto callOp = cast<mlir::CallOpInterface>(user);
578 SmallPtrSet<Value, 4> maybeUnusedValues;
579 SmallVector<Value> newInputs;
580 for (
auto [index, value] :
llvm::enumerate(callOp.getArgOperands())) {
582 maybeUnusedValues.insert(value);
584 newInputs.push_back(value);
586 rewriter.modifyOpInPlace(
587 callOp, [&]() { callOp.getArgOperandsMutable().assign(newInputs); });
588 for (
auto value : maybeUnusedValues)
589 if (value.use_empty())
590 rewriter.eraseOp(value.getDefiningOp());
593 return success(toDelete.any());
598 PatternRewriter &rewriter)
const {
604 if (mlir::matchPattern(op.getResetValue(), mlir::m_ConstantInt(&constant)))
605 if (constant.isZero())
608 Value newInput = comb::MuxOp::create(rewriter, op->getLoc(), op.getReset(),
609 op.getResetValue(), op.getInput());
610 rewriter.modifyOpInPlace(op, [&]() {
611 op.getInputMutable().set(newInput);
612 op.getResetMutable().clear();
613 op.getResetValueMutable().clear();
620MergeVectorizeOps::matchAndRewrite(VectorizeOp vecOp,
621 PatternRewriter &rewriter)
const {
622 auto ¤tBlock = vecOp.getBody().front();
623 IRMapping argMapping;
624 SmallVector<Value> newOperands;
625 SmallVector<VectorizeOp> vecOpsToRemove;
626 bool canBeMerged =
false;
628 unsigned paddedBy = 0;
630 for (
unsigned argIdx = 0, numArgs = vecOp.getInputs().size();
631 argIdx < numArgs; ++argIdx) {
632 auto inputVec = vecOp.getInputs()[argIdx];
636 auto otherVecOp = inputVec[0].getDefiningOp<VectorizeOp>();
637 if (!otherVecOp || otherVecOp == vecOp ||
638 !llvm::all_of(otherVecOp.getResults(),
639 [](
auto result) {
return result.hasOneUse(); }) ||
640 !llvm::all_of(inputVec, [&](
auto result) {
641 return result.template getDefiningOp<VectorizeOp>() == otherVecOp;
643 newOperands.insert(newOperands.end(), inputVec.begin(), inputVec.end());
650 DenseMap<Value, size_t> resultIdxMap;
651 for (
auto [resultIdx, result] :
llvm::enumerate(otherVecOp.getResults()))
652 resultIdxMap[result] = resultIdx;
654 SmallVector<Value> tempVec(inputVec.begin(), inputVec.end());
655 llvm::sort(tempVec, [&](Value a, Value b) {
656 return resultIdxMap[
a] < resultIdxMap[
b];
660 if (tempVec != SmallVector<Value>(otherVecOp.getResults().begin(),
661 otherVecOp.getResults().end())) {
662 newOperands.insert(newOperands.end(), inputVec.begin(), inputVec.end());
666 DenseMap<size_t, size_t> fromRealIdxToSortedIdx;
667 for (
auto [inIdx, in] :
llvm::enumerate(inputVec))
668 fromRealIdxToSortedIdx[inIdx] = resultIdxMap[in];
675 if (inputVec != otherVecOp.getResults()) {
676 for (
auto otherVecOpInputVec : otherVecOp.getInputs()) {
678 tempVec = SmallVector<Value>(inputVec.size());
679 for (
auto [realIdx, opernad] :
llvm::enumerate(otherVecOpInputVec))
681 otherVecOpInputVec[fromRealIdxToSortedIdx[realIdx]];
683 newOperands.insert(newOperands.end(), tempVec.begin(), tempVec.end());
687 newOperands.insert(newOperands.end(), otherVecOp.getOperands().begin(),
688 otherVecOp.getOperands().end());
690 auto &otherBlock = otherVecOp.getBody().front();
691 for (
auto &otherArg : otherBlock.getArguments()) {
692 auto newArg = currentBlock.insertArgument(
693 argIdx + paddedBy, otherArg.getType(), otherArg.getLoc());
694 argMapping.map(otherArg, newArg);
698 rewriter.setInsertionPointToStart(¤tBlock);
699 for (
auto &op : otherBlock.without_terminator())
700 rewriter.clone(op, argMapping);
702 unsigned argNewPos = paddedBy + argIdx;
705 auto retOp = cast<VectorizeReturnOp>(otherBlock.getTerminator());
706 rewriter.replaceAllUsesWith(currentBlock.getArgument(argNewPos),
707 argMapping.lookupOrDefault(retOp.getValue()));
708 rewriter.modifyOpInPlace(vecOp,
709 [&]() { currentBlock.eraseArgument(argNewPos); });
710 vecOpsToRemove.push_back(otherVecOp);
722 for (
auto deadOp : vecOpsToRemove)
723 rewriter.eraseOp(deadOp);
729static unsigned hashValue(
const SmallVector<Value> &inputs) {
731 for (
auto input : inputs)
732 hash = hash_combine(hash, input);
739 return SmallVector<Value>();
743 return SmallVector<Value>();
750 static bool isEqual(
const SmallVector<Value> &lhs,
751 const SmallVector<Value> &rhs) {
757LogicalResult KeepOneVecOp::matchAndRewrite(VectorizeOp vecOp,
758 PatternRewriter &rewriter)
const {
759 DenseMap<SmallVector<Value>,
unsigned> inExists;
760 auto ¤tBlock = vecOp.getBody().front();
761 SmallVector<Value> newOperands;
762 BitVector argsToRemove(vecOp.getInputs().size(),
false);
763 for (
size_t argIdx = 0; argIdx < vecOp.getInputs().size(); ++argIdx) {
764 auto input = SmallVector<Value>(vecOp.getInputs()[argIdx].begin(),
765 vecOp.getInputs()[argIdx].end());
766 if (
auto in = inExists.find(input); in != inExists.end()) {
767 rewriter.replaceAllUsesWith(currentBlock.getArgument(argIdx),
768 currentBlock.getArgument(in->second));
769 argsToRemove.set(argIdx);
772 inExists[input] = argIdx;
773 newOperands.insert(newOperands.end(), input.begin(), input.end());
776 if (argsToRemove.none())
779 rewriter.modifyOpInPlace(
780 vecOp, [&]() { currentBlock.eraseArguments(argsToRemove); });
789struct ArcCanonicalizerPass
790 :
public arc::impl::ArcCanonicalizerBase<ArcCanonicalizerPass> {
791 void runOnOperation()
override;
795void ArcCanonicalizerPass::runOnOperation() {
796 MLIRContext &ctxt = getContext();
797 SymbolTableCollection symbolTable;
799 cache.addDefinitions(getOperation());
800 cache.collectAllSymbolUses(getOperation(), symbolTable);
803 DenseMap<StringAttr, StringAttr> arcMapping;
805 mlir::GreedyRewriteConfig config;
806 config.setRegionSimplificationLevel(
807 mlir::GreedySimplifyRegionLevel::Disabled);
808 config.setMaxIterations(10);
809 config.setUseTopDownTraversal(
true);
810 ArcListener listener(&cache);
811 config.setListener(&listener);
813 PatternStatistics statistics;
814 RewritePatternSet symbolPatterns(&getContext());
815 symbolPatterns.add<CallPassthroughArc, RemoveUnusedArcs,
816 RemoveUnusedArcArgumentsPattern, SinkArcInputsPattern>(
817 &getContext(), cache, names, statistics);
818 symbolPatterns.add<MemWritePortEnableAndMaskCanonicalizer>(
819 &getContext(), cache, names, statistics, arcMapping);
821 if (failed(mlir::applyPatternsGreedily(getOperation(),
822 std::move(symbolPatterns), config)))
823 return signalPassFailure();
825 numArcArgsRemoved = statistics.removeUnusedArcArgumentsPatternNumArgsRemoved;
828 for (
auto *dialect : ctxt.getLoadedDialects())
829 dialect->getCanonicalizationPatterns(
patterns);
830 for (mlir::RegisteredOperationName op : ctxt.getRegisteredOperations())
831 op.getCanonicalizationPatterns(
patterns, &ctxt);
832 patterns.add<ICMPCanonicalizer, CompRegCanonicalizer, MergeVectorizeOps,
833 KeepOneVecOp>(&getContext());
836 (void)mlir::applyPatternsGreedily(getOperation(), std::move(
patterns),
LogicalResult canonicalizePassthoughCall(mlir::CallOpInterface callOp, SymbolHandler &symbolCache, PatternRewriter &rewriter)
LogicalResult updateInputOperands(VectorizeOp &vecOp, const SmallVector< Value > &newOperands)
assert(baseType &&"element must be base type")
static std::optional< APSInt > getConstant(Attribute operand)
Determine the value of a constant operand for the sake of constant folding.
static InstancePath empty
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
SymbolCacheBase::Iterator end() override
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
llvm::hash_code hash_value(const DenseSet< T > &set)
static unsigned hashValue(const SmallVector< Value > &inputs)
static SmallVector< Value > getTombstoneKey()
static SmallVector< Value > getEmptyKey()
static bool isEqual(const SmallVector< Value > &lhs, const SmallVector< Value > &rhs)
static unsigned getHashValue(const SmallVector< Value > &inputs)