Skip to content

Commit faba6e5

Browse files
committed
Add a stand-alone generic specializer pass.
Begin unbundling devirtualization, specialization, and inlining by recreating the stand-alone generic specializer pass. I've added a use of the pass to the pipeline, but this is almost certainly not going to be the final location of where it runs. It's primarily there to ensure this code gets exercised. Since this is running prior to inlining, it changes the order that some functions are specialized in, which means differences in the order of output of one of the tests (one which similarly changed when devirtualization, specialization, and inlining were bundled together).
1 parent dbde7cc commit faba6e5

File tree

8 files changed

+218
-100
lines changed

8 files changed

+218
-100
lines changed

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ PASS(RedundantLoadElimination, "redundant-load-elim",
104104
"Multiple basic block redundant load elimination")
105105
PASS(DeadStoreElimination, "dead-store-elim",
106106
"Multiple basic block dead store elimination")
107+
PASS(GenericSpecializer, "generic-specializer",
108+
"Specialization of generic functions by static types")
107109
PASS(GlobalOpt, "global-opt",
108110
"Global variable optimizations")
109111
PASS(GlobalPropertyOpt, "global-property-opt",

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -277,16 +277,12 @@ void SILPassManager::runFunctionPasses(PassList FuncTransforms) {
277277
runPassesOnFunction(FuncTransforms, F);
278278

279279
++CountOptimized[F];
280-
// We currently have no function passes that generate new
281-
// functions, so confirm that we only optimize a given function
282-
// once.
283-
assert(CountOptimized[F] == 1 && "Expected function to be optimized once!");
284280

285281
// If running the function transforms did not result in new
286282
// functions being added to the top of the worklist, then we're
287-
// done with this function and can pop it off and
288-
// continue. Otherwise, we'll return to this function and
289-
// reoptimize after processing the new function that were added.
283+
// done with this function and can pop it off and continue.
284+
// Otherwise, we'll return to this function and reoptimize after
285+
// processing the new functions that were added.
290286
if (F == FunctionWorklist.back())
291287
FunctionWorklist.pop_back();
292288
}

lib/SILOptimizer/PassManager/Passes.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
251251

252252
// Run two iterations of the high-level SSA passes.
253253
PM.setStageName("HighLevel");
254+
PM.addGenericSpecializer();
254255
AddSSAPasses(PM, OptimizationLevelKind::HighLevel);
255256
PM.runOneIteration();
256257
PM.runOneIteration();

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(TRANSFORMS_SOURCES
77
Transforms/DeadCodeElimination.cpp
88
Transforms/DeadObjectElimination.cpp
99
Transforms/DeadStoreElimination.cpp
10+
Transforms/GenericSpecializer.cpp
1011
Transforms/MergeCondFail.cpp
1112
Transforms/RedundantLoadElimination.cpp
1213
Transforms/RedundantOverflowCheckRemoval.cpp
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//===-- GenericSpecializer.cpp - Specialization of generic functions ------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 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+
// Specialize calls to generic functions by substituting static type
14+
// information.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#define DEBUG_TYPE "sil-generic-specialize"
19+
20+
#include "swift/SIL/SILFunction.h"
21+
#include "swift/SIL/SILInstruction.h"
22+
#include "swift/SILOptimizer/Utils/Generics.h"
23+
#include "swift/SILOptimizer/Utils/Local.h"
24+
#include "swift/SILOptimizer/PassManager/Transforms.h"
25+
#include "llvm/ADT/SmallVector.h"
26+
27+
using namespace swift;
28+
29+
// STATISTIC(NumEscapingAllocas, "Number of aggregate allocas not chopped up "
30+
// "due to uses.");
31+
// STATISTIC(NumChoppedAllocas, "Number of chopped up aggregate allocas.");
32+
// STATISTIC(NumUnhandledAllocas, "Number of non struct, tuple allocas.");
33+
34+
namespace {} // end anonymous namespace
35+
36+
namespace {
37+
38+
class GenericSpecializer : public SILFunctionTransform {
39+
40+
bool specializeAppliesInFunction(SILFunction &F);
41+
42+
/// The entry point to the transformation.
43+
void run() override {
44+
SILFunction &F = *getFunction();
45+
DEBUG(llvm::dbgs() << "***** GenericSpecializer on function:" << F.getName()
46+
<< " *****\n");
47+
48+
if (specializeAppliesInFunction(F))
49+
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
50+
}
51+
52+
StringRef getName() override { return "Generic Specializer"; }
53+
};
54+
55+
} // end anonymous namespace
56+
57+
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
58+
bool Changed = false;
59+
llvm::SmallVector<SILInstruction *, 8> DeadApplies;
60+
61+
for (auto &BB : F) {
62+
for (auto It = BB.begin(), End = BB.end(); It != End;) {
63+
auto &I = *It++;
64+
65+
// Skip non-apply instructions, apply instructions with no
66+
// substitutions, apply instructions where we do not statically
67+
// know the called function, and apply instructions where we do
68+
// not have the body of the called function.
69+
70+
ApplySite Apply = ApplySite::isa(&I);
71+
if (!Apply || !Apply.hasSubstitutions())
72+
continue;
73+
74+
auto *Callee = Apply.getCalleeFunction();
75+
if (!Callee || !Callee->isDefinition())
76+
continue;
77+
78+
// We have a call that can potentially be specialized, so
79+
// attempt to do so.
80+
81+
// The specializer helper function currently expects a collector
82+
// argument, but we aren't going to make use of the results so
83+
// we'll have our filter always return false;
84+
auto Filter = [](SILInstruction *I) -> bool { return false; };
85+
CloneCollector Collector(Filter);
86+
87+
SILFunction *SpecializedFunction;
88+
89+
auto Specialized =
90+
trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector);
91+
92+
if (Specialized) {
93+
Changed = true;
94+
95+
// If calling the specialization utility resulted in a new
96+
// function (as opposed to returning a previous
97+
// specialization), we need to notify the pass manager so that
98+
// the new function gets optimized.
99+
if (SpecializedFunction)
100+
notifyPassManagerOfFunction(SpecializedFunction);
101+
102+
auto *AI = Apply.getInstruction();
103+
104+
if (!isa<TryApplyInst>(AI))
105+
AI->replaceAllUsesWith(Specialized.getInstruction());
106+
107+
DeadApplies.push_back(AI);
108+
}
109+
}
110+
}
111+
112+
// Remove all the now-dead applies.
113+
while (!DeadApplies.empty()) {
114+
auto *AI = DeadApplies.pop_back_val();
115+
recursivelyDeleteTriviallyDeadInstructions(AI, true);
116+
}
117+
118+
return Changed;
119+
}
120+
121+
SILTransform *swift::createGenericSpecializer() {
122+
return new GenericSpecializer();
123+
}

test/SILOptimizer/specialize_inherited.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -module-name inherit | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -generic-specializer -module-name inherit | FileCheck %s
22

33
import Builtin
44
import Swift

test/SILOptimizer/specialize_metatypes_with_nondefault_representation.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -generic-specializer | FileCheck %s
22

33
// REQUIRES: objc_interop
44

0 commit comments

Comments
 (0)