Files
swift-mirror/lib/SILPasses/Passes.cpp
Arnold Schwaighofer 39e77dc7c6 Enable loop rotation and LICM
We want this to get tested.

O3:
Ackermann 8.0%
GlobalClass 30.8%
R17315246 -50.2%
Phonebook 7.4%

Ofast:
RC4 -9.7%

The R17315246 regression is because LLVM seems to unable to 'unswitch' the loop
that makes up this benchmark after rotation. The only explaination I have atm is
that after rotation the first exit is a cond_fail.

I looked at RC4's profile and did not see anything suspicious. I was chasing a
10% regression yesterday in phonebook (today it seems i see about 7%
improvement). So I am not sure how 'stable' wrt to cache effects our benchmarks
are (we are calling into runtimes and whatnot).

Swift SVN r20098
2014-07-17 16:12:45 +00:00

229 lines
6.9 KiB
C++

//===-------- Passes.cpp - Swift Compiler SIL Pass Entrypoints ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file provides implementations of a few helper functions
/// which provide abstracted entrypoints to the SILPasses stage.
///
/// \note The actual SIL passes should be implemented in per-pass source files,
/// not in this file.
///
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-optimizer"
#include "swift/SILPasses/Passes.h"
#include "swift/SILPasses/PassManager.h"
#include "swift/SILPasses/Transforms.h"
#include "swift/SILAnalysis/Analysis.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
#include "swift/AST/SILOptions.h"
#include "swift/SIL/SILModule.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
using namespace swift;
static void registerAnalysisPasses(SILPassManager &PM, SILModule *Mod) {
PM.registerAnalysis(createCallGraphAnalysis(Mod));
PM.registerAnalysis(createAliasAnalysis(Mod));
PM.registerAnalysis(createDominanceAnalysis(Mod));
PM.registerAnalysis(createLoopInfoAnalysis(Mod, &PM));
PM.registerAnalysis(createInductionVariableAnalysis(Mod));
PM.registerAnalysis(createPostOrderAnalysis(Mod));
}
bool swift::runSILDiagnosticPasses(SILModule &Module,
const SILOptions &Options) {
// If we parsed a .sil file that is already in canonical form, don't rerun
// the diagnostic passes.
if (Module.getStage() == SILStage::Canonical)
return false;
auto &Ctx = Module.getASTContext();
SILPassManager PM(&Module, Options);
registerAnalysisPasses(PM, &Module);
// If we are asked do debug serialization, instead of running all diagnostic
// passes, just run mandatory inlining with dead transparent function cleanup
// disabled.
PM.add(createMandatoryInlining());
if (Options.DebugSerialization) {
PM.run();
return Ctx.hadError();
}
// Otherwise run the rest of diagnostics.
PM.add(createCapturePromotion());
PM.add(createAllocBoxToStack());
PM.add(createInOutDeshadowing());
PM.add(createNoReturnFolding());
PM.add(createDefiniteInitialization());
PM.add(createPredictableMemoryOptimizations());
PM.add(createDiagnosticConstantPropagation());
PM.add(createDiagnoseUnreachable());
PM.add(createEmitDFDiagnostics());
PM.run();
// Generate diagnostics.
Module.setStage(SILStage::Canonical);
// If errors were produced during SIL analysis, return true.
return Ctx.hadError();
}
/// Perform semantic annotation/loop base optimizations.
void AddHighLevelLoopOptPasses(SILPassManager &PM, SILModule &Mod) {
// Perform classsic SSA optimizations for cleanup.
PM.add(createLowerAggregate());
PM.add(createSILCombine());
PM.add(createSROA());
PM.add(createMem2Reg());
PM.add(createDCE());
PM.add(createSILCombine());
PM.add(createSimplifyCFG());
// Run high-level loop opts.
PM.add(createLoopRotatePass());
// Cleanup.
PM.add(createDCE());
PM.add(createCSE());
PM.add(createSILCombine());
PM.add(createSimplifyCFG());
}
void AddLowLevelLoopOptPasses(SILPassManager &PM, SILModule &Mod) {
PM.add(createLICMPass());
PM.add(createDCE());
PM.add(createCSE());
PM.add(createSILCombine());
PM.add(createSimplifyCFG());
}
void AddSSAPasses(SILPassManager &PM, SILModule &Module,
bool useEarlyInliner) {
PM.add(createSimplifyCFG());
PM.add(createAllocBoxToStack());
PM.add(createLowerAggregate());
PM.add(createSILCombine());
PM.add(createSROA());
PM.add(createMem2Reg());
// Perform classsic SSA optimizations.
PM.add(createPerformanceConstantPropagation());
PM.add(createDCE());
PM.add(createCSE());
PM.add(createSILCombine());
PM.add(createSimplifyCFG());
// Perform retain/release code motion and run the first ARC optimizer.
PM.add(createLoadStoreOpts());
PM.add(createCodeMotion());
PM.add(createEnumSimplification());
PM.add(createGlobalARCOpts());
// Devirtualize.
PM.add(createDevirtualization());
PM.add(createGenericSpecializer());
PM.add(createSILLinker());
// Use either the early inliner that does not inline functions with defined
// semantics or the late performance inliner that inlines everything.
PM.add(useEarlyInliner ? createEarlyInliner() : createPerfInliner());
PM.add(createSimplifyCFG());
PM.add(createGlobalARCOpts());
}
void swift::runSILOptimizationPasses(SILModule &Module,
const SILOptions &Options) {
if (Options.DebugSerialization) {
SILPassManager PM(&Module, Options);
registerAnalysisPasses(PM, &Module);
PM.add(createSILLinker());
PM.run();
return;
}
SILPassManager PM(&Module, Options);
registerAnalysisPasses(PM, &Module);
// Start by specializing generics and by cloning functions from stdlib.
PM.add(createSILLinker());
PM.add(createGenericSpecializer());
PM.run();
PM.resetAndRemoveTransformations();
// Run two iterations of the high-level SSA passes.
AddSSAPasses(PM, Module, true);
PM.runOneIteration();
PM.runOneIteration();
#if 0
PM.resetAndRemoveTransformations();
#else
// Run the high-level loop optimization passes.
PM.resetAndRemoveTransformations();
AddHighLevelLoopOptPasses(PM, Module);
PM.runOneIteration();
PM.resetAndRemoveTransformations();
#endif
// Run two iterations of the low-level SSA passes.
AddSSAPasses(PM, Module, false);
PM.runOneIteration();
PM.runOneIteration();
PM.resetAndRemoveTransformations();
// Perform lowering optimizations.
PM.add(createDeadFunctionElimination());
PM.add(createDeadObjectElimination());
// Hoist globals out of loops.
PM.add(createGlobalOpt());
// Insert inline caches for virtual calls.
PM.add(createDevirtualization());
PM.add(createInlineCaches());
PM.run();
PM.resetAndRemoveTransformations();
// Run another iteration of the SSA optimizations to optimize the
// devirtualized inline caches.
AddSSAPasses(PM, Module, false);
PM.runOneIteration();
#if 1
PM.resetAndRemoveTransformations();
// TODO: this should run as part of the last iteration of the previous
// pass manager so that we can reuse analysis info.
AddLowLevelLoopOptPasses(PM, Module);
PM.runOneIteration();
#endif
// Invalidate the SILLoader and allow it to drop references to SIL functions.
Module.invalidateSILLoader();
performSILElimination(&Module);
// Gather instruction counts if we are asked to do so.
if (Options.PrintInstCounts) {
SILPassManager PrinterPM(&Module, Options);
PrinterPM.add(createSILInstCount());
PrinterPM.runOneIteration();
}
DEBUG(Module.verify());
}