[Closure Specializer] check in a pass to specialize closure.

If we have function A calls function B with a closure C
func A {
  B(...) {
    // closure C
  }
}
and the inliner decides to not inline B into A, it may be beneficial to generate
a specialized version of B to have
func A {
  B_spec_with_C(..., arguments_to_closure_C)
}
 
SILCombine will optimize apply of partial_apply that are both in B_spec_with_C.
Then inliner can inline the closure to B_spec_with_C.

For profitability, we check the relative size of the callee B and the closure C.
We also check hotness of the callsite to B in A and callsites to the closure
inside B. For now, if closure is called inside a loop, we think it is
profitable.

I will add this to the pass manager in a follow-up patch.
rdar://16569736


Swift SVN r21216
This commit is contained in:
Manman Ren
2014-08-14 19:45:11 +00:00
parent cd6b046e0c
commit 1f54d024a9
5 changed files with 526 additions and 0 deletions

View File

@@ -80,6 +80,7 @@ enum class PassKind {
GlobalLoadStoreOpts,
ArrayOpts,
ABCOpts,
ClosureSpecialization
};
enum class OptGroup {
@@ -264,6 +265,9 @@ Passes(llvm::cl::desc("Passes:"),
clEnumValN(PassKind::ABCOpts,
"abcopts",
"Array bounds check opts."),
clEnumValN(PassKind::ClosureSpecialization,
"closure-specialize",
"Closure specialization."),
clEnumValEnd));
static llvm::cl::opt<bool>
@@ -464,6 +468,9 @@ static void runCommandLineSelectedPasses(SILModule *Module,
case PassKind::ABCOpts:
PM.add(createABCOpt());
break;
case PassKind::ClosureSpecialization:
PM.add(createClosureSpecializer());
break;
}
}
PM.run();