mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This pass is a port of InstCombine from LLVM to SIL. Thus if you are familiar with the code from InstCombine you will feel right at home. Keep in mind that in order to help with review, this is just a skeleton with no optimizations in it besides a simple DCE based off of isInstructionTriviallyDead (which this patch exposes in Local.h like LLVM does) to ensure that trivial testing of the pass can be accomplished since otherwise it would do nothing implying that no tests could be written at all. I additionally modified one test which no longer passed due to SILCombine removing 1x unused metatype instruction from the standard library. Swift SVN r9404
204 lines
7.0 KiB
C++
204 lines
7.0 KiB
C++
//===-- SILOpt.cpp - SIL Optimization Driver ------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This is the entry point.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/Subsystems.h"
|
|
#include "swift/Frontend/DiagnosticVerifier.h"
|
|
#include "swift/Frontend/Frontend.h"
|
|
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/Signals.h"
|
|
using namespace swift;
|
|
|
|
enum class PassKind {
|
|
AllocBoxToStack,
|
|
DefiniteInit,
|
|
CCP,
|
|
DCE,
|
|
DataflowDiagnostics,
|
|
InOutDeshadowing,
|
|
MandatoryInlining,
|
|
CapturePromotion,
|
|
SILCleanup,
|
|
SILCombine
|
|
};
|
|
|
|
static llvm::cl::opt<std::string>
|
|
InputFilename(llvm::cl::desc("input file"), llvm::cl::init("-"),
|
|
llvm::cl::Positional);
|
|
|
|
static llvm::cl::opt<std::string>
|
|
OutputFilename("o", llvm::cl::desc("output filename"), llvm::cl::init("-"));
|
|
|
|
static llvm::cl::list<std::string>
|
|
ImportPaths("I", llvm::cl::desc("add a directory to the import search path"));
|
|
|
|
static llvm::cl::list<PassKind>
|
|
Passes(llvm::cl::desc("Passes:"),
|
|
llvm::cl::values(clEnumValN(PassKind::AllocBoxToStack,
|
|
"allocbox-to-stack", "Promote memory"),
|
|
clEnumValN(PassKind::DefiniteInit,
|
|
"definite-init","definitive initialization"),
|
|
clEnumValN(PassKind::CCP,
|
|
"constant-propagation",
|
|
"Propagate constants"),
|
|
clEnumValN(PassKind::DCE,
|
|
"dead-code-elimination", "Remove dead code"),
|
|
clEnumValN(PassKind::DataflowDiagnostics,
|
|
"dataflow-diagnostics",
|
|
"Emit SIL diagnostics"),
|
|
clEnumValN(PassKind::InOutDeshadowing,
|
|
"inout-deshadow",
|
|
"Remove inout argument shadow variables"),
|
|
clEnumValN(PassKind::MandatoryInlining,
|
|
"mandatory-inlining",
|
|
"Inline transparent functions"),
|
|
clEnumValN(PassKind::CapturePromotion,
|
|
"capture-promotion",
|
|
"Promote closure capture variables"),
|
|
clEnumValN(PassKind::SILCleanup,
|
|
"cleanup",
|
|
"Cleanup SIL in preparation for IRGen"),
|
|
clEnumValN(PassKind::SILCombine,
|
|
"sil-combine",
|
|
"Perform small peepholes/combine operations/"
|
|
"dead code elimination."),
|
|
clEnumValEnd));
|
|
|
|
static llvm::cl::opt<bool>
|
|
PrintStats("print-stats", llvm::cl::desc("Print various statistics"));
|
|
|
|
static llvm::cl::opt<bool>
|
|
VerifyMode("verify",
|
|
llvm::cl::desc("verify diagnostics against expected-"
|
|
"{error|warning|note} annotations"));
|
|
|
|
|
|
static llvm::cl::opt<bool>
|
|
EmitVerboseSIL("emit-verbose-sil",
|
|
llvm::cl::desc("Emit locations during sil emission."));
|
|
|
|
// This function isn't referenced outside its translation unit, but it
|
|
// can't use the "static" keyword because its address is used for
|
|
// getMainExecutable (since some platforms don't support taking the
|
|
// address of main, and some platforms can't implement getMainExecutable
|
|
// without being given the address of a function in the main executable).
|
|
void anchorForGetMainExecutable() {}
|
|
|
|
int main(int argc, char **argv) {
|
|
// Print a stack trace if we signal out.
|
|
llvm::sys::PrintStackTraceOnErrorSignal();
|
|
llvm::PrettyStackTraceProgram X(argc, argv);
|
|
|
|
llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n");
|
|
|
|
if (PrintStats)
|
|
llvm::EnableStatistics();
|
|
|
|
CompilerInvocation Invocation;
|
|
|
|
Invocation.setMainExecutablePath(
|
|
llvm::sys::fs::getMainExecutable(argv[0],
|
|
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
|
|
|
// Give the context the list of search paths to use for modules.
|
|
Invocation.setImportSearchPaths(ImportPaths);
|
|
|
|
Invocation.setModuleName("main");
|
|
Invocation.setInputKind(SourceFile::SIL);
|
|
|
|
Invocation.addInputFilename(InputFilename);
|
|
|
|
CompilerInstance CI;
|
|
PrintingDiagnosticConsumer PrintDiags;
|
|
CI.addDiagnosticConsumer(&PrintDiags);
|
|
|
|
if (CI.setup(Invocation))
|
|
return 1;
|
|
CI.doIt();
|
|
|
|
// If parsing produced an error, don't run any passes.
|
|
if (CI.getASTContext().hadError())
|
|
return 1;
|
|
|
|
// If we're in verify mode, install a custom diagnostic handling for
|
|
// SourceMgr.
|
|
if (VerifyMode)
|
|
enableDiagnosticVerifier(CI.getSourceMgr());
|
|
|
|
for (auto Pass : Passes) {
|
|
switch (Pass) {
|
|
case PassKind::AllocBoxToStack:
|
|
performSILAllocBoxToStackPromotion(CI.getSILModule());
|
|
break;
|
|
case PassKind::DefiniteInit:
|
|
performSILDefiniteInitialization(CI.getSILModule());
|
|
break;
|
|
case PassKind::CCP:
|
|
performSILConstantPropagation(CI.getSILModule());
|
|
break;
|
|
case PassKind::DCE:
|
|
performSILDeadCodeElimination(CI.getSILModule());
|
|
break;
|
|
case PassKind::DataflowDiagnostics:
|
|
emitSILDataflowDiagnostics(CI.getSILModule());
|
|
break;
|
|
case PassKind::InOutDeshadowing:
|
|
performInOutDeshadowing(CI.getSILModule());
|
|
break;
|
|
case PassKind::MandatoryInlining:
|
|
performSILMandatoryInlining(CI.getSILModule());
|
|
break;
|
|
case PassKind::CapturePromotion:
|
|
performSILCapturePromotion(CI.getSILModule());
|
|
break;
|
|
case PassKind::SILCleanup:
|
|
performSILCleanup(CI.getSILModule());
|
|
break;
|
|
case PassKind::SILCombine:
|
|
performSILCombine(CI.getSILModule());
|
|
break;
|
|
}
|
|
|
|
// Verify the module after every pass.
|
|
CI.getSILModule()->verify(CI.getTU());
|
|
}
|
|
|
|
std::string ErrorInfo;
|
|
llvm::raw_fd_ostream OS(OutputFilename.c_str(), ErrorInfo);
|
|
if (!ErrorInfo.empty()) {
|
|
llvm::errs() << "while opening '" << OutputFilename << "': "
|
|
<< ErrorInfo << '\n';
|
|
return 1;
|
|
}
|
|
CI.getSILModule()->print(OS, EmitVerboseSIL);
|
|
|
|
// Print statistics.
|
|
if (PrintStats)
|
|
llvm::PrintStatistics(llvm::errs());
|
|
|
|
bool HadError = CI.getASTContext().hadError();
|
|
|
|
// If we're in -verify mode, we've buffered up all of the generated
|
|
// diagnostics. Check now to ensure that they meet our expectations.
|
|
if (VerifyMode)
|
|
HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs());
|
|
|
|
|
|
return HadError;
|
|
}
|