[TableGen] Allocate `Operator` object on heap in `RecordOperatorMap`

Iterators for a `llvm::DenseMap` can be invalidated when an insertion occurs.
    In Pattern's `collectBoundArguments()`, we recursively handle all nested DAG
    nodes and grow the the `RecordOperatorMap`, while retaining a reference.
    This can cause the reference to be invalid and the program to behave randomly.
    Allocate each `Operator` object specifically to solve this issue.

    Also, `llvm::DenseMap` is a great way to map pointers to pointers, or map
    other small types to each other. This avoids placing the `Operator` object
    directly into the map.

--

PiperOrigin-RevId: 243281486
This commit is contained in:
Lei Zhang 2019-04-12 09:52:11 -07:00 committed by Mehdi Amini
parent 138c972d11
commit 2dc6d205ac
2 changed files with 13 additions and 3 deletions

View File

@ -39,8 +39,14 @@ class Record;
namespace mlir {
namespace tblgen {
// Mapping from TableGen Record to Operator wrapper object
using RecordOperatorMap = llvm::DenseMap<const llvm::Record *, Operator>;
// Mapping from TableGen Record to Operator wrapper object.
//
// We allocate each wrapper object in heap to make sure the pointer to it is
// valid throughout the lifetime of this map. This is important because this map
// is shared among multiple patterns to avoid creating the wrapper object for
// the same op again and again. But this map will continuously grow.
using RecordOperatorMap =
llvm::DenseMap<const llvm::Record *, std::unique_ptr<Operator>>;
class Pattern;

View File

@ -111,7 +111,11 @@ llvm::StringRef tblgen::DagNode::getOpName() const {
Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
return mapper->try_emplace(opDef, opDef).first->second;
auto it = mapper->find(opDef);
if (it != mapper->end())
return *it->second;
return *mapper->try_emplace(opDef, llvm::make_unique<Operator>(opDef))
.first->second;
}
unsigned tblgen::DagNode::getNumOps() const {