Skip to content

Commit e9a7427

Browse files
authored
[SILOptimizer] Add pipeline execution request (swiftlang#29552)
[SILOptimizer] Add pipeline execution request
2 parents 24d8aa1 + 13217b6 commit e9a7427

23 files changed

+417
-107
lines changed

include/swift/AST/ASTContext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ namespace swift {
110110
struct RawComment;
111111
class DocComment;
112112
class SILBoxType;
113+
class SILTransform;
113114
class TypeAliasDecl;
114115
class VarDecl;
115116
class UnifiedStatsReporter;
@@ -978,6 +979,15 @@ class ASTContext final {
978979
/// Each kind and SourceFile has its own cache for a Type.
979980
Type &getDefaultTypeRequestCache(SourceFile *, KnownProtocolKind);
980981

982+
using SILTransformCtors = ArrayRef<SILTransform *(*)(void)>;
983+
984+
/// Register IRGen specific SIL passes such that the SILOptimizer can access
985+
/// and execute them without directly depending on IRGen.
986+
void registerIRGenSILTransforms(SILTransformCtors fns);
987+
988+
/// Retrieve the IRGen specific SIL passes.
989+
SILTransformCtors getIRGenSILTransforms() const;
990+
981991
private:
982992
friend Decl;
983993
Optional<RawComment> getRawComment(const Decl *D);
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===--- SILOptimizerRequests.h - SILOptimizer Requests ---------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines SILOptimizer requests.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SILOPTIMIZER_REQUESTS_H
18+
#define SWIFT_SILOPTIMIZER_REQUESTS_H
19+
20+
#include "swift/AST/ASTTypeIDs.h"
21+
#include "swift/AST/SimpleRequest.h"
22+
23+
namespace swift {
24+
25+
namespace irgen {
26+
class IRGenModule;
27+
}
28+
29+
class SILModule;
30+
class SILPassPipelinePlan;
31+
32+
struct SILPipelineExecutionDescriptor {
33+
SILModule *SM;
34+
35+
// Note that we currently store a reference to the pipeline plan on the stack.
36+
// If ExecuteSILPipelineRequest ever becomes cached, we will need to adjust
37+
// this.
38+
const SILPassPipelinePlan &Plan;
39+
bool IsMandatory;
40+
irgen::IRGenModule *IRMod;
41+
42+
bool operator==(const SILPipelineExecutionDescriptor &other) const;
43+
bool operator!=(const SILPipelineExecutionDescriptor &other) const {
44+
return !(*this == other);
45+
}
46+
};
47+
48+
llvm::hash_code hash_value(const SILPipelineExecutionDescriptor &desc);
49+
50+
/// Executes a SIL pipeline plan on a SIL module.
51+
class ExecuteSILPipelineRequest
52+
: public SimpleRequest<ExecuteSILPipelineRequest,
53+
bool(SILPipelineExecutionDescriptor),
54+
CacheKind::Uncached> {
55+
public:
56+
using SimpleRequest::SimpleRequest;
57+
58+
private:
59+
friend SimpleRequest;
60+
61+
// Evaluation.
62+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
63+
SILPipelineExecutionDescriptor desc) const;
64+
};
65+
66+
void simple_display(llvm::raw_ostream &out,
67+
const SILPipelineExecutionDescriptor &desc);
68+
69+
SourceLoc extractNearestSourceLoc(const SILPipelineExecutionDescriptor &desc);
70+
71+
/// Report that a request of the given kind is being evaluated, so it
72+
/// can be recorded by the stats reporter.
73+
template <typename Request>
74+
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
75+
const Request &request);
76+
77+
/// The zone number for SILOptimizer.
78+
#define SWIFT_TYPEID_ZONE SILOptimizer
79+
#define SWIFT_TYPEID_HEADER "swift/AST/SILOptimizerTypeIDZone.def"
80+
#include "swift/Basic/DefineTypeIDZone.h"
81+
#undef SWIFT_TYPEID_ZONE
82+
#undef SWIFT_TYPEID_HEADER
83+
84+
// Set up reporting of evaluated requests.
85+
#define SWIFT_REQUEST(Zone, RequestType, Sig, Caching, LocOptions) \
86+
template<> \
87+
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
88+
const RequestType &request) { \
89+
++stats.getFrontendCounters().RequestType; \
90+
}
91+
#include "swift/AST/SILOptimizerTypeIDZone.def"
92+
#undef SWIFT_REQUEST
93+
94+
} // end namespace swift
95+
96+
#endif // SWIFT_SILOPTIMIZER_REQUESTS_H
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===--- SILOptimizerTypeIDZone.def -----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This definition file describes the requests in SILOptimizer's zone.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
SWIFT_REQUEST(SILOptimizer, ExecuteSILPipelineRequest,
18+
bool(SILPipelineExecutionDescriptor), Uncached, NoLocationInfo)

include/swift/Basic/Statistics.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@ FRONTEND_STATISTIC(SILModule, NumSILGenWitnessTables)
280280
FRONTEND_STATISTIC(SILModule, NumSILGenDefaultWitnessTables)
281281
FRONTEND_STATISTIC(SILModule, NumSILGenGlobalVariables)
282282

283+
#define SWIFT_REQUEST(ZONE, NAME, Sig, Caching, LocOptions) FRONTEND_STATISTIC(SILOptimizer, NAME)
284+
#include "swift/AST/SILOptimizerTypeIDZone.def"
285+
#undef SWIFT_REQUEST
286+
283287
FRONTEND_STATISTIC(SILModule, NumSILOptFunctions)
284288
FRONTEND_STATISTIC(SILModule, NumSILOptVtables)
285289
FRONTEND_STATISTIC(SILModule, NumSILOptWitnessTables)

include/swift/Basic/TypeID.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ enum class Zone : uint8_t {
3838
Parse = 8,
3939
TypeChecker = 10,
4040
SILGen = 12,
41+
SILOptimizer = 13,
4142
TBDGen = 14,
4243
// N.B. This is not a formal zone and exists solely to support the unit tests.
4344
ArithmeticEvaluator = 255,

include/swift/SIL/SILModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,13 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){
777777
return OS;
778778
}
779779

780+
/// Print a simple description of a SILModule for the request evaluator.
781+
void simple_display(llvm::raw_ostream &out, const SILModule *M);
782+
783+
/// Retrieve a SourceLoc for a SILModule that the request evaluator can use for
784+
/// diagnostics.
785+
SourceLoc extractNearestSourceLoc(const SILModule *SM);
786+
780787
namespace Lowering {
781788
/// Determine whether the given class will be allocated/deallocated using the
782789
/// Objective-C runtime, i.e., +alloc and -dealloc.

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,15 @@ namespace irgen {
3737
class IRGenModule;
3838
}
3939

40+
/// The main entrypoint for executing a pipeline pass on a SIL module.
41+
void executePassPipelinePlan(SILModule *SM, const SILPassPipelinePlan &plan,
42+
bool isMandatory = false,
43+
irgen::IRGenModule *IRMod = nullptr);
44+
4045
/// The SIL pass manager.
4146
class SILPassManager {
47+
friend class ExecuteSILPipelineRequest;
48+
4249
/// The module that the pass manager will transform.
4350
SILModule *Mod;
4451

@@ -99,9 +106,6 @@ class SILPassManager {
99106
/// OptimizationMode::NoOptimization.
100107
bool isMandatory = false;
101108

102-
/// The IRGen SIL passes. These have to be dynamically added by IRGen.
103-
llvm::DenseMap<unsigned, SILTransform *> IRGenPasses;
104-
105109
/// The notification handler for this specific SILPassManager.
106110
///
107111
/// This is not owned by the pass manager, it is owned by the SILModule which
@@ -110,20 +114,12 @@ class SILPassManager {
110114
/// pass manager is destroyed.
111115
DeserializationNotificationHandler *deserializationNotificationHandler;
112116

113-
public:
114117
/// C'tor. It creates and registers all analysis passes, which are defined
115-
/// in Analysis.def.
116-
///
117-
/// If \p isMandatory is true, passes are also run for functions
118-
/// which have OptimizationMode::NoOptimization.
119-
SILPassManager(SILModule *M, llvm::StringRef Stage = "",
120-
bool isMandatory = false);
121-
122-
/// C'tor. It creates an IRGen pass manager. Passes can query for the
123-
/// IRGenModule.
124-
SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
125-
llvm::StringRef Stage = "", bool isMandatory = false);
118+
/// in Analysis.def. This is private as it should only be used by
119+
/// ExecuteSILPipelineRequest.
120+
SILPassManager(SILModule *M, bool isMandatory, irgen::IRGenModule *IRMod);
126121

122+
public:
127123
const SILOptions &getOptions() const;
128124

129125
/// Searches for an analysis of type T in the list of registered
@@ -269,15 +265,6 @@ class SILPassManager {
269265
}
270266
}
271267

272-
void registerIRGenPass(PassKind Kind, SILTransform *Transform) {
273-
assert(IRGenPasses.find(unsigned(Kind)) == IRGenPasses.end() &&
274-
"Pass already registered");
275-
assert(
276-
IRMod &&
277-
"Attempting to register an IRGen pass with a non-IRGen pass manager");
278-
IRGenPasses[unsigned(Kind)] = Transform;
279-
}
280-
281268
private:
282269
void execute();
283270

include/swift/SILOptimizer/PassManager/PassPipeline.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/Basic/LLVM.h"
2929
#include "swift/SILOptimizer/PassManager/PassPipeline.h"
3030
#include "swift/SILOptimizer/PassManager/Passes.h"
31+
#include "llvm/ADT/Hashing.h"
3132
#include <vector>
3233

3334
namespace swift {
@@ -98,12 +99,50 @@ class SILPassPipelinePlan final {
9899
PipelineRange getPipelines() const {
99100
return {PipelineStages.begin(), PipelineStages.end()};
100101
}
102+
103+
friend bool operator==(const SILPassPipelinePlan &lhs,
104+
const SILPassPipelinePlan &rhs) {
105+
// FIXME: Comparing the SILOptions by identity should work in practice, but
106+
// we don't currently prevent them from being copied. We should consider
107+
// either making them move-only, or properly implementing == for them.
108+
return &lhs.Options == &rhs.Options && lhs.Kinds == rhs.Kinds &&
109+
lhs.PipelineStages == rhs.PipelineStages;
110+
}
111+
112+
friend bool operator!=(const SILPassPipelinePlan &lhs,
113+
const SILPassPipelinePlan &rhs) {
114+
return !(lhs == rhs);
115+
}
116+
117+
friend llvm::hash_code hash_value(const SILPassPipelinePlan &plan) {
118+
using namespace llvm;
119+
auto &kinds = plan.Kinds;
120+
auto &stages = plan.PipelineStages;
121+
return hash_combine(&plan.Options,
122+
hash_combine_range(kinds.begin(), kinds.end()),
123+
hash_combine_range(stages.begin(), stages.end()));
124+
}
101125
};
102126

103127
struct SILPassPipeline final {
104128
unsigned ID;
105129
StringRef Name;
106130
unsigned KindOffset;
131+
132+
friend bool operator==(const SILPassPipeline &lhs,
133+
const SILPassPipeline &rhs) {
134+
return lhs.ID == rhs.ID && lhs.Name.equals(rhs.Name) &&
135+
lhs.KindOffset == rhs.KindOffset;
136+
}
137+
138+
friend bool operator!=(const SILPassPipeline &lhs,
139+
const SILPassPipeline &rhs) {
140+
return !(lhs == rhs);
141+
}
142+
143+
friend llvm::hash_code hash_value(const SILPassPipeline &pipeline) {
144+
return llvm::hash_combine(pipeline.ID, pipeline.Name, pipeline.KindOffset);
145+
}
107146
};
108147

109148
inline void SILPassPipelinePlan::startPipeline(StringRef Name) {

include/swift/Subsystems.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,12 @@ namespace swift {
368368
/// should call this functions after forming the ASTContext.
369369
void registerSILGenRequestFunctions(Evaluator &evaluator);
370370

371+
/// Register SILOptimizer-level request functions with the evaluator.
372+
///
373+
/// Clients that form an ASTContext and will perform any SIL optimization
374+
/// should call this functions after forming the ASTContext.
375+
void registerSILOptimizerRequestFunctions(Evaluator &evaluator);
376+
371377
/// Register TBDGen-level request functions with the evaluator.
372378
///
373379
/// Clients that form an ASTContext and will perform any TBD generation
@@ -385,6 +391,9 @@ namespace swift {
385391
/// Calling registerIDERequestFunctions will invoke this function as well.
386392
void registerIDETypeCheckRequestFunctions(Evaluator &evaluator);
387393

394+
/// Register SILOptimizer passes necessary for IRGen.
395+
void registerIRGenSILTransforms(ASTContext &ctx);
396+
388397
} // end namespace swift
389398

390399
#endif // SWIFT_SUBSYSTEMS_H

lib/AST/ASTContext.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,9 @@ struct ASTContext::Implementation {
473473
llvm::DenseMap<OverrideSignatureKey, GenericSignature> overrideSigCache;
474474

475475
Optional<ClangTypeConverter> Converter;
476+
477+
/// The IRGen specific SIL transforms that have been registered.
478+
SILTransformCtors IRGenSILPasses;
476479
};
477480

478481
ASTContext::Implementation::Implementation()
@@ -4576,6 +4579,17 @@ bool ASTContext::overrideGenericSignatureReqsSatisfied(
45764579
llvm_unreachable("Unhandled OverrideGenericSignatureReqCheck in switch");
45774580
}
45784581

4582+
void ASTContext::registerIRGenSILTransforms(SILTransformCtors ctors) {
4583+
assert(getImpl().IRGenSILPasses.empty() && "Already registered");
4584+
getImpl().IRGenSILPasses = ctors;
4585+
}
4586+
4587+
ASTContext::SILTransformCtors ASTContext::getIRGenSILTransforms() const {
4588+
auto passes = getImpl().IRGenSILPasses;
4589+
assert(!passes.empty() && "Didn't register the necessary passes");
4590+
return passes;
4591+
}
4592+
45794593
SILLayout *SILLayout::get(ASTContext &C,
45804594
CanGenericSignature Generics,
45814595
ArrayRef<SILField> Fields) {

0 commit comments

Comments
 (0)