Fix parameter invariance analysis (MPR#7291)#731
Fix parameter invariance analysis (MPR#7291)#731mshinwell wants to merge 3 commits intoocaml:trunkfrom
Conversation
|
Having just talked to Leo about this, it might be that in fact (kind of conversely) the existing |
|
Right, so it looks like the way things work at the moment, we are going to freshen up all occurrences of the recursively-bound identifiers during simplification after specialisation---meaning that we probably do need to fix |
|
However the case that used to be |
|
@chambart I'm unsure whether the function variable <-> symbol mapping construction could still be at toplevel only. Leo suspects maybe it could be since we'll never replace a recursive call via a symbol in a subfunction during specialisation. |
|
@chambart Looking at |
|
Yes only toplevel application are rewritten since this function was not supposed to find compatible deep function calls. Also the current substitution effectively does not allow non invariant recursive calls, so By the way in the subpart Both recursive calls were did not preserve their arguments, why did this one not prevent the rewriting already ? Also I couldn't review carefully the change yet. |
|
Oh, sorry, I pasted the wrong version of the code! |
|
I think I know why we didn't spot it. Originally, inline_by_copying_function_declaration (or the name it had at the time) Applied a round of Flambda_utils.toplevel_substitution before running simplification, and was running simplification freshening. In particular, it had no freshening for the function itself. Hence in a situation like that, it was ok to specialize the recursive function as the specialisation was happening only toplevel, and deep recursive calls below functions where not changed. I think I forgot that when we made that change. Probably a lot of the testing related to that kind of cases were before that change. Also, for it to trigger in a noticeable way, it had to trigger in a situation where the only call preventing specialisation is below a function that was not inlined or specialised at definition point, but became when the whole function became specialised. This might be quite unfrequent. |
|
This fix will do for now. |
|
I tried to change a bit the handling of specialised recursive calls such that it would be safe to accept some recursive calls that does not keep the invariant parameters. The simple version is to add the original closure to the environment of the function and substitute every uses that are not a direct call to use that one instead. In this example that would mean that in the specialised version of the function (which is useless here, but this is another problem) the closure passed to list map would bind the original closure instead of the specialised one. The change for that is quite minimal, but requires applying a potentially costly Flambda_utils.toplevel_substitution during the specialisation. The not so simple version could push that idea a bit further and remember the original closure from which the specialised version comes from. When an application to the original closure is encountered inside the specialised function, if the arguments matches (are aliases) the call is rewritten to be a direct recursive one. This allows to also discover specialised calls opportunities after inlining inside the function, oppening the way for specialisation when doing some open recursions: In this case, when one is inlined, the call to f is rewritten to a recursive call. The simple one might be acceptable this late in the release, but the second one is certainly too complicated. I don't think that the additional substitution is too costly in that case (compared to the two calls to simplify on the expression just after), so I might propose the simple version as a pull request tomorrow (after some cleanup). |
|
@chambart OK, let's see the simple version as a separate pull request, and then we can decide which fix is less risky. I think we need one or the other for 4.04. |
|
@mshinwell I have pushed a first proposition for the 'simple' solution. It might be a bit too much for a change this late in the release. |
|
We think this is going to be superceded by #780 |
AFL: segfault and lock resetting (fixes ocaml#497). Also fixes broken ./configure -afl-instrument && make
Co-authored-by: Cuihtlauac ALVARADO <cuihtmlauac@tarides.com>
The Flambda analysis as to which parameters of recursive functions are invariant appears to be broken in the presence of recursive calls under subfunctions. I'm not sure why we didn't spot this earlier.
The example from MPR#7291 fails due to this problem. In that case the parameter
substof the following function is being marked as invariant, which is wrong:I think this patch fixes the problem; MPR#7291 seems to build ok now. It keeps track of the free variables mapping as it descends under lambdas, meaning that it can correctly identify variables that actually refer to one of the recursive functions being examined. There is some trickiness as regards variables that might be aliases to function symbols, as usual: I added an assertion in one place and a comment in another to try to clarify this.
At the moment, the resulting analysis is over-conservative: if there is a recursive call found from a subfunction then the corresponding parameter is deemed to have "any" value flowing to it. I think this probably suffices for the moment.
We should probably try to get this into 4.04.