Potentially fixes https://github.com/rust-lang/rust/issues/111603.
Marking tail calls helps MemCpyOptimizer and AliasAnalysis remove a
memcpy.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
This should be implemented in CaptureTracking first and foremost. TRE can be adjusted afterwards, or preferably should use CaptureTracking as well, instead of doing its own, incorrect reimplementation.
Just considering all icmps non-escaping is obviously wrong. The property you are looking for here is that if you have an icmp where both sides are at some offset of the same underlying object, then the icmp will only compare the offsets and not leak any bits of the pointer, and as such is not capturing.
Thanks for review. I don't understand how icmp's leak bits of a pointer. I asked this in https://discord.com/channels/636084430946959380/636732535434510338/1112644263029776414 as well. Could you take a look?
In the simplest case, icmp ptr eq %p, %p2 leaks whether the address of %p is the same as %p2. You could loop over all 2^64 possible %p2 to determine the address. Or more realistically, you could use inequality comparisons to bisect the address. Effectively you can implement ptrtoint with it.
That said, I've looked a bit closer at what this specific pass does, and as far as I can tell it does not actually care about address capture, only about provenance escape. So I think the legality question as far as this pass is concerned is, after determining the bits of the alloca address via a sequence of icmps, is it legal to perform an inttoptr operation and dereference the result? That is, does icmp only leak address bits, or can it also leak provenance?
If icmp does not leak provenance, then your patch is correct as-is. Otherwise we need the general reasoning about whether the icmp is capturing or not, as I described above.
I think icmp shouldn't leak provenance, but I couldn't find a definitive statement on this. Possibly this is caught up in the larger question of the provenance model around pointer/integer conversions, which icmps effectively perform.
Maybe @efriedma could comment on this.
I also think that icmp should not leak provenance. However, after looking at your example, I think TRE actually does care about address capture. If the address is captured by another pointer such as %p2 in your example, and we pass that pointer as an argument to a capturing call, %p is also captured and we can't mark tail calls. In this case, my patch is incorrect.
This should be implemented in CaptureTracking first and foremost. TRE can be adjusted afterwards, or preferably should use CaptureTracking as well, instead of doing its own, incorrect reimplementation.
Just considering all icmps non-escaping is obviously wrong. The property you are looking for here is that if you have an icmp where both sides are at some offset of the same underlying object, then the icmp will only compare the offsets and not leak any bits of the pointer, and as such is not capturing.
Extending CaptureTracking to support icmp's of pointers with the same underlying object seems like a reasonable choice. TRE's ad-hoc escape analysis has some specifics that may make it non-trivial to port to CaptureTracking, but we can look at that afterwards.
I'm going to abandon this. This issue can be solved in other ways. CaptureTracking can be improved, and this TRE-specific escape analysis can probably be rewritten in ways that depend on capture tracking