Handle value uses wrapped in metadata for the use-list order

When generating the use-list order, also consider value uses that are
operands which are wrapped in metadata; e.g. llvm.dbg.value operands.

This fixes PR36778. The test case is based on the reproducer from that
report.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D53758
This commit is contained in:
David Stenberg
2020-10-20 19:30:39 +02:00
parent cf9e54ef49
commit 0c0fcea557
4 changed files with 115 additions and 6 deletions

View File

@@ -78,6 +78,16 @@ struct OrderMap {
} // end anonymous namespace
/// Look for a value that might be wrapped as metadata, e.g. a value in a
/// metadata operand. Returns nullptr for a non-wrapped input value if
/// OnlyWrapped is true, or it returns the input value as-is if false.
static const Value *skipMetadataWrapper(const Value *V, bool OnlyWrapped) {
if (const auto *MAV = dyn_cast<MetadataAsValue>(V))
if (const auto *VAM = dyn_cast<ValueAsMetadata>(MAV->getMetadata()))
return VAM->getValue();
return OnlyWrapped ? nullptr : V;
}
static void orderValue(const Value *V, OrderMap &OM) {
if (OM.lookup(V).first)
return;
@@ -123,6 +133,25 @@ static OrderMap orderModule(const Module &M) {
if (!isa<GlobalValue>(U.get()))
orderValue(U.get(), OM);
}
// As constants used in metadata operands are emitted as module-level
// constants, we must order them before other operands. Also, we must order
// these before global values, as these will be read before setting the
// global values' initializers. The latter matters for constants which have
// uses towards other constants that are used as initializers.
for (const Function &F : M) {
if (F.isDeclaration())
continue;
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
for (const Value *V : I.operands()) {
if (const Value *Op = skipMetadataWrapper(V, true)) {
if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
isa<InlineAsm>(*Op))
orderValue(Op, OM);
}
}
}
OM.LastGlobalConstantID = OM.size();
// Initializers of GlobalValues are processed in