Improve IRGen's infrastructure for caching local type data.

There are several interesting new features here.

The first is that, when emitting a SILFunction, we're now able to
cache type data according to the full dominance structure of the
original function.  For example, if we ask for type metadata, and
we've already computed it in a dominating position, we're now able
to re-use that value; previously, we were limited to only doing this
if the value was from the entry block or the LLVM basic block
matched exactly.  Since this tracks the SIL dominance relationship,
things in IRGen which add their own control flow must be careful
to suppress caching within blocks that may not dominate the
fallthrough; this mechanism is currently very crude, but could be
made to allow a limited amount of caching within the
conditionally-executed blocks.

This query is done using a proper dominator tree analysis, even at -O0.
I do not expect that we will frequently need to actually build the
tree, and I expect that the code-size benefits of doing a real
analysis will be significant, especially as we move towards making
more metadata lazily computed.

The second feature is that this adds support for "abstract"
cache entries, which indicate that we know how to derive the metadata
but haven't actually done so.  This code isn't yet tested, but
it's going to be the basis of making a lot of things much lazier.
This commit is contained in:
John McCall
2016-01-05 17:36:50 -08:00
parent 589a46f9ba
commit 7dd9f5f037
22 changed files with 1237 additions and 187 deletions

View File

@@ -52,8 +52,12 @@ IRGenFunction::IRGenFunction(IRGenModule &IGM,
IRGenFunction::~IRGenFunction() {
emitEpilogue();
// Restore the debug location.
if (IGM.DebugInfo) IGM.DebugInfo->popLoc();
// Tear down any side-table data structures.
if (LocalTypeData) destroyLocalTypeData();
}
/// Call the llvm.memcpy intrinsic. The arguments need not already
@@ -212,40 +216,6 @@ void IRGenFunction::emitFakeExplosion(const TypeInfo &type,
}
}
llvm::Value *IRGenFunction::lookupTypeDataMap(CanType type, LocalTypeData index,
const TypeDataMap &scopedMap) {
// First try to lookup in the unscoped cache (= definitions in the entry block
// of the function).
auto key = getLocalTypeDataKey(type, index);
auto it = LocalTypeDataMap.find(key);
if (it != LocalTypeDataMap.end())
return it->second;
// Now try to lookup in the scoped cache.
auto it2 = scopedMap.find(key);
if (it2 == scopedMap.end())
return nullptr;
if (auto *I = dyn_cast<llvm::Instruction>(it2->second)) {
// This is a very very simple dominance check: either the definition is in the
// entry block or in the current block.
// TODO: do a better dominance check.
if (I->getParent() == &CurFn->getEntryBlock() ||
I->getParent() == Builder.GetInsertBlock()) {
return I;
}
return nullptr;
}
if (isa<llvm::Constant>(it2->second)) {
return it2->second;
}
// TODO: other kinds of value?
return nullptr;
}
void IRGenFunction::unimplemented(SourceLoc Loc, StringRef Message) {
return IGM.unimplemented(Loc, Message);
}