Skip to content

Implement a function signature cloner and rewriter. #1744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/SIL/Projection.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ class ProjectionTreeNode {
NullablePtr<SILInstruction> createProjection(SILBuilder &B, SILLocation Loc,
SILValue Arg) const;

std::string getNameEncoding(const ProjectionTree &PT) const;

SILInstruction *
createAggregate(SILBuilder &B, SILLocation Loc,
ArrayRef<SILValue> Args) const;
Expand Down Expand Up @@ -846,6 +848,9 @@ class ProjectionTree {
/// All debug instructions (debug_value, debug_value_addr) are ignored.
void computeUsesAndLiveness(SILValue Base);

/// Return a name encoding of the projection tree.
std::string getNameEncoding() const;

/// Initialize an empty projection tree with an existing, computed projection
/// tree.
void initializeWithExistingTree(const ProjectionTree &PT);
Expand Down
13 changes: 10 additions & 3 deletions include/swift/SILOptimizer/Analysis/FunctionSignatureAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ struct ResultDescriptor {
};

class FunctionSignatureInfo {
/// Have the signature be computed for this function.
bool SignatureComputed;

/// Should we optimize the signature for this function.
bool SignatureOptimize;

/// Function currently analyzing.
SILFunction *F;

Expand Down Expand Up @@ -204,9 +210,10 @@ class FunctionSignatureInfo {


public:
FunctionSignatureInfo(SILFunction *F, llvm::BumpPtrAllocator &BPA, AliasAnalysis *AA,
RCIdentityFunctionInfo *RCFI) :
F(F), Allocator(BPA), AA(AA), RCFI(RCFI), MayBindDynamicSelf(computeMayBindDynamicSelf(F)) {}
FunctionSignatureInfo(SILFunction *F, llvm::BumpPtrAllocator &BPA,
AliasAnalysis *AA, RCIdentityFunctionInfo *RCFI) :
SignatureComputed(false), SignatureOptimize(false), F(F), Allocator(BPA),
AA(AA), RCFI(RCFI), MayBindDynamicSelf(computeMayBindDynamicSelf(F)) {}

bool analyze();
bool analyzeParameters();
Expand Down
4 changes: 4 additions & 0 deletions include/swift/SILOptimizer/PassManager/Passes.def
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ PASS(FunctionOrderPrinter, "function-order-printer",
"Print function orderings for test purposes")
PASS(FunctionSignatureOpts, "function-signature-opts",
"Optimize Function Signatures")
PASS(FunctionSignatureOptCloner, "function-signature-opt-cloner",
"Create function with optimized signatures")
PASS(FunctionSignatureOptRewriter, "function-signature-opt-rewriter",
"Optimize Function Signatures by rewriting callsites")
PASS(ARCSequenceOpts, "arc-sequence-opts",
"Optimize sequences of retain/release opts by removing redundant inner "
"retain/release sequences")
Expand Down
45 changes: 45 additions & 0 deletions include/swift/SILOptimizer/Utils/FunctionSignatureOptUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===--- FunctionSignatureOptUtils.h ----------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SIL_FUNCTIONSIGOPTUTILS_H
#define SWIFT_SIL_FUNCTIONSIGOPTUTILS_H

#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SILOptimizer/Analysis/FunctionSignatureAnalysis.h"

namespace swift {

bool canSpecializeFunction(SILFunction *F);

void
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
SILLocation Loc,
OperandValueArrayRef Parameters,
ArrayRef<ArgumentDescriptor> &ArgDescs);

void
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
SILLocation Loc,
ArrayRef<SILArgument*> Parameters,
ArrayRef<ArgumentDescriptor> &ArgDescs);
void
addRetainsForConvertedDirectResults(SILBuilder &Builder,
SILLocation Loc,
SILValue ReturnValue,
SILInstruction *AI,
ArrayRef<ResultDescriptor> DirectResults);

} // end namespace swift

#endif
22 changes: 22 additions & 0 deletions lib/SIL/Projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,19 @@ createProjection(SILBuilder &B, SILLocation Loc, SILValue Arg) const {
return Proj->createProjection(B, Loc, Arg);
}

std::string
ProjectionTreeNode::getNameEncoding(const ProjectionTree &PT) const {
std::string Encoding;
const ProjectionTreeNode *Node = this;
while(Node) {
if (Node->isRoot())
break;
Encoding += std::to_string(Node->Proj->getIndex());
Node = Node->getParent(PT);
}
return Encoding;
}

void
ProjectionTreeNode::
processUsersOfValue(ProjectionTree &Tree,
Expand Down Expand Up @@ -1182,6 +1195,15 @@ ProjectionTree::initializeWithExistingTree(const ProjectionTree &PT) {
}
}

std::string ProjectionTree::getNameEncoding() const {
std::string Encoding;
for (unsigned index : LiveLeafIndices) {
const ProjectionTreeNode *Node = ProjectionTreeNodes[index];
Encoding += Node->getNameEncoding(*this);
}
return Encoding;
}

SILValue
ProjectionTree::computeExplodedArgumentValueInner(SILBuilder &Builder,
SILLocation Loc,
Expand Down
28 changes: 20 additions & 8 deletions lib/SILOptimizer/Analysis/FunctionSignatureAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ bool FunctionSignatureInfo::analyzeParameters() {
RCFI, F, ConsumedArgToEpilogueReleaseMatcher::ExitKind::Throw);

// Did we decide we should optimize any parameter?
bool ShouldOptimize = false;
bool SignatureOptimize = false;

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

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

return ShouldOptimize;
return SignatureOptimize;
}

bool FunctionSignatureInfo::analyzeResult() {
Expand All @@ -203,7 +203,7 @@ bool FunctionSignatureInfo::analyzeResult() {
return false;

// Did we decide we should optimize any parameter?
bool ShouldOptimize = false;
bool SignatureOptimize = false;

// Analyze return result information.
auto DirectResults = F->getLoweredFunctionType()->getDirectResults();
Expand All @@ -221,19 +221,26 @@ bool FunctionSignatureInfo::analyzeResult() {
// going to be used in the return block/normal block of the try_apply instruction.
if (!Retains.empty()) {
RI.CalleeRetain = Retains;
ShouldOptimize = true;
SignatureOptimize = true;
}
}
return ShouldOptimize;
return SignatureOptimize;
}

/// This function goes through the arguments of F and sees if we have anything
/// to optimize in which case it returns true. If we have nothing to optimize,
/// it returns false.
bool FunctionSignatureInfo::analyze() {
if (SignatureComputed)
return SignatureOptimize;

// Compute the signature optimization.
bool OptimizedParams = analyzeParameters();
bool OptimizedResult = analyzeResult();
return OptimizedParams || OptimizedResult;

SignatureComputed = true;
SignatureOptimize = OptimizedParams || OptimizedResult;
return SignatureOptimize;
}

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

std::string ArgEnc;

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

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

FSSM.mangle();

return M.finalize();
return M.finalize() + ArgEnc;
}


Expand Down
13 changes: 11 additions & 2 deletions lib/SILOptimizer/PassManager/Passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ void AddSSAPasses(SILPassManager &PM, OptimizationLevelKind OpLevel) {
// current function (after optimizing any new callees).
PM.addDevirtualizer();
PM.addGenericSpecializer();

switch (OpLevel) {
case OptimizationLevelKind::HighLevel:
// Does not inline functions with defined semantics.
Expand Down Expand Up @@ -245,6 +246,7 @@ void AddSSAPasses(SILPassManager &PM, OptimizationLevelKind OpLevel) {
PM.addLateCodeMotion();
else
PM.addEarlyCodeMotion();

PM.addARCSequenceOpts();
PM.addRemovePins();
}
Expand Down Expand Up @@ -327,8 +329,6 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
// We do this late since it is a pass like the inline caches that we only want
// to run once very late. Make sure to run at least one round of the ARC
// optimizer after this.
PM.addFunctionSignatureOpts();

PM.runOneIteration();
PM.resetAndRemoveTransformations();

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

PM.setStageName("LowLevel");

// Rewrite to get the benefit of release devirtualizer.
// Also, Make sure the run the rewriter to create the optimized functions before
// the cloner on the current function is run !.
PM.addFunctionSignatureOptRewriter();

// Should be after FunctionSignatureOpts and before the last inliner.
PM.addReleaseDevirtualizer();

AddSSAPasses(PM, OptimizationLevelKind::LowLevel);
PM.addDeadStoreElimination();

// We've done a lot of optimizations on this function, attempt to FSO.
PM.addFunctionSignatureOptCloner();

PM.runOneIteration();
PM.resetAndRemoveTransformations();

Expand Down
2 changes: 2 additions & 0 deletions lib/SILOptimizer/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ set(TRANSFORMS_SOURCES
Transforms/DeadObjectElimination.cpp
Transforms/DeadStoreElimination.cpp
Transforms/Devirtualizer.cpp
Transforms/FunctionSignatureOptCloner.cpp
Transforms/FunctionSignatureOptRewriter.cpp
Transforms/GenericSpecializer.cpp
Transforms/MergeCondFail.cpp
Transforms/RedundantLoadElimination.cpp
Expand Down
Loading