Support seeding a ValueMap with nullptr for Metadata entries, a
situation I didn't consider in the Metadata/Value split.
I added a ValueMapper::getMappedMD accessor that returns an
Optional<Metadata*> with the mapped (possibly null) metadata. IRMover
needs to use this to avoid modifying the map when it's checking for
unneeded subprograms. I updated a call from bugpoint since I find the
new code clearer.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265228
91177308-0d34-0410-b5e6-
96231b3b80d8
#define LLVM_IR_VALUEMAP_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
return *MDMap;
}
+ /// Get the mapped metadata, if it's in the map.
+ Optional<Metadata *> getMappedMD(const Metadata *MD) const {
+ if (!MDMap)
+ return None;
+ auto Where = MDMap->find(MD);
+ if (Where == MDMap->end())
+ return None;
+ return Where->second.get();
+ }
+
typedef ValueMapIterator<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
inline iterator begin() { return iterator(Map.begin()); }
// Any needed SPs should have been mapped as they would be reached
// from the function linked in (either on the function itself for linked
// function bodies, or from DILocation on inlined instructions).
- if (!ValueMap.MD()[Op] && !ImportedEntitySPs.count(Op))
+ if (!ValueMap.getMappedMD(Op) && !ImportedEntitySPs.count(Op))
UnneededSubprograms.insert(Op);
}
}
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
// If the value already exists in the map, use it.
- if (Metadata *NewMD = VM.MD().lookup(MD).get())
- return NewMD;
+ if (Optional<Metadata *> NewMD = VM.getMappedMD(MD))
+ return *NewMD;
if (isa<MDString>(MD))
return mapToSelf(VM, MD);
MDNode *llvm::MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
- return cast<MDNode>(MapMetadata(static_cast<const Metadata *>(MD), VM, Flags,
- TypeMapper, Materializer));
+ return cast_or_null<MDNode>(MapMetadata(static_cast<const Metadata *>(MD), VM,
+ Flags, TypeMapper, Materializer));
}
/// RemapInstruction - Convert the instruction operands from referencing the
// module, and that they don't include any deleted blocks.
NamedMDOps.clear();
for (const MDNode *Node : OldMDNodeOps)
- NamedMDOps.push_back(cast<MDNode>(VMap.MD()[Node].get()));
+ NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));
BD.setNewProgram(M); // It crashed, keep the trimmed version...
return true;
EXPECT_EQ(New, D->getOperand(0));
}
+TEST(ValueMapperTest, MapMetadataSeeded) {
+ LLVMContext Context;
+ auto *D = MDTuple::getDistinct(Context, None);
+
+ // The node should be moved.
+ ValueToValueMapTy VM;
+ EXPECT_EQ(None, VM.getMappedMD(D));
+
+ VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
+ EXPECT_EQ(D, *VM.getMappedMD(D));
+ EXPECT_EQ(D, MapMetadata(D, VM, RF_None));
+}
+
+TEST(ValueMapperTest, MapMetadataSeededWithNull) {
+ LLVMContext Context;
+ auto *D = MDTuple::getDistinct(Context, None);
+
+ // The node should be moved.
+ ValueToValueMapTy VM;
+ EXPECT_EQ(None, VM.getMappedMD(D));
+
+ VM.MD().insert(std::make_pair(D, TrackingMDRef()));
+ EXPECT_EQ(nullptr, *VM.getMappedMD(D));
+ EXPECT_EQ(nullptr, MapMetadata(D, VM, RF_None));
+}
+
} // end namespace