Files
swift-mirror/include/swift/SILOptimizer/PassManager/PassPipeline.h
Michael Gottesman 3c61f783ea [sil-bug-reducer] Add SILPassPipeline{,Plan}. Add current pass pipelines to it.
This commit adds the functionality, but does not change SILPassManager to use
it. The reason why I am doing this is so I can implement sil-opt pass bisecting
functionality in python using a tool that dumps the current pass pipelines
out. This will ensure that even in the face of changes to the pass pipelines,
everything should just work.
2016-12-12 14:38:56 -08:00

144 lines
4.8 KiB
C++

//===--- PassPipeline.h ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 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
///
/// This file defines the SILPassPipelinePlan and SILPassPipeline
/// classes. These are higher level representations of sequences of SILPasses
/// and the run behavior of these sequences (i.e. run one, until fixed point,
/// etc). This makes it easy to serialize and deserialize pipelines without work
/// on the part of the user. Eventually this will be paired with a gyb based
/// representation of Passes.def that will able to be used to generate a python
/// based script builder.
///
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_PASSPIPELINE_H
#define SWIFT_SILOPTIMIZER_PASSMANAGER_PASSPIPELINE_H
#include "swift/Basic/LLVM.h"
#include "swift/SILOptimizer/PassManager/PassPipeline.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include <vector>
namespace swift {
class SILPassPipelinePlan;
struct SILPassPipeline;
enum class PassPipelineKind {
#define PASSPIPELINE(NAME, DESCRIPTION) NAME,
#include "swift/SILOptimizer/PassManager/PassPipeline.def"
};
class SILPassPipelinePlan final {
public:
enum class ExecutionKind {
Invalid,
OneIteration,
UntilFixPoint,
};
private:
std::vector<PassKind> Kinds;
std::vector<SILPassPipeline> PipelineStages;
public:
SILPassPipelinePlan() = default;
~SILPassPipelinePlan() = default;
SILPassPipelinePlan(const SILPassPipelinePlan &) = default;
SILPassPipelinePlan(SILPassPipelinePlan &&) = delete;
// Each pass gets its own add-function.
#define PASS(ID, NAME, DESCRIPTION) \
void add##ID() { Kinds.push_back(PassKind::ID); }
#include "swift/SILOptimizer/PassManager/Passes.def"
void addPasses(ArrayRef<PassKind> PassKinds);
#define PASSPIPELINE(NAME, DESCRIPTION) \
static SILPassPipelinePlan get##NAME##PassPipeline();
#define PASSPIPELINE_WITH_OPTIONS(NAME, DESCRIPTION) \
static SILPassPipelinePlan get##NAME##PassPipeline(SILOptions Options);
#include "swift/SILOptimizer/PassManager/PassPipeline.def"
static SILPassPipelinePlan getPassPipelineForKinds(ExecutionKind ExecKind,
ArrayRef<PassKind> Kinds);
static SILPassPipelinePlan getPassPipelineFromFile(StringRef Filename);
/// Our general format is as follows:
///
/// [
/// [
/// "PASS_MANAGER_ID",
/// "one_iteration"|"until_fix_point",
/// "PASS1", "PASS2", ...
/// ],
/// ...
/// ]
void dump();
void print(llvm::raw_ostream &os);
void startPipeline(ExecutionKind ExecKind, StringRef Name = "");
using PipelineKindIterator = decltype(Kinds)::const_iterator;
using PipelineKindRange = iterator_range<PipelineKindIterator>;
iterator_range<PipelineKindIterator>
getPipelinePasses(const SILPassPipeline &P) const;
using PipelineIterator = decltype(PipelineStages)::const_iterator;
using PipelineRange = iterator_range<PipelineIterator>;
PipelineRange getPipelines() const {
return {PipelineStages.begin(), PipelineStages.end()};
}
};
struct SILPassPipeline final {
unsigned ID;
StringRef Name;
SILPassPipelinePlan::ExecutionKind ExecutionKind;
unsigned KindOffset;
};
inline void SILPassPipelinePlan::startPipeline(ExecutionKind ExecKind,
StringRef Name) {
PipelineStages.push_back(SILPassPipeline{
unsigned(PipelineStages.size()), Name, ExecKind, unsigned(Kinds.size())});
}
inline SILPassPipelinePlan::PipelineKindRange
SILPassPipelinePlan::getPipelinePasses(const SILPassPipeline &P) const {
unsigned ID = P.ID;
assert(PipelineStages.size() > ID && "Pipeline with ID greater than the "
"size of its container?!");
// In this case, we are the last pipeline. Return end and the kind offset.
if ((PipelineStages.size() - 1) == ID) {
return {std::next(Kinds.begin(), P.KindOffset), Kinds.end()};
}
// Otherwise, end is the beginning of the next PipelineStage.
return {std::next(Kinds.begin(), P.KindOffset),
std::next(Kinds.begin(), PipelineStages[ID + 1].KindOffset)};
}
} // end namespace swift
namespace llvm {
raw_ostream &operator<<(raw_ostream &os,
swift::SILPassPipelinePlan::ExecutionKind ExecKind);
} // end namespace llvm
#endif