This patch addresses part of Bug 33648. It adds new information to the summary and implements part of the FunctionAttrs pass (propagating read attrs and norecurse attrs). The other part of the pass is not implement at the moment, since it requires argument information which currently is not included in the summary.
Diff Detail
Event Timeline
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
---|---|---|
413 | I'm don't think this entirely correct. The reason I did it this way was so I could reuse the computeFunctionBodyMemoryAccess from the original FunctionAttrs pass. I think I'll need to modify that function a bit to work with the Index so it can access information about functions external to the current module. |
Just a note: this isn't fully completed yet. I still have to add tests and do some verification, but I wanted to make it's on the right track.
Thanks, that's a very good start! Few comments inline, I didn't understand everything.
include/llvm/IR/ModuleSummaryIndex.h | ||
---|---|---|
60 | I think we may get to the point with this structure where documenting fields here would be nice. | |
294 | Doc. | |
366 | Doc (including return value). I'd suggest naming it: `updateCalleeMemAccessKind()` | |
include/llvm/Transforms/IPO/FunctionAttrs.h | ||
36 | DenseMap instead of std::map? | |
include/llvm/Transforms/IPO/FunctionImport.h | ||
106 | Doc (simple). | |
129 | Doc. | |
lib/Transforms/IPO/FunctionImport.cpp | ||
424 | Here I'd expect a better description of "how" you're gonna achieve the API contract, i.e. a high level view about what's involved. | |
425 | naming could help understand. Something like `all_of_calllees` or something like that (may still need a comment. | |
427 | std::function``` is heavy, use ```llvm::function_ref``` here. | |
430 | Are we sure there can't be an alias summary here? | |
440 | early continue: FunctionSummary *F = dyn_cast<FunctionSummary>(S.get()); if (!F) continue; ... | |
443 | Doc. | |
445 | Not sure why the second condition is needed? | |
551 | Agree, but coherent with the one right below... | |
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
443 | Why do we need to mark the edges? |
lib/Transforms/IPO/FunctionImport.cpp | ||
---|---|---|
445 | I copied that out of the original FunctionAttrs pass to prevent the function from being marked NoRecurse if it calls itself (http://llvm-cs.pcc.me.uk/lib/Transforms/IPO/FunctionAttrs.cpp#1068). | |
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
443 | I was planning on using that to propagate read attrs up to the caller. For instance: void x(int *k) { // can't mark readonly since k could be global *k++; } void j() { int i = 5; x(&i); // since i is local memory, we can mark j as readnone } I'm currently working on implementing this - when I finish I'll update the patch. |
It looks like you are on the right track from the standpoint of dividing it up into pieces implemented during the compile step (building the index), the thin link (propagating), the backend (applying). I have a few comments after a quick initial perusal. But note when you have something ready for a full review, you should create a new patch that adds llvm-commits as a subscriber.
lib/Transforms/IPO/FunctionAttrs.cpp | ||
---|---|---|
94 | These used to be continues, I think the change to an early return will mean that not all call site args are analyzed? | |
lib/Transforms/IPO/FunctionImport.cpp | ||
443 | CalleeInfo unused. But in any case, I don't think the checking here is sufficient as it will only detect self-recursion, not indirect recursion (e.g. A->B->A). For that you need to build the SCC (strongly connected components) on the call graph in the index. See for example addNoRecurseAttrs where it first checks if the SCC has more than one function (in which case there is automatically indirect recursion). I wonder if the SCC builder in llvm can be made to work for the index call graph? See SCCIterator.h. You'd need to provide GraphTraits for the index graph. Additionally, the memory access info needs to be propagated during the thin link. See how FunctionAttrs propagates them across the SCC. See addReadAttrs() for example. | |
559 | As mentioned above, this needs to be computed on the SCC. | |
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
413 | This is called from the compile step, so there is no information in the Index for external functions. Here you just want to compute the per function attribute info to put into the index for the global analysis to use during the thin link. | |
494 | Can this just be moved into the ModuleSummaryIndex builder (see ModuleSummaryAnalysis.cpp)? We should do all the building of the index there. |
Thank you for the feedback and corrections, @mehdi_amini and @tejohnson. I wasn't understanding the purpose of SCCNodes when I initially wrote the patch - thanks for clarifying :)
I'm going to work on GraphTraits for the ModuleSummaryIndex so SCCNodes can be used during the propagation step. After doing that and some cleanup I'll resubmit the patch to llvm-commits, unless anyone has any major modifications I should make to this patch.
lib/Transforms/IPO/FunctionAttrs.cpp | ||
---|---|---|
94 | It's kinda messed up by the diff, I moved callsite analysis to its own function (analyseCallSite). Line 148 shows where it's called. | |
lib/Transforms/IPO/FunctionImport.cpp | ||
443 |
Ah, good point. Now I see what the SCCNodes are for.
I started looking into this, and I think it'll be possible with a few more iterator types. |
lib/Transforms/IPO/FunctionImport.cpp | ||
---|---|---|
445 | This comment does not display in the right place for me right now, to clarify I'm wondering about this: if (!S->fflags().NoRecurse || S->getOriginalName() == F->getOriginalName()) So the second check here is intended to check for self-recursion. Are we recording self-recursion in the summaries? | |
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
443 | I think it is complex enough that doing it in two patches would be easier to review and assert correctness, catch edge cases, and make sure we have the right level of test coverage. Also if possible, I'd even break it so that you first implement propagating only readnone, forget about norecurse and other stuff, and you don't need SCC. Then you can add more stuff. Again we'll have more targeted testing and we are less likely to miss anything in review (and if we need to bisect a failure, it'll be easier to pinpoint the faulty logic as well). |
lib/Transforms/IPO/FunctionImport.cpp | ||
---|---|---|
445 |
I think so. I'll double check, but I think this is a redundant check (in which case I'll remove it). | |
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | ||
443 | Sounds good - I was thinking about splitting it into multiple patches, and I agree with that level of granularity (i.e. a patch for propagating readnone, a patch for readnone propagated across call edges, and a patch for no recurse). |
This is a decent start, some comments inline. Thanks!
include/llvm/IR/ModuleSummaryIndex.h | ||
---|---|---|
306 | Comment? | |
370–372 | Do you need the -> bool ? | |
lib/Transforms/IPO/FunctionAttrs.cpp | ||
89–94 | range for? | |
121–123 | I find this a little harder to read, maybe you can use an explicit continue instead of LLVM_FALLTHROUGH ? | |
993 | spurious new whiteline. |
I think we may get to the point with this structure where documenting fields here would be nice.