mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user