DI: Reverse direction of subprogram -> function edge.

Previously, subprograms contained a metadata reference to the function they
described. Because most clients need to get or set a subprogram for a given
function rather than the other way around, this created unneeded inefficiency.

For example, many passes needed to call the function llvm::makeSubprogramMap()
to build a mapping from functions to subprograms, and the IR linker needed to
fix up function references in a way that caused quadratic complexity in the IR
linking phase of LTO.

This change reverses the direction of the edge by storing the subprogram as
function-level metadata and removing DISubprogram's function field.

Since this is an IR change, a bitcode upgrade has been provided.

Fixes PR23367. An upgrade script for textual IR for out-of-tree clients is
attached to the PR.

Differential Revision: http://reviews.llvm.org/D14265

llvm-svn: 252219
This commit is contained in:
Peter Collingbourne
2015-11-05 22:03:56 +00:00
parent 18da38edb3
commit d4bff30370
400 changed files with 1385 additions and 1536 deletions

View File

@@ -232,6 +232,10 @@ class BitcodeReader : public GVMaterializer {
bool StripDebugInfo = false;
/// Functions that need to be matched with subprograms when upgrading old
/// metadata.
SmallDenseMap<Function *, DISubprogram *, 16> FunctionsWithSPs;
std::vector<std::string> BundleTags;
public:
@@ -2182,20 +2186,33 @@ std::error_code BitcodeReader::parseMetadata() {
break;
}
case bitc::METADATA_SUBPROGRAM: {
if (Record.size() != 19)
if (Record.size() != 18 && Record.size() != 19)
return error("Invalid record");
MDValueList.assignValue(
GET_OR_DISTINCT(
DISubprogram,
Record[0] || Record[8], // All definitions should be distinct.
(Context, getMDOrNull(Record[1]), getMDString(Record[2]),
getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
Record[14], getMDOrNull(Record[15]), getMDOrNull(Record[16]),
getMDOrNull(Record[17]), getMDOrNull(Record[18]))),
NextMDValueNo++);
bool HasFn = Record.size() == 19;
DISubprogram *SP = GET_OR_DISTINCT(
DISubprogram,
Record[0] || Record[8], // All definitions should be distinct.
(Context, getMDOrNull(Record[1]), getMDString(Record[2]),
getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
Record[14], getMDOrNull(Record[15 + HasFn]),
getMDOrNull(Record[16 + HasFn]), getMDOrNull(Record[17 + HasFn])));
MDValueList.assignValue(SP, NextMDValueNo++);
// Upgrade sp->function mapping to function->sp mapping.
if (HasFn && Record[15]) {
if (auto *CMD = dyn_cast<ConstantAsMetadata>(getMDOrNull(Record[15])))
if (auto *F = dyn_cast<Function>(CMD->getValue())) {
if (F->isMaterializable())
// Defer until materialized; unmaterialized functions may not have
// metadata.
FunctionsWithSPs[F] = SP;
else if (!F->empty())
F->setSubprogram(SP);
}
}
break;
}
case bitc::METADATA_LEXICAL_BLOCK: {
@@ -5139,6 +5156,10 @@ std::error_code BitcodeReader::materialize(GlobalValue *GV) {
}
}
// Finish fn->subprogram upgrade for materialized functions.
if (DISubprogram *SP = FunctionsWithSPs.lookup(F))
F->setSubprogram(SP);
// Bring in any functions that this function forward-referenced via
// blockaddresses.
return materializeForwardReferencedFunctions();