-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Preserve SIL when merging modules #8388
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
Preserve SIL when merging modules #8388
Conversation
So @jrose-apple, the problem is that while we constructed a SIL module with the right sections, nothing was forcing them to be read in. Also, I'm going to disable the SIL optimizer when there's no primary file. Does the general approach here look reasonable? |
You can't just disable the SIL optimizer when there's no primary file; that's WMO mode. Really in merge-modules we don't want to run any SIL passes—mandatory, optimizing, whatever. I took a manual stab at it at one point by passing |
lib/FrontendTool/FrontendTool.cpp
Outdated
SM->verify(); | ||
if (!PrimarySourceFile) { | ||
SM->linkAll(); | ||
SM->dump(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clearly a WIP. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what's being proposed, but -disable-sil-perf-optzns
should be analogous to -disable-llvm-optzns
. It should only disable optional SIL passes and should not affect functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Onone optimization passes are optional. (I'm not talking about the mandatory passes; this is the specific set of "optimizations run even at Onone".)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@atrick That is what I said below. They should add a different flag for this. @jrose-apple This brings up an interesting question. Right now we do not have that concept in our pipeline. Optimizations that run at -Onone are considered mandatory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's well understood that -Onone
does not do what it says. The -disable
flag should also disable the Onone optimizations. It's just that no one has bothered implementing it.
@@ -112,6 +112,10 @@ class SerializedSILLoader { | |||
|
|||
/// Deserialize all SILFunctions, VTables, and WitnessTables for | |||
/// a given Module. | |||
void getAllForModule(Identifier Mod); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same as passing nullptr
for PrimaryFile
below. I'm not sure if this is better because it's more explicit, or worse because it's easy to do by accident.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it's the opposite. If you pass a null primary file below, we call getAll(true) on each iteration. I want to call getAll(false).
Ah. My bad on the primary file check. How do I detect that we have no source files? |
I don't know if that's the right check either. Last time I talked to @gottesmm about this we thought it probably made sense to add more SIL stages, and then be more careful about mixing them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrose-apple I would rather add a separate flag than the perf flag. The reason why is that sometimes it is useful to just disable the perf passes despite doing at -O build.
include/swift/SIL/SILModule.h
Outdated
@@ -459,6 +459,8 @@ class SILModule { | |||
/// Link in all VTables in the module. | |||
void linkAllVTables(); | |||
|
|||
void linkAll(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to redo this and add comments etc. I just wanted to get feedback on the general approach(and it turns out I forgot WMO exists)
@slavapestov SGTM! In terms of general approach, IMO greater granularity is in general better. Not having to recompile when debugging is good. |
77de22f
to
f731ea5
Compare
@swift-ci Please test |
1 similar comment
@swift-ci Please test |
This is now ready for review -- @graydon, @jrose-apple, @gottesmm. |
Build failed |
Looks like swift-xcode-playground-support exposed a real bug here. |
Reduced test case:
It's crashing while deserializing the generic environment of _T0So19NSRegularExpressionC15MatchingOptionsVs10SetAlgebra10FoundationsAEPxqd__cs8SequenceRd__8Iterator_7ElementQYd__AJRtzlufCTW, which is a protocol conformance witness thunk:
Of course the code compiles with -WMO or without -sil-merge-partial-modules so the driver or frontend must not be configuring something that would allow the imported decl to be found. @jrose-apple Any ideas? Should be a simple oversight on my part. |
It could just be another case where SIL ends up pulling in new declarations from the Clang importer too late in the process. This isn't a new issue, but we mostly avoid it today by not having inlinable code that references Clang declarations. I'm not sure that simply declaring a TypeChecker that lives through the whole merge-modules phase is correct either—SILGen and SILOpt are probably set up to assume the set of external declarations doesn't change. |
That is, it's possible there's a whole army of yaks over this hill. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad this is mostly coming out pretty simple, though!
include/swift/AST/SILOptions.h
Outdated
@@ -56,6 +56,11 @@ class SILOptions { | |||
/// Controls how to perform SIL linking. | |||
LinkingMode LinkMode = LinkNormal; | |||
|
|||
/// Controls whether to pull in SIL from partial modules during the | |||
/// merge modules step. Could perhaps be merged with the link mode | |||
/// above but the interactions between all the flags are tricky. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth trying to merge them, in the spirit of "not leaving work around to clean up later". The settings are already not orthogonal.
|
||
// Disable SIL optimization passes; we've already optimized the code in each | ||
// partial mode. | ||
Arguments.push_back("-disable-diagnostic-passes"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*sigh* I wish this was inferred, but meanwhile this seems reasonable.
// Disable SIL optimization passes; we've already optimized the code in each | ||
// partial mode. | ||
Arguments.push_back("-disable-diagnostic-passes"); | ||
Arguments.push_back("-disable-sil-perf-optzns"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should change this to also disable running the Onone passes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jrose-apple I think in such a case in our pipeline, we need a better separation conceptually in between the "diagnostic passes" and the "mandatory optimizations". Those should be conceptually two different groups of passes. I would rather have a separate flag. Perhaps:
-disable-sil-mandatory-optzns.
And then a third flag that just disables /all/ swift optzns, i.e.:
-disable-sil-optzns
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm talking about SILPassPipelinePlan::getOnonePassPipeline. That's not mandatory optimizations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, "mandatory optimizations" is an oxymoron, and therefore I wouldn't expect -disable-sil-optzns
to disable the mandatory passes. Skipping the diagnostic passes and the mandatory passes should just be automatic from seeing the SIL stage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I talked with @jrose-apple offline. Turns out my memory was wrong and the -Onone pass pipeline is not what I thought it was. The -Onone pass pipeline is a pass pipeline that includes extra optimizations run at -Onone.
For posterity here's a test case that triggers this problem even without my change. x.swift:
y.swift:
Compile x.swift with WMO, and y.swift with -O (doesn't matter if you enable WMO or not). |
Maybe we can throw that into the validation suite. |
f731ea5
to
72e40e9
Compare
@DougGregor recently did some work on the ClangImporter. Let's try running the tests again. |
@swift-ci Please test |
Build failed |
New failure, but in the same code:
|
@DougGregor looks like it got further, though. This is in SIL verification at the end of merge-modules. |
You know, that backtrace looks a whole lot like something fixed by #8812. |
@swift-ci Please test |
Build failed |
No such luck. Needs actually debugging |
@swift-ci Please test macOS |
72e40e9
to
5c45ba8
Compare
5c45ba8
to
a521f17
Compare
@swift-ci Please test |
@swift-ci Please test source compatibility |
Build failed |
This test used to fail because we would look up an associated type in an incomplete conformance after Sema was torn down, causing a crash. Now, the ClangImporter is able to correctly complete the conformance.
Also pass flags to disable SIL optimization passes when merging modules, since that's completely unnecessary. An evolution test that used to fail with WMO disabled now passes with this change. FIxes <rdar://problem/18913977>.
Meh, you're missing a REQUIRES: objc_interop one of the new tests. |
a521f17
to
cf9e266
Compare
Source compat test suite passed. This new version just adds the REQUIRES:. |
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
I think this is causing a failure on some of our internal bots -- reverting for now. |
Fixes rdar://problem/18913977.
Now that #11909 and previous PRs are in, we can finally look up associated types in imported conformances after Sema has been torn down. Phew!
Next steps in this area: