Hi, everyone. Since last week, I had been prototyping @Arnold and @Michael_Gottesman 's architecture.
Here is my rough implementation of the architecture:
Overview
Almost the same as LLVM's Thin LTO
- Emit module summary
- Add a new file type
.swiftmodule.sumary
. - It serializes a module's call graph, Witness Table, and VTable information.
- The structure is similar to LLVM Thin LTO summary.
- swift-frontend's option
-emit-module-summary-path
corresponds the emission. - This can be done in parallel.
- Add a new file type
- Merge summaries
-
swift-frontend -cross-module-opt [module summary file...]
links and merges multiple summaries. - And prepare for optimization at this phase (e.g. Marking dead functions)
- This is sequential stage
-
- Performing Optimizations for each modules
- Pass merged module summary to swift-frontend via
-module-summary-path
- My prototype implements only simple Dead Function Elimination.
- This can be done in parallel
- Pass merged module summary to swift-frontend via
# 1. Emit module summary for 'module1' into './module1.swiftmodule.summary'
$ swift-frontend -emit-sib module1.swift \
-emit-module-summary-path module1.swiftmodule.summary \
-parse-as-library
$ swift-frontend -emit-module module1.swift -parse-as-library
# 2. Emit module summary for 'main' into './main.swiftmodule.summary'
$ swift-frontend -emit-sib main.swift \
-emit-module-summary-path main.swiftmodule.summary
# 3. Merge module summaries into one summary file, link them and mark dead functions
$ swift-frontend -cross-module-opt \
main.swiftmodule.summary module1.swiftmodule.summary \
-o merged-module.summary
# 4. Do Dead Function Elimination for 'module1' module using the combined module summary
$ sil-opt -emit-sil module1.sib \
-module-summary-path merged-module.summary \
--sil-cross-deadfuncelim
# 5. Do again for 'main' module.
$ sil-opt -emit-sil main.sib \
-module-summary-path merged-module.summary \
--sil-cross-deadfuncelim
Module Summary file format
The module summary file consists of call graph information and virtual method table information.
func myPrint(_ text: String) { ... }
public protocol Animal {
func bark()
}
public struct Cat: Animal {
public func bark() { myPrint("mew") }
}
public struct Dog: Animal {
public func bark() { myPrint("bow")}
}
public func callBark<T: Animal>(_ animal: T) {
animal.bark()
}
For example, this swift file would be summarized as: