This is an archive of the discontinued LLVM Phabricator instance.

[TRE] icmp does not escape an alloca
AbandonedPublic

Authored by caojoshua on May 28 2023, 8:58 PM.

Details

Summary

Potentially fixes https://github.com/rust-lang/rust/issues/111603.
Marking tail calls helps MemCpyOptimizer and AliasAnalysis remove a
memcpy.

Diff Detail

Event Timeline

caojoshua created this revision.May 28 2023, 8:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 28 2023, 8:58 PM
caojoshua updated this revision to Diff 526367.May 28 2023, 9:04 PM
caojoshua edited the summary of this revision. (Show Details)

Add details to commit msg

caojoshua edited the summary of this revision. (Show Details)

edit commit msg

caojoshua published this revision for review.May 28 2023, 10:25 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 28 2023, 10:25 PM
nikic requested changes to this revision.May 29 2023, 12:16 AM

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.

This revision now requires changes to proceed.May 29 2023, 12:16 AM

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?

nikic added a comment.May 29 2023, 4:16 AM

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.

jdoerfert requested changes to this revision.May 29 2023, 11:27 AM
jdoerfert added a subscriber: jdoerfert.

ICMP, in general, captures. Check the tests for the capture tracker for examples.

khei4 added a subscriber: khei4.May 29 2023, 6:58 PM
caojoshua abandoned this revision.May 31 2023, 8:54 PM

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