summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-16 01:29:08 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-16 01:29:08 +0000
commitf0d73f95c15f909c6034f1735632695248bb75a8 (patch)
treeb7f244a7c9f762457852998500c4e62a014516c2 /llvm/include
parent2db6f2e508126d237435a4d43af8076bf74f641d (diff)
downloadbcm5719-llvm-f0d73f95c15f909c6034f1735632695248bb75a8.tar.gz
bcm5719-llvm-f0d73f95c15f909c6034f1735632695248bb75a8.zip
ValueMapper: Eliminate cross-file co-recursion, NFC
Eliminate co-recursion of Mapper::mapValue through ValueMaterializer::materializeInitFor, through a major redesign of the ValueMapper.cpp interface. - Expose a ValueMapper class that controls the entry points to the mapping algorithms. - Change IRLinker to use ValueMapper directly, rather than llvm::RemapInstruction, llvm::MapValue, etc. - Use (e.g.) ValueMapper::scheduleMapGlobalInit to add mapping work to a worklist in ValueMapper instead of recursing. There were two fairly major complications. Firstly, IRLinker::linkAppendingVarProto incorporates an on-the-fly IR ugprade that I had to split apart. Long-term, this upgrade should be done in the bitcode reader (and we should only accept the "new" form), but for now I've just made it work and added a FIXME. The hold-op is that we need to deprecate C API that relies on this. Secondly, IRLinker has special logic to correctly implement aliases with comdats, and uses two ValueToValueMapTy instances and two ValueMaterializers. I supported this by allowing clients to register an alternate mapping context, whose MCID can be passed in when scheduling new work. While out of scope for this commit, it should now be straightforward to remove recursion from Mapper::mapValue. llvm-svn: 266503
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/Transforms/Utils/ValueMapper.h140
1 files changed, 117 insertions, 23 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/ValueMapper.h b/llvm/include/llvm/Transforms/Utils/ValueMapper.h
index 295c18776fe..4d8da32214e 100644
--- a/llvm/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/llvm/include/llvm/Transforms/Utils/ValueMapper.h
@@ -98,6 +98,92 @@ static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
return RemapFlags(unsigned(LHS) | unsigned(RHS));
}
+class ValueMapperImpl;
+
+/// Context for (re-)mapping values (and metadata).
+///
+/// A shared context used for mapping and remapping of Value and Metadata
+/// instances using \a ValueToValueMapTy, \a RemapFlags, \a
+/// ValueMapTypeRemapper, and \a ValueMaterializer.
+///
+/// There are a number of top-level entry points:
+/// - \a mapValue() (and \a mapConstant());
+/// - \a mapMetadata() (and \a mapMDNode());
+/// - \a remapInstruction(); and
+/// - \a remapFunction().
+///
+/// The \a ValueMaterializer can be used as a callback, but cannot invoke any
+/// of these top-level functions recursively. Instead, callbacks should use
+/// one of the following to schedule work lazily in the \a ValueMapper
+/// instance:
+/// - \a scheduleMapGlobalInitializer()
+/// - \a scheduleMapAppendingVariable()
+/// - \a scheduleMapGlobalAliasee()
+/// - \a scheduleRemapFunction()
+///
+/// Sometimes a callback needs a diferent mapping context. Such a context can
+/// be registered using \a registerAlternateMappingContext(), which takes an
+/// alternate \a ValueToValueMapTy and \a ValueMaterializer and returns a ID to
+/// pass into the schedule*() functions.
+///
+/// TODO: lib/Linker really doesn't need the \a ValueHandle in the \a
+/// ValueToValueMapTy. We should template \a ValueMapper (and its
+/// implementation classes), and explicitly instantiate on two concrete
+/// instances of \a ValueMap (one as \a ValueToValueMap, and one with raw \a
+/// Value pointers). It may be viable to do away with \a TrackingMDRef in the
+/// \a Metadata side map for the lib/Linker case as well, in which case we'll
+/// need a new template parameter on \a ValueMap.
+///
+/// TODO: Update callers of \a RemapInstruction() and \a MapValue() (etc.) to
+/// use \a ValueMapper directly.
+class ValueMapper {
+ void *pImpl;
+
+ ValueMapper(ValueMapper &&) = delete;
+ ValueMapper(const ValueMapper &) = delete;
+ ValueMapper &operator=(ValueMapper &&) = delete;
+ ValueMapper &operator=(const ValueMapper &) = delete;
+
+public:
+ ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+ ~ValueMapper();
+
+ /// Register an alternate mapping context.
+ ///
+ /// Returns a MappingContextID that can be used with the various schedule*()
+ /// API to switch in a different value map on-the-fly.
+ unsigned
+ registerAlternateMappingContext(ValueToValueMapTy &VM,
+ ValueMaterializer *Materializer = nullptr);
+
+ /// Add to the current \a RemapFlags.
+ ///
+ /// \note Like the top-level mapping functions, \a addFlags() must be called
+ /// at the top level, not during a callback in a \a ValueMaterializer.
+ void addFlags(RemapFlags Flags);
+
+ Metadata *mapMetadata(const Metadata &MD);
+ MDNode *mapMDNode(const MDNode &N);
+
+ Value *mapValue(const Value &V);
+ Constant *mapConstant(const Constant &C);
+
+ void remapInstruction(Instruction &I);
+ void remapFunction(Function &F);
+
+ void scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init,
+ unsigned MappingContextID = 0);
+ void scheduleMapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
+ bool IsOldCtorDtor,
+ ArrayRef<Constant *> NewMembers,
+ unsigned MappingContextID = 0);
+ void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
+ unsigned MappingContextID = 0);
+ void scheduleRemapFunction(Function &F, unsigned MappingContextID = 0);
+};
+
/// Look up or compute a value in the value map.
///
/// Return a mapped value for a function-local value (Argument, Instruction,
@@ -115,10 +201,12 @@ static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
/// 6. Else if \c V is a \a MetadataAsValue, rewrap the return of \a
/// MapMetadata().
/// 7. Else, compute the equivalent constant, and return it.
-Value *MapValue(const Value *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
+inline Value *MapValue(const Value *V, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapValue(*V);
+}
/// Lookup or compute a mapping for a piece of metadata.
///
@@ -135,16 +223,20 @@ Value *MapValue(const Value *V, ValueToValueMapTy &VM,
///
/// \note \a LocalAsMetadata is completely unsupported by \a MapMetadata.
/// Instead, use \a MapValue() with its wrapping \a MetadataAsValue instance.
-Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
+inline Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMetadata(*MD);
+}
/// Version of MapMetadata with type safety for MDNode.
-MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
+inline MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMDNode(*MD);
+}
/// Convert the instruction operands from referencing the current values into
/// those specified by VM.
@@ -154,10 +246,12 @@ MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
///
/// Note that \a MapValue() only returns \c nullptr for SSA values missing from
/// \c VM.
-void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
+inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ ValueMapper(VM, Flags, TypeMapper, Materializer).remapInstruction(*I);
+}
/// Remap the operands, metadata, arguments, and instructions of a function.
///
@@ -165,19 +259,19 @@ void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
/// function; calls \a MapMetadata() on each attached MDNode; remaps the
/// argument types using the provided \c TypeMapper; and calls \a
/// RemapInstruction() on every instruction.
-void RemapFunction(Function &F, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr);
+inline void RemapFunction(Function &F, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr) {
+ ValueMapper(VM, Flags, TypeMapper, Materializer).remapFunction(F);
+}
/// Version of MapValue with type safety for Constant.
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr) {
- // This can be null for RF_NullMapMissingGlobalValues.
- return cast_or_null<Constant>(
- MapValue((const Value *)V, VM, Flags, TypeMapper, Materializer));
+ return ValueMapper(VM, Flags, TypeMapper, Materializer).mapConstant(*V);
}
} // End llvm namespace
OpenPOWER on IntegriCloud