Skip to content

SILOptimizer: some compile time fixes #23931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions include/swift/SILOptimizer/Utils/PerformanceInlinerUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ class ShortestPathAnalysis {
SILLoopInfo *LI;
llvm::DenseMap<const SILBasicBlock *, BlockInfo *> BlockInfos;
std::vector<BlockInfo> BlockInfoStorage;
bool valid = false;

BlockInfo *getBlockInfo(const SILBasicBlock *BB) {
BlockInfo *BI = BlockInfos[BB];
Expand Down Expand Up @@ -381,15 +382,22 @@ class ShortestPathAnalysis {
public:
ShortestPathAnalysis(SILFunction *F, SILLoopInfo *LI) : F(F), LI(LI) { }

bool isValid() const { return !BlockInfos.empty(); }
bool isValid() const { return valid; }

/// Compute the distances. The function \p getApplyLength returns the length
/// of a function call.
template <typename Func>
void analyze(ColdBlockInfo &CBI, Func getApplyLength) {
assert(!isValid());
valid = true;
unsigned numBlocks = F->size();

BlockInfoStorage.resize(F->size());
// As the complexity of the analysis is more than linear with the number of blocks,
// disable it for huge functions. In this case inlining will be less aggressive.
if (numBlocks > 2000)
return;

BlockInfoStorage.resize(numBlocks);

// First step: compute the length of the blocks.
unsigned BlockIdx = 0;
Expand Down Expand Up @@ -433,6 +441,11 @@ class ShortestPathAnalysis {
/// shortest path in the function.
int getScopeLength(SILBasicBlock *BB, int LoopDepth) {
assert(BB->getParent() == F);

// Return a conservative default if the analysis was not done due to a high number of blocks.
if (BlockInfos.empty())
return ColdBlockLength;

if (LoopDepth >= MaxNumLoopLevels)
LoopDepth = MaxNumLoopLevels - 1;
return getBlockInfo(BB)->getScopeLength(LoopDepth);
Expand Down
21 changes: 15 additions & 6 deletions lib/SILOptimizer/Transforms/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ namespace {

ConstantFolder ConstFolder;

// True if the function has a large amount of blocks. In this case we turn off some expensive
// optimizations.
bool isVeryLargeFunction = false;

void constFoldingCallback(SILInstruction *I) {
// If a terminal instruction gets constant folded (like cond_br), it
// enables further simplify-CFG optimizations.
Expand Down Expand Up @@ -1226,11 +1230,13 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
if (DestBB->getArgument(i) != BI->getArg(i)) {
SILValue Val = BI->getArg(i);
DestBB->getArgument(i)->replaceAllUsesWith(Val);
if (auto *I = dyn_cast<SingleValueInstruction>(Val)) {
// Replacing operands may trigger constant folding which then could
// trigger other simplify-CFG optimizations.
ConstFolder.addToWorklist(I);
ConstFolder.processWorkList();
if (!isVeryLargeFunction) {
if (auto *I = dyn_cast<SingleValueInstruction>(Val)) {
// Replacing operands may trigger constant folding which then could
// trigger other simplify-CFG optimizations.
ConstFolder.addToWorklist(I);
ConstFolder.processWorkList();
}
}
} else {
// We must be processing an unreachable part of the cfg with a cycle.
Expand Down Expand Up @@ -1290,7 +1296,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
// If this unconditional branch has BBArgs, check to see if duplicating the
// destination would allow it to be simplified. This is a simple form of jump
// threading.
if (!BI->getArgs().empty() &&
if (!isVeryLargeFunction && !BI->getArgs().empty() &&
tryJumpThreading(BI))
return true;

Expand Down Expand Up @@ -3067,6 +3073,9 @@ bool SimplifyCFG::run() {

LLVM_DEBUG(llvm::dbgs() << "### Run SimplifyCFG on " << Fn.getName() << '\n');

// Disable some expensive optimizations if the function is huge.
isVeryLargeFunction = (Fn.size() > 10000);

// First remove any block not reachable from the entry.
bool Changed = removeUnreachableBlocks(Fn);

Expand Down
4 changes: 4 additions & 0 deletions lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ ShortestPathAnalysis::Weight ShortestPathAnalysis::
getWeight(SILBasicBlock *BB, Weight CallerWeight) {
assert(BB->getParent() == F);

// Return a conservative default if the analysis was not done due to a high number of blocks.
if (BlockInfos.empty())
return Weight(CallerWeight.ScopeLength + ColdBlockLength, CallerWeight.LoopWeight);

SILLoop *Loop = LI->getLoopFor(BB);
if (!Loop) {
// We are not in a loop. So just account the length of our function scope
Expand Down