Skip to content

Commit 2437bca

Browse files
Merge pull request #1632 from swiftwasm/katei/wasm-thin-lto
[Experimental] Integrate LTO works
2 parents 6874807 + b3d242f commit 2437bca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3312
-54
lines changed

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ class SILOptions {
166166
/// Enable large loadable types IRGen pass.
167167
bool EnableLargeLoadableTypes = true;
168168

169+
/// The path to combined module summary file
170+
std::string ModuleSummaryPath;
171+
169172
/// The name of the file to which the backend should save optimization
170173
/// records.
171174
std::string OptRecordFile;

include/swift/Frontend/FrontendOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class FrontendOptions {
7070
/// The path to which we should store indexing data, if any.
7171
std::string IndexStorePath;
7272

73+
/// The path to which we should emit combined module summary file
74+
std::string ModuleSummaryOutputPath;
7375
/// The path to look in when loading a module interface file, to see if a
7476
/// binary module has already been built for use by the compiler.
7577
std::string PrebuiltModuleCachePath;

include/swift/Option/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ def emit_module_summary_path :
449449
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
450450
ArgumentIsPath, SupplementaryOutput]>,
451451
MetaVarName<"<path>">, HelpText<"Output module summary file to <path>">;
452+
def module_summary_path : Separate<["-"], "module-summary-path">,
453+
Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"<path>">,
454+
HelpText<"Combined module summary file <path>">;
452455

453456
def emit_module_interface :
454457
Flag<["-"], "emit-module-interface">,

include/swift/SIL/ModuleSummary.h

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
//===----- ModuleSummary.h --------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SIL_MODULE_SUMMARY_H
14+
#define SWIFT_SIL_MODULE_SUMMARY_H
15+
16+
#include "swift/AST/Decl.h"
17+
#include "swift/SIL/SILFunction.h"
18+
#include "llvm/Support/YAMLTraits.h"
19+
20+
namespace swift {
21+
22+
namespace modulesummary {
23+
24+
using GUID = uint64_t;
25+
26+
/// Compute globally unique identifier from the symbol.
27+
GUID getGUIDFromUniqueName(llvm::StringRef Name);
28+
29+
/// Function summary information to help callee analysis
30+
class FunctionSummary {
31+
public:
32+
/// Function call information
33+
class Call {
34+
public:
35+
/// Kinds of callee reference.
36+
enum KindTy {
37+
/// The call references a function statically
38+
Direct,
39+
/// The call references a function via a witness table.
40+
Witness,
41+
/// The call references a function via a vtable.
42+
VTable,
43+
kindCount,
44+
};
45+
46+
private:
47+
// For import/export
48+
friend llvm::yaml::MappingTraits<FunctionSummary::Call>;
49+
50+
/// The callee function GUID. This can be a static function or a virtual
51+
/// function GUID.
52+
GUID Callee;
53+
/// The symbol name of the callee function only for debug and test purposes.
54+
std::string Name;
55+
/// Kind of the callee reference.
56+
KindTy Kind;
57+
public:
58+
friend ::llvm::yaml::MappingTraits<Call>;
59+
Call() = default;
60+
Call(GUID callee, std::string name, KindTy kind)
61+
: Callee(callee), Name(name), Kind(kind) {}
62+
63+
KindTy getKind() const { return Kind; }
64+
GUID getCallee() const { return Callee; }
65+
std::string getName() const { return Name; };
66+
};
67+
68+
/// Function state flags
69+
struct FlagsTy {
70+
/// In per-module summary, always false.
71+
/// In combined summary, indicates that the function is live.
72+
bool Live;
73+
/// Indicates that the function must be considered a live root for liveness
74+
/// analysis.
75+
bool Preserved;
76+
};
77+
78+
using CallGraphEdgeListTy = std::vector<Call>;
79+
80+
private:
81+
// For import/export
82+
friend llvm::yaml::MappingTraits<FunctionSummary>;
83+
84+
/// The function identity.
85+
GUID Guid;
86+
/// The function state flags.
87+
FlagsTy Flags;
88+
/// List of Call from this function.
89+
CallGraphEdgeListTy CallGraphEdgeList;
90+
/// The symbol name of the function only for debug and test purposes.
91+
std::string Name;
92+
93+
public:
94+
FunctionSummary() = default;
95+
FunctionSummary(GUID guid)
96+
: Guid(guid), Flags({false, false}), CallGraphEdgeList(), Name("") {}
97+
98+
/// Add a call to the list.
99+
void addCall(Call call) { CallGraphEdgeList.push_back(call); }
100+
101+
/// Return the list of Call from this function
102+
ArrayRef<Call> calls() const { return CallGraphEdgeList; }
103+
104+
bool isLive() const { return Flags.Live; }
105+
void setLive(bool Live) { Flags.Live = Live; }
106+
107+
bool isPreserved() const { return Flags.Preserved; }
108+
void setPreserved(bool Preserved) { Flags.Preserved = Preserved; }
109+
110+
std::string getName() const { return Name; }
111+
void setName(std::string name) { this->Name = name; }
112+
113+
GUID getGUID() const { return Guid; }
114+
};
115+
116+
/// A slot in a set of virtual tables.
117+
struct VFuncSlot {
118+
/// Kinds of table.
119+
enum KindTy {
120+
Witness,
121+
VTable,
122+
kindCount,
123+
};
124+
125+
/// Kind of table.
126+
KindTy Kind;
127+
/// The virtual function GUID.
128+
GUID VFuncID;
129+
130+
VFuncSlot(KindTy Kind, GUID VFuncID) : Kind(Kind), VFuncID(VFuncID) {}
131+
};
132+
133+
struct VFuncImpl {
134+
GUID Guid;
135+
GUID TypeGuid;
136+
};
137+
138+
using FunctionSummaryMapTy = std::map<GUID, std::unique_ptr<FunctionSummary>>;
139+
using VFuncToImplsMapTy = std::map<GUID, std::vector<VFuncImpl>>;
140+
141+
/// Module summary that consists of function summaries and virtual function
142+
/// tables.
143+
class ModuleSummaryIndex {
144+
// For import/export
145+
friend llvm::yaml::MappingTraits<ModuleSummaryIndex>;
146+
147+
/// Map from function GUID to function summary.
148+
FunctionSummaryMapTy FunctionSummaryMap;
149+
/// Map from virtual function GUID to list of implementations for witness
150+
/// tables.
151+
VFuncToImplsMapTy WitnessTableMethodMap;
152+
/// Map from virtual function GUID to list of implementations for vtables.
153+
VFuncToImplsMapTy VTableMethodMap;
154+
/// The symbol name of the module.
155+
std::string Name;
156+
157+
VFuncToImplsMapTy &getVFuncMap(VFuncSlot::KindTy kind) {
158+
switch (kind) {
159+
case VFuncSlot::Witness:
160+
return WitnessTableMethodMap;
161+
case VFuncSlot::VTable:
162+
return VTableMethodMap;
163+
case VFuncSlot::kindCount: {
164+
llvm_unreachable("impossible");
165+
}
166+
}
167+
}
168+
const VFuncToImplsMapTy &getVFuncMap(VFuncSlot::KindTy kind) const {
169+
switch (kind) {
170+
case VFuncSlot::Witness:
171+
return WitnessTableMethodMap;
172+
case VFuncSlot::VTable:
173+
return VTableMethodMap;
174+
case VFuncSlot::kindCount: {
175+
llvm_unreachable("impossible");
176+
}
177+
}
178+
}
179+
public:
180+
friend ::llvm::yaml::MappingTraits<ModuleSummaryIndex>;
181+
ModuleSummaryIndex() = default;
182+
183+
std::string getName() const { return this->Name; }
184+
void setName(std::string name) { this->Name = name; }
185+
186+
/// Add a global value summary.
187+
void addFunctionSummary(std::unique_ptr<FunctionSummary> summary) {
188+
FunctionSummaryMap.insert(
189+
std::make_pair(summary->getGUID(), std::move(summary)));
190+
}
191+
192+
/// Return a FunctionSummary for GUID if it exists, otherwise return nullptr.
193+
FunctionSummary *getFunctionSummary(GUID guid) const {
194+
auto found = FunctionSummaryMap.find(guid);
195+
if (found == FunctionSummaryMap.end()) {
196+
return nullptr;
197+
}
198+
auto &entry = found->second;
199+
return entry.get();
200+
}
201+
202+
/// Record a implementation for the virtual function slot.
203+
void addImplementation(VFuncSlot slot, GUID implGUID, GUID typeGUID) {
204+
VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
205+
auto found = table.find(slot.VFuncID);
206+
VFuncImpl impl = {implGUID, typeGUID};
207+
if (found == table.end()) {
208+
table.insert(std::make_pair(slot.VFuncID, std::vector<VFuncImpl>{impl}));
209+
return;
210+
}
211+
found->second.push_back(impl);
212+
}
213+
214+
/// Return a list of implementations for the virtual function slot.
215+
ArrayRef<VFuncImpl> getImplementations(VFuncSlot slot) const {
216+
const VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
217+
auto found = table.find(slot.VFuncID);
218+
if (found == table.end()) {
219+
return ArrayRef<VFuncImpl>();
220+
}
221+
return ArrayRef<VFuncImpl>(found->second);
222+
}
223+
224+
const VFuncToImplsMapTy &getWitnessTableMethodMap() const {
225+
return WitnessTableMethodMap;
226+
}
227+
const VFuncToImplsMapTy &getVTableMethodMap() const {
228+
return VTableMethodMap;
229+
}
230+
231+
FunctionSummaryMapTy::const_iterator functions_begin() const {
232+
return FunctionSummaryMap.begin();
233+
}
234+
FunctionSummaryMapTy::const_iterator functions_end() const {
235+
return FunctionSummaryMap.end();
236+
}
237+
};
238+
239+
/// Compute a \c ModuleSummaryIndex from the given SILModule.
240+
std::unique_ptr<ModuleSummaryIndex> buildModuleSummaryIndex(SILModule &M);
241+
242+
/// Serializes a module summary to the given output file.
243+
///
244+
/// \returns false on success, true on error.
245+
bool writeModuleSummaryIndex(const ModuleSummaryIndex &index,
246+
DiagnosticEngine &diags, StringRef path);
247+
248+
/// Attempt to deserialize the module summary.
249+
///
250+
/// \returns false on success, true on error.
251+
bool loadModuleSummaryIndex(llvm::MemoryBufferRef inputBuffer,
252+
ModuleSummaryIndex &moduleSummary);
253+
} // namespace modulesummary
254+
} // namespace swift
255+
256+
#endif

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2957,7 +2957,10 @@ class KeyPathPatternComponent {
29572957
void visitReferencedFunctionsAndMethods(
29582958
std::function<void (SILFunction *)> functionCallBack,
29592959
std::function<void (SILDeclRef)> methodCallBack) const;
2960-
2960+
2961+
void clearReferencedFunctions_if(
2962+
llvm::function_ref<bool(SILFunction *)> predicate);
2963+
29612964
void incrementRefCounts() const;
29622965
void decrementRefCounts() const;
29632966

include/swift/SIL/SILProperty.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,14 @@ class SILProperty : public llvm::ilist_node<SILProperty>,
6767
const Optional<KeyPathPatternComponent> &getComponent() const {
6868
return Component;
6969
}
70-
70+
71+
void clearReferencedFunctions_if(
72+
llvm::function_ref<bool(SILFunction *)> predicate) {
73+
if (Component) {
74+
Component->clearReferencedFunctions_if(predicate);
75+
}
76+
}
77+
7178
void print(SILPrintContext &Ctx) const;
7279
void dump() const;
7380

include/swift/SILOptimizer/PassManager/PassPipeline.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
PASSPIPELINE(Diagnostic, "Guaranteed Passes")
2626
PASSPIPELINE(OwnershipEliminator, "Utility pass to just run the ownership eliminator pass")
27+
PASSPIPELINE(CrossModuleEliminator, "Passes run at -module-summary-path")
2728
PASSPIPELINE(Performance, "Passes run at -O")
2829
PASSPIPELINE(Onone, "Passes run at -Onone")
2930
PASSPIPELINE(InstCount, "Utility pipeline to just run the inst count pass")

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ PASS(AccessEnforcementWMO, "access-enforcement-wmo",
6666
"Access Enforcement Whole Module Optimization")
6767
PASS(CrossModuleSerializationSetup, "cross-module-serialization-setup",
6868
"Setup serialization flags for cross-module optimization")
69+
PASS(CrossDeadFunctionElimination, "sil-cross-deadfuncelim",
70+
"Cross Dead Function Elimination")
6971
PASS(AccessSummaryDumper, "access-summary-dump",
7072
"Dump Address Parameter Access Summary")
7173
PASS(AccessedStorageAnalysisDumper, "accessed-storage-analysis-dump",

include/swift/SILOptimizer/PassManager/Passes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace swift {
4242
/// Run the SIL ownership eliminator pass on \p M.
4343
bool runSILOwnershipEliminatorPass(SILModule &M);
4444

45+
bool runSILCrossModuleEliminatorPass(SILModule &M);
46+
4547
void runSILOptimizationPassesWithFileSpecification(SILModule &Module,
4648
StringRef FileName);
4749

0 commit comments

Comments
 (0)