diff --git a/mlir/include/mlir/Analysis/NestedMatcher.h b/mlir/include/mlir/Analysis/NestedMatcher.h --- a/mlir/include/mlir/Analysis/NestedMatcher.h +++ b/mlir/include/mlir/Analysis/NestedMatcher.h @@ -93,8 +93,15 @@ public: NestedPattern(ArrayRef nested, FilterFunctionType filter = defaultFilterFunction); - NestedPattern(const NestedPattern &) = default; - NestedPattern &operator=(const NestedPattern &) = default; + NestedPattern(const NestedPattern &other); + NestedPattern &operator=(const NestedPattern &other); + + ~NestedPattern() { + // Call destructors manually, ArrayRef is non-owning so it wouldn't call + // them, but we should free the memory allocated by std::function outside of + // the arena allocator. + freeNested(); + } /// Returns all the top-level matches in `func`. void match(FuncOp func, SmallVectorImpl *matches) { @@ -114,6 +121,13 @@ friend class NestedMatch; friend struct State; + /// Copies the list of nested patterns to the arena allocator associated with + /// this pattern. + void copyNestedToThis(ArrayRef nested); + + /// Calls destructors on nested patterns. + void freeNested(); + /// Underlying global bump allocator managed by a NestedPatternContext. static llvm::BumpPtrAllocator *&allocator(); diff --git a/mlir/lib/Analysis/NestedMatcher.cpp b/mlir/lib/Analysis/NestedMatcher.cpp --- a/mlir/lib/Analysis/NestedMatcher.cpp +++ b/mlir/lib/Analysis/NestedMatcher.cpp @@ -39,14 +39,37 @@ return allocator; } +void NestedPattern::copyNestedToThis(ArrayRef nested) { + if (nested.empty()) + return; + + auto *newNested = allocator()->Allocate(nested.size()); + std::uninitialized_copy(nested.begin(), nested.end(), newNested); + nestedPatterns = ArrayRef(newNested, nested.size()); +} + +void NestedPattern::freeNested() { + for (const auto &p : nestedPatterns) + p.~NestedPattern(); +} + NestedPattern::NestedPattern(ArrayRef nested, FilterFunctionType filter) : nestedPatterns(), filter(filter), skip(nullptr) { - if (!nested.empty()) { - auto *newNested = allocator()->Allocate(nested.size()); - std::uninitialized_copy(nested.begin(), nested.end(), newNested); - nestedPatterns = ArrayRef(newNested, nested.size()); - } + copyNestedToThis(nested); +} + +NestedPattern::NestedPattern(const NestedPattern &other) + : nestedPatterns(), filter(other.filter), skip(other.skip) { + copyNestedToThis(other.nestedPatterns); +} + +NestedPattern &NestedPattern::operator=(const NestedPattern &other) { + freeNested(); + filter = other.filter; + skip = other.skip; + copyNestedToThis(other.nestedPatterns); + return *this; } unsigned NestedPattern::getDepth() const {