A function can be marked as norecurse if:
- The SCC to which it belongs has cardinality 1.
- It does not call any non-norecurse function. This includes self-recursion.
We can simply build up norecurse attributes in the existing SCC pass.
Differential D14228
[FunctionAttrs] Identify norecurse functions jmolloy on Nov 2 2015, 5:06 AM. Authored by
Details
A function can be marked as norecurse if:
We can simply build up norecurse attributes in the existing SCC pass.
Diff Detail
Event TimelineComment Actions I don't know the CGSCC enough: what about a function whose address is taken? What about potential call site from a different module you have no visibility to? Comment Actions Hi, My understanding is that CGSCC behaves conservatively - if a function's address is taken, an edge is added from the "Externally called" node to that function. However, in our case we don't actually need to care what can *call* a function, we just need to know whether or not we have full knowledge about what that function *can call*. That's why we only mark functions norecurse if we've enumerated successfully all call edges and found them not to form a cycle or encounter the special "calls external" node in which case all bets are off. James
Comment Actions Thanks for working on it!
Comment Actions Hi, Thanks all for the feedback. This new version is rebased to HEAD on top of Chandler's changes, and improves the way the algorithm works. I've added an extra inference rule - if a function F has only one callsite and that callsite is itself in a norecurse function, then F cannot recurse. Obviously this lends itself to top-down propagation rather than the bottom-up propagation we get with SCC passes. Now, we do the same bottom-up approach but if we see a function that is not obviously recursive but can't be proven non-recursive we save it and after the SCC is over we go and revisit it, top-down. This allows more functions to be marked norecurse. I think I've acted on all the review comments so far, and I've added more comments into the code to make it clearer what's going on. Cheers, James
Comment Actions Hi Mehdi, I agree with you, having thought about it. I've updated the patch to be less strict. Cheers, James Comment Actions Hi Mehdi, Sorry, I created the last diff from an old branch. This now contains the correct code. Cheers, James
Comment Actions Hi Manman, I think these should already be tested by the tests @called_by_norecurse and @called_by_norecurse_indirectly? Cheers, James Comment Actions Hi Manman, Chatting with Mehdi on IRC, I elaborated a bit on what that first check is doing; it's just an optimization. It's the same check as in the top-down-only function, it just runs a bit earlier so has the potential to catch more cases, earlier, opening up more opportunities for the other bottom-up checks. Mehdi rightly stated that it only affects functions that were marked norecurse before FunctionAttrs ran. He also mentioned that the checks should be factored together, which I agree with (changing the first check in bottom-up to just call addNoRecurseAttrsTopDownOnly(). James Comment Actions Hi Mehdi, I've removed the offending bottom-up check as we discussed yesterday. Cheers, James |
This is sad: it will run at the end of the SCC PassManager, it means you need a barrier after this pass in the pipeline before running another pass. (I don't have a better solution to suggest though).