Skip to content

Fix the mid-level pass pipeline #26256

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

Closed
wants to merge 7 commits into from
Closed
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
2 changes: 1 addition & 1 deletion docs/ErrorHandlingRationale.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ Haskell
Haskell provides three different common error-propagation mechanisms.

The first is that, like many other functional languages, it supports
manual propagation with a ``Maybe`` type. A function can return ``None``
manual propagation with a ``Maybe`` type. A function can return ``Nothing``
to indicate that it couldn't produce a more useful result. This is
the most common failure method for functions in the functional subset
of the library.
Expand Down
23 changes: 11 additions & 12 deletions lib/IRGen/AllocStackHoisting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@

#define DEBUG_TYPE "alloc-stack-hoisting"

#include "swift/IRGen/IRGenSILPasses.h"
#include "swift/AST/Availability.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/IRGen/IRGenSILPasses.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"

#include "IRGenModule.h"
#include "NonFixedTypeInfo.h"
Expand Down Expand Up @@ -124,7 +124,7 @@ insertDeallocStackAtEndOf(SmallVectorImpl<SILInstruction *> &FunctionExits,

/// Hack to workaround a clang LTO bug.
LLVM_ATTRIBUTE_NOINLINE
void moveAllocStackToBeginningOfBlock(AllocStackInst* AS, SILBasicBlock *BB) {
void moveAllocStackToBeginningOfBlock(AllocStackInst *AS, SILBasicBlock *BB) {
AS->moveFront(BB);
}

Expand All @@ -149,7 +149,8 @@ void Partition::assignStackLocation(
// Rewrite all the other alloc_stacks in the partition to use the assigned
// location.
for (auto *AllocStack : Elts) {
if (AssignedLoc == AllocStack) continue;
if (AssignedLoc == AllocStack)
continue;
eraseDeallocStacks(AllocStack);
AllocStack->replaceAllUsesWith(AssignedLoc);
AllocStack->eraseFromParent();
Expand Down Expand Up @@ -277,8 +278,8 @@ void MergeStackSlots::mergeSlots() {
// Check if we can add it to an existing partition that we have show to be
// non-interfering.
for (auto &CandidateP : DisjointPartitions) {
// If the candidate partition is empty (the very first time we look at an
// alloc_stack) we can just add the alloc_stack.
// If the candidate partition is empty (the very first time we look at
// an alloc_stack) we can just add the alloc_stack.
if (CandidateP.Elts.empty()) {
CandidateP.Elts.push_back(CurAllocStack);
FoundAPartition = true;
Expand Down Expand Up @@ -316,7 +317,6 @@ void MergeStackSlots::mergeSlots() {
}
}


namespace {
/// Hoist alloc_stack instructions to the entry block and merge them.
class HoistAllocStack {
Expand Down Expand Up @@ -437,8 +437,7 @@ class AllocStackHoisting : public SILFunctionTransform {
auto *F = getFunction();
auto *Mod = getIRGenModule();
assert(Mod && "This pass must be run as part of an IRGen pipeline");
bool Changed = HoistAllocStack(F, *Mod).run();
if (Changed) {
if (HoistAllocStack(F, *Mod).run()) {
PM->invalidateAnalysis(F, SILAnalysis::InvalidationKind::Instructions);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
///
/// Another possibility is to implement these optimizations as separate passes,
/// but then we would send slightly different functions to the pass pipeline
/// multiple times through notifyPassManagerOfFunction.
/// multiple times through notifyPassManagerOfFunction.
///
/// TODO: Optimize function with generic parameters.
///
/// TODO: Improve epilogue release matcher, i.e. do a data flow instead of
/// only finding releases in the return block.
/// only finding releases in the return block.
///
//===----------------------------------------------------------------------===//

Expand All @@ -34,7 +34,6 @@
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
#include "swift/SILOptimizer/Analysis/CallerAnalysis.h"
Expand All @@ -44,6 +43,7 @@
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/Utils/SILInliner.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
Expand All @@ -54,7 +54,8 @@ using namespace swift;
STATISTIC(NumFunctionSignaturesOptimized, "Total func sig optimized");
STATISTIC(NumDeadArgsEliminated, "Total dead args eliminated");
STATISTIC(NumOwnedConvertedToGuaranteed, "Total owned args -> guaranteed args");
STATISTIC(NumOwnedConvertedToNotOwnedResult, "Total owned result -> not owned result");
STATISTIC(NumOwnedConvertedToNotOwnedResult,
"Total owned result -> not owned result");
STATISTIC(NumSROAArguments, "Total SROA arguments optimized");

using SILParameterInfoList = llvm::SmallVector<SILParameterInfo, 8>;
Expand Down Expand Up @@ -228,9 +229,9 @@ static bool usesGenerics(SILFunction *F,
if (&BB != &*F->begin()) {
// Scan types of all BB arguments. Ignore the entry BB, because
// it is handled in a special way.
Arg->getType().getASTType().visit(FindArchetypesAndGenericTypes);
if (UsesGenerics)
return UsesGenerics;
Arg->getType().getASTType().visit(FindArchetypesAndGenericTypes);
if (UsesGenerics)
return UsesGenerics;
}
}
// Scan types of all operands.
Expand Down Expand Up @@ -356,17 +357,17 @@ FunctionSignatureTransformDescriptor::createOptimizedSILFunctionType() {
// The set of used archetypes is complete now.
if (!UsesGenerics) {
// None of the generic type parameters are used.
LLVM_DEBUG(llvm::dbgs() << "None of generic parameters are used by "
<< F->getName() << "\n";
llvm::dbgs() << "Interface params:\n";
for (auto Param : InterfaceParams) {
Param.getType().dump();
}

llvm::dbgs() << "Interface results:\n";
for (auto Result : InterfaceResults) {
Result.getType().dump();
});
LLVM_DEBUG(
llvm::dbgs() << "None of generic parameters are used by "
<< F->getName() << "\n";
llvm::dbgs() << "Interface params:\n";
for (auto Param
: InterfaceParams) { Param.getType().dump(); }

llvm::dbgs()
<< "Interface results:\n";
for (auto Result
: InterfaceResults) { Result.getType().dump(); });
}
}

Expand Down Expand Up @@ -574,8 +575,7 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
// Produce a substitutions list and a set of substituted SIL types
// required for creating a new SIL function.
Subs = F->getForwardingSubstitutionMap();
auto SubstCalleeType =
GenCalleeType->substGenericArgs(M, Subs);
auto SubstCalleeType = GenCalleeType->substGenericArgs(M, Subs);
SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeType);
SILFunctionConventions Conv(SubstCalleeType, M);
ResultType = Conv.getSILResultType();
Expand Down Expand Up @@ -619,19 +619,6 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
bool Changed = false;
SILFunction *F = TransformDescriptor.OriginalFunction;

// Never repeat the same function signature optimization on the same function.
// Multiple function signature optimizations are composed by successively
// optmizing the newly created functions. Each optimization creates a new
// level of thunk. Those should all be ultimately inlined away.
//
// This happens, for example, when a new reference to the original function is
// discovered during devirtualization. That will cause the original function
// (now and FSO thunk) to be pushed back on the function pass pipeline.
if (F->isThunk() == IsSignatureOptimizedThunk) {
LLVM_DEBUG(llvm::dbgs() << " FSO already performed on this thunk\n");
return false;
}

if (!hasCaller && (F->getDynamicallyReplacedFunction() ||
canBeCalledIndirectly(F->getRepresentation()))) {
LLVM_DEBUG(llvm::dbgs() << " function has no caller -> abort\n");
Expand Down Expand Up @@ -690,10 +677,7 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
// After this optimization CapturePropagation can replace the partial_apply by a
// direct reference to the specialized function.
bool FunctionSignatureTransform::removeDeadArgs(int minPartialAppliedArgs) {
if (minPartialAppliedArgs < 1)
return false;

if (!DeadArgumentAnalyzeParameters())
if (minPartialAppliedArgs < 1 || !DeadArgumentAnalyzeParameters())
return false;

SILFunction *F = TransformDescriptor.OriginalFunction;
Expand Down Expand Up @@ -737,16 +721,15 @@ bool FunctionSignatureTransform::removeDeadArgs(int minPartialAppliedArgs) {
namespace {

class FunctionSignatureOpts : public SILFunctionTransform {

/// If true, perform a special kind of dead argument elimination to enable
/// removal of partial_apply instructions where all partially applied
/// arguments are dead.
bool OptForPartialApply;

public:

FunctionSignatureOpts(bool OptForPartialApply) :
OptForPartialApply(OptForPartialApply) { }
FunctionSignatureOpts(bool OptForPartialApply)
: OptForPartialApply(OptForPartialApply) {}

void run() override {
auto *F = getFunction();
Expand All @@ -763,15 +746,15 @@ class FunctionSignatureOpts : public SILFunctionTransform {
return;

// This is the function to optimize.
LLVM_DEBUG(llvm::dbgs() << "*** FSO on function: " << F->getName()
<< " ***\n");
LLVM_DEBUG(llvm::dbgs()
<< "*** FSO on function: " << F->getName() << " ***\n");

// Check the signature of F to make sure that it is a function that we
// can specialize. These are conditions independent of the call graph.
// No need for CallerAnalysis if we are not optimizing for partial
// applies.
if (!OptForPartialApply &&
!canSpecializeFunction(F, nullptr, OptForPartialApply)) {
if (!(OptForPartialApply ||
canSpecializeFunction(F, nullptr, OptForPartialApply))) {
LLVM_DEBUG(llvm::dbgs() << " cannot specialize function -> abort\n");
return;
}
Expand All @@ -786,7 +769,20 @@ class FunctionSignatureOpts : public SILFunctionTransform {
LLVM_DEBUG(llvm::dbgs() << " cannot specialize function -> abort\n");
return;
}

// Never repeat the same function signature optimization on the same
// function. Multiple function signature optimizations are composed by
// successively optmizing the newly created functions. Each optimization
// creates a new level of thunk. Those should all be ultimately inlined
// away.
//
// This happens, for example, when a new reference to the original function
// is discovered during devirtualization. That will cause the original
// function (now and FSO thunk) to be pushed back on the function pass
// pipeline.
if (F->isThunk() == IsSignatureOptimizedThunk) {
LLVM_DEBUG(llvm::dbgs() << " FSO already performed on this thunk\n");
return false;
}
// Ok, we think we can perform optimization. Now perform a quick check
auto *RCIA = getAnalysis<RCIdentityAnalysis>();
auto *EA = PM->getAnalysis<EpilogueARCAnalysis>();
Expand All @@ -795,8 +791,8 @@ class FunctionSignatureOpts : public SILFunctionTransform {
// going to change, make sure the mangler is aware of all the changes done
// to the function.
auto P = Demangle::SpecializationPass::FunctionSignatureOpts;
Mangle::FunctionSignatureSpecializationMangler Mangler(P,
F->isSerialized(), F);
Mangle::FunctionSignatureSpecializationMangler Mangler(P, F->isSerialized(),
F);

/// Keep a map between the exploded argument index and the original argument
/// index.
Expand All @@ -823,7 +819,7 @@ class FunctionSignatureOpts : public SILFunctionTransform {
FunctionSignatureTransform FST(FuncBuilder, F, RCIA, EA, Mangler, AIM,
ArgumentDescList, ResultDescList);

bool Changed = false;
bool Changed;
if (OptForPartialApply) {
Changed = FST.removeDeadArgs(FuncInfo.getMinPartialAppliedArgs());
} else {
Expand Down Expand Up @@ -853,7 +849,6 @@ class FunctionSignatureOpts : public SILFunctionTransform {
restartPassPipeline();
}
}

};

} // end anonymous namespace
Expand Down
Loading