Skip to content

Commit cff61d7

Browse files
committed
Implement a function signature cloner and rewriter.
This split the function signature module pass into 2 functin passes. By doing so, this allows us to rewrite to using the FSO-optimized function prior to attempting inlining, but allow us to do a substantial amount of optimization on the current function before attempting to do FSO on that function. And also helps us to move to a model which module pass is NOT used unless necesary. I do not see regression nor improvement for on the performance test suite. functionsignopts.sil and functionsignopt_sroa.sil are modified because the mangler now takes into account of information in the projection tree.
1 parent 07c892c commit cff61d7

File tree

15 files changed

+1116
-51
lines changed

15 files changed

+1116
-51
lines changed

include/swift/SIL/Projection.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,8 @@ class ProjectionTreeNode {
772772
NullablePtr<SILInstruction> createProjection(SILBuilder &B, SILLocation Loc,
773773
SILValue Arg) const;
774774

775+
std::string getNameEncoding(const ProjectionTree &PT) const;
776+
775777
SILInstruction *
776778
createAggregate(SILBuilder &B, SILLocation Loc,
777779
ArrayRef<SILValue> Args) const;
@@ -846,6 +848,9 @@ class ProjectionTree {
846848
/// All debug instructions (debug_value, debug_value_addr) are ignored.
847849
void computeUsesAndLiveness(SILValue Base);
848850

851+
/// Return a name encoding of the projection tree.
852+
std::string getNameEncoding() const;
853+
849854
/// Initialize an empty projection tree with an existing, computed projection
850855
/// tree.
851856
void initializeWithExistingTree(const ProjectionTree &PT);

include/swift/SILOptimizer/Analysis/FunctionSignatureAnalysis.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ struct ResultDescriptor {
174174
};
175175

176176
class FunctionSignatureInfo {
177+
/// Have the signature be computed for this function.
178+
bool SignatureComputed;
179+
180+
/// Should we optimize the signature for this function.
181+
bool SignatureOptimize;
182+
177183
/// Function currently analyzing.
178184
SILFunction *F;
179185

@@ -204,9 +210,10 @@ class FunctionSignatureInfo {
204210

205211

206212
public:
207-
FunctionSignatureInfo(SILFunction *F, llvm::BumpPtrAllocator &BPA, AliasAnalysis *AA,
208-
RCIdentityFunctionInfo *RCFI) :
209-
F(F), Allocator(BPA), AA(AA), RCFI(RCFI), MayBindDynamicSelf(computeMayBindDynamicSelf(F)) {}
213+
FunctionSignatureInfo(SILFunction *F, llvm::BumpPtrAllocator &BPA,
214+
AliasAnalysis *AA, RCIdentityFunctionInfo *RCFI) :
215+
SignatureComputed(false), SignatureOptimize(false), F(F), Allocator(BPA),
216+
AA(AA), RCFI(RCFI), MayBindDynamicSelf(computeMayBindDynamicSelf(F)) {}
210217

211218
bool analyze();
212219
bool analyzeParameters();

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ PASS(FunctionOrderPrinter, "function-order-printer",
104104
"Print function orderings for test purposes")
105105
PASS(FunctionSignatureOpts, "function-signature-opts",
106106
"Optimize Function Signatures")
107+
PASS(FunctionSignatureOptCloner, "function-signature-opt-cloner",
108+
"Create function with optimized signatures")
109+
PASS(FunctionSignatureOptRewriter, "function-signature-opt-rewriter",
110+
"Optimize Function Signatures by rewriting callsites")
107111
PASS(ARCSequenceOpts, "arc-sequence-opts",
108112
"Optimize sequences of retain/release opts by removing redundant inner "
109113
"retain/release sequences")
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===--- FunctionSignatureOptUtils.h ----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SIL_FUNCTIONSIGOPTUTILS_H
14+
#define SWIFT_SIL_FUNCTIONSIGOPTUTILS_H
15+
16+
#include "swift/SIL/SILFunction.h"
17+
#include "swift/SIL/SILInstruction.h"
18+
#include "swift/SIL/SILDebugScope.h"
19+
#include "swift/SILOptimizer/Analysis/FunctionSignatureAnalysis.h"
20+
21+
namespace swift {
22+
23+
bool canSpecializeFunction(SILFunction *F);
24+
25+
void
26+
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
27+
SILLocation Loc,
28+
OperandValueArrayRef Parameters,
29+
ArrayRef<ArgumentDescriptor> &ArgDescs);
30+
31+
void
32+
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
33+
SILLocation Loc,
34+
ArrayRef<SILArgument*> Parameters,
35+
ArrayRef<ArgumentDescriptor> &ArgDescs);
36+
void
37+
addRetainsForConvertedDirectResults(SILBuilder &Builder,
38+
SILLocation Loc,
39+
SILValue ReturnValue,
40+
SILInstruction *AI,
41+
ArrayRef<ResultDescriptor> DirectResults);
42+
43+
} // end namespace swift
44+
45+
#endif

lib/SIL/Projection.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,19 @@ createProjection(SILBuilder &B, SILLocation Loc, SILValue Arg) const {
875875
return Proj->createProjection(B, Loc, Arg);
876876
}
877877

878+
std::string
879+
ProjectionTreeNode::getNameEncoding(const ProjectionTree &PT) const {
880+
std::string Encoding;
881+
const ProjectionTreeNode *Node = this;
882+
while(Node) {
883+
if (Node->isRoot())
884+
break;
885+
Encoding += std::to_string(Node->Proj->getIndex());
886+
Node = Node->getParent(PT);
887+
}
888+
return Encoding;
889+
}
890+
878891
void
879892
ProjectionTreeNode::
880893
processUsersOfValue(ProjectionTree &Tree,
@@ -1182,6 +1195,15 @@ ProjectionTree::initializeWithExistingTree(const ProjectionTree &PT) {
11821195
}
11831196
}
11841197

1198+
std::string ProjectionTree::getNameEncoding() const {
1199+
std::string Encoding;
1200+
for (unsigned index : LiveLeafIndices) {
1201+
const ProjectionTreeNode *Node = ProjectionTreeNodes[index];
1202+
Encoding += Node->getNameEncoding(*this);
1203+
}
1204+
return Encoding;
1205+
}
1206+
11851207
SILValue
11861208
ProjectionTree::computeExplodedArgumentValueInner(SILBuilder &Builder,
11871209
SILLocation Loc,

lib/SILOptimizer/Analysis/FunctionSignatureAnalysis.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ bool FunctionSignatureInfo::analyzeParameters() {
130130
RCFI, F, ConsumedArgToEpilogueReleaseMatcher::ExitKind::Throw);
131131

132132
// Did we decide we should optimize any parameter?
133-
bool ShouldOptimize = false;
133+
bool SignatureOptimize = false;
134134

135135
// Analyze the argument information.
136136
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
@@ -183,7 +183,7 @@ bool FunctionSignatureInfo::analyzeParameters() {
183183
}
184184

185185
if (HaveOptimizedArg) {
186-
ShouldOptimize = true;
186+
SignatureOptimize = true;
187187
// Store that we have modified the self argument. We need to change the
188188
// calling convention later.
189189
if (Args[i]->isSelf())
@@ -194,7 +194,7 @@ bool FunctionSignatureInfo::analyzeParameters() {
194194
ArgDescList.push_back(std::move(A));
195195
}
196196

197-
return ShouldOptimize;
197+
return SignatureOptimize;
198198
}
199199

200200
bool FunctionSignatureInfo::analyzeResult() {
@@ -203,7 +203,7 @@ bool FunctionSignatureInfo::analyzeResult() {
203203
return false;
204204

205205
// Did we decide we should optimize any parameter?
206-
bool ShouldOptimize = false;
206+
bool SignatureOptimize = false;
207207

208208
// Analyze return result information.
209209
auto DirectResults = F->getLoweredFunctionType()->getDirectResults();
@@ -221,19 +221,26 @@ bool FunctionSignatureInfo::analyzeResult() {
221221
// going to be used in the return block/normal block of the try_apply instruction.
222222
if (!Retains.empty()) {
223223
RI.CalleeRetain = Retains;
224-
ShouldOptimize = true;
224+
SignatureOptimize = true;
225225
}
226226
}
227-
return ShouldOptimize;
227+
return SignatureOptimize;
228228
}
229229

230230
/// This function goes through the arguments of F and sees if we have anything
231231
/// to optimize in which case it returns true. If we have nothing to optimize,
232232
/// it returns false.
233233
bool FunctionSignatureInfo::analyze() {
234+
if (SignatureComputed)
235+
return SignatureOptimize;
236+
237+
// Compute the signature optimization.
234238
bool OptimizedParams = analyzeParameters();
235239
bool OptimizedResult = analyzeResult();
236-
return OptimizedParams || OptimizedResult;
240+
241+
SignatureComputed = true;
242+
SignatureOptimize = OptimizedParams || OptimizedResult;
243+
return SignatureOptimize;
237244
}
238245

239246
//===----------------------------------------------------------------------===//
@@ -245,6 +252,8 @@ std::string FunctionSignatureInfo::getOptimizedName() const {
245252
auto P = SpecializationPass::FunctionSignatureOpts;
246253
FunctionSignatureSpecializationMangler FSSM(P, M, F);
247254

255+
std::string ArgEnc;
256+
248257
// Handle arguments' changes.
249258
for (unsigned i : indices(ArgDescList)) {
250259
const ArgumentDescriptor &Arg = ArgDescList[i];
@@ -262,6 +271,9 @@ std::string FunctionSignatureInfo::getOptimizedName() const {
262271
// mangling.
263272
if (Arg.Explode && !Arg.IsEntirelyDead) {
264273
FSSM.setArgumentSROA(i);
274+
// Generate a string of encoding for the argument projection tree.
275+
// TODO: we can put this into the mangler itself.
276+
ArgEnc += "_arg" + std::to_string(i) + "_" + Arg.ProjTree.getNameEncoding();
265277
}
266278
}
267279

@@ -273,7 +285,7 @@ std::string FunctionSignatureInfo::getOptimizedName() const {
273285

274286
FSSM.mangle();
275287

276-
return M.finalize();
288+
return M.finalize() + ArgEnc;
277289
}
278290

279291

lib/SILOptimizer/PassManager/Passes.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ void AddSSAPasses(SILPassManager &PM, OptimizationLevelKind OpLevel) {
197197
// current function (after optimizing any new callees).
198198
PM.addDevirtualizer();
199199
PM.addGenericSpecializer();
200+
200201
switch (OpLevel) {
201202
case OptimizationLevelKind::HighLevel:
202203
// Does not inline functions with defined semantics.
@@ -245,6 +246,7 @@ void AddSSAPasses(SILPassManager &PM, OptimizationLevelKind OpLevel) {
245246
PM.addLateCodeMotion();
246247
else
247248
PM.addEarlyCodeMotion();
249+
248250
PM.addARCSequenceOpts();
249251
PM.addRemovePins();
250252
}
@@ -327,8 +329,6 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
327329
// We do this late since it is a pass like the inline caches that we only want
328330
// to run once very late. Make sure to run at least one round of the ARC
329331
// optimizer after this.
330-
PM.addFunctionSignatureOpts();
331-
332332
PM.runOneIteration();
333333
PM.resetAndRemoveTransformations();
334334

@@ -338,11 +338,20 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
338338

339339
PM.setStageName("LowLevel");
340340

341+
// Rewrite to get the benefit of release devirtualizer.
342+
// Also, Make sure the run the rewriter to create the optimized functions before
343+
// the cloner on the current function is run !.
344+
PM.addFunctionSignatureOptRewriter();
345+
341346
// Should be after FunctionSignatureOpts and before the last inliner.
342347
PM.addReleaseDevirtualizer();
343348

344349
AddSSAPasses(PM, OptimizationLevelKind::LowLevel);
345350
PM.addDeadStoreElimination();
351+
352+
// We've done a lot of optimizations on this function, attempt to FSO.
353+
PM.addFunctionSignatureOptCloner();
354+
346355
PM.runOneIteration();
347356
PM.resetAndRemoveTransformations();
348357

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ set(TRANSFORMS_SOURCES
88
Transforms/DeadObjectElimination.cpp
99
Transforms/DeadStoreElimination.cpp
1010
Transforms/Devirtualizer.cpp
11+
Transforms/FunctionSignatureOptCloner.cpp
12+
Transforms/FunctionSignatureOptRewriter.cpp
1113
Transforms/GenericSpecializer.cpp
1214
Transforms/MergeCondFail.cpp
1315
Transforms/RedundantLoadElimination.cpp

0 commit comments

Comments
 (0)