Add a stand-alone devirtualizer pass.

Add back a stand-alone devirtualizer pass, running prior to generic
specialization. As with the stand-alone generic specializer pass, this
may add functions to the pass manager's work list.

This is another step in unbundling these passes from the performance
inliner.
This commit is contained in:
Mark Lacey
2015-12-20 21:04:43 -08:00
parent 4bb33dc3fd
commit 70938b1aee
9 changed files with 122 additions and 20 deletions

View File

@@ -0,0 +1,99 @@
//===-------- Devirtualizer.cpp - Devirtualize indirect calls ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Devirtualize indirect calls to functions, turning them into direct function
// references.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-devirtualizer"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
#include "swift/SILOptimizer/Utils/Devirtualize.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/ADT/SmallVector.h"
using namespace swift;
namespace {
class Devirtualizer : public SILFunctionTransform {
bool devirtualizeAppliesInFunction(SILFunction &F,
ClassHierarchyAnalysis *CHA);
/// The entry point to the transformation.
void run() override {
SILFunction &F = *getFunction();
ClassHierarchyAnalysis *CHA = PM->getAnalysis<ClassHierarchyAnalysis>();
DEBUG(llvm::dbgs() << "***** Devirtualizer on function:" << F.getName()
<< " *****\n");
if (devirtualizeAppliesInFunction(F, CHA))
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
}
StringRef getName() override { return "Devirtualizer"; }
};
} // end anonymous namespace
bool Devirtualizer::devirtualizeAppliesInFunction(SILFunction &F,
ClassHierarchyAnalysis *CHA) {
bool Changed = false;
llvm::SmallVector<SILInstruction *, 8> DeadApplies;
for (auto &BB : F) {
for (auto It = BB.begin(), End = BB.end(); It != End;) {
auto &I = *It++;
// Skip non-apply instructions.
auto Apply = FullApplySite::isa(&I);
if (!Apply)
continue;
auto NewInstPair = tryDevirtualizeApply(Apply, CHA);
if (!NewInstPair.second)
continue;
Changed = true;
auto *CalleeFn = NewInstPair.second.getCalleeFunction();
assert(CalleeFn && "Expected devirtualized callee!");
// We may not have optimized these functions yet, and it could
// be beneficial to rerun some earlier passes on the current
// function now that we've made these direct references visible.
if (CalleeFn->isDefinition() && CalleeFn->shouldOptimize())
notifyPassManagerOfFunction(CalleeFn);
auto *AI = Apply.getInstruction();
if (!isa<TryApplyInst>(AI))
AI->replaceAllUsesWith(NewInstPair.first);
DeadApplies.push_back(AI);
}
}
// Remove all the now-dead applies.
while (!DeadApplies.empty()) {
auto *AI = DeadApplies.pop_back_val();
recursivelyDeleteTriviallyDeadInstructions(AI, true);
}
return Changed;
}
SILTransform *swift::createDevirtualizer() { return new Devirtualizer(); }