This is an archive of the discontinued LLVM Phabricator instance.

[ValueTracking] Let analyses assume a value cannot be partially poison
ClosedPublic

Authored by aqjune on Apr 20 2020, 9:20 AM.

Details

Summary

This is RFC for fixes in poison-related functions of ValueTracking.
These functions assume that a value can be poison bitwisely, but the semantics
of bitwise poison is not clear at the moment.
Allowing a value to have bitwise poison adds complexity to reasoning about
correctness of optimizations.

This patch makes the analysis functions simply assume that a value is
either fully poison or not, which has been used to understand the correctness
of a few previous optimizations.
The bitwise poison semantics seems to be only used by these functions as well.

In terms of implementation, using value-wise poison concept makes existing
functions do more precise analysis, which is what this patch contains.

Diff Detail

Event Timeline

aqjune created this revision.Apr 20 2020, 9:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2020, 9:20 AM
nikic added inline comments.Apr 20 2020, 10:03 AM
llvm/include/llvm/Analysis/ValueTracking.h
568

This doesn't seem to line up with the implementation, e.g. division ops return true for propagatesPoison.

I'm also not sure why we would not want to return true for immediate UB. It's a stronger condition, but it should always be fine to relax immediate UB into returning poison.

aqjune updated this revision to Diff 258797.Apr 20 2020, 11:06 AM

Correctly handle div/rems

aqjune marked an inline comment as done.Apr 20 2020, 11:14 AM
aqjune added inline comments.
llvm/include/llvm/Analysis/ValueTracking.h
568

Thanks, fixed.

I'm also not sure why we would not want to return true for immediate UB. It's a stronger condition, but it should always be fine to relax immediate UB into returning poison.

I think this is more natural in the sense that the operation wouldn't return a value when UB happened; it immediately exits the program.
It is analogous to what canCreatePoison(I) returns when I raises UB as well.

fhahn added a subscriber: fhahn.Apr 20 2020, 11:40 AM
aqjune updated this revision to Diff 258912.Apr 21 2020, 12:12 AM

Add unit tests for propagatesPoison

jdoerfert added inline comments.Apr 21 2020, 9:51 AM
llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
348

Is this true? I mean, don't you check for binary operands above?

llvm/test/Analysis/ScalarEvolution/nsw.ll
242 ↗(On Diff #259029)

Given the name of the function I tried to figure out what the reasoning here is.

  1. This patch is not NFC. Maybe split the wording changes from the functional ones.
  2. It seems valid to derive both nuw and nsw here but we should confirm with the history and the author of this test.
242 ↗(On Diff #259029)

Forget the NFC part but we could still split the wording changes from the rest ;)

aqjune updated this revision to Diff 259189.Apr 22 2020, 12:33 AM

Leave wording changes only

aqjune marked 2 inline comments as done.Apr 22 2020, 12:39 AM

I'll make a separate patch for the functional changes.
BTW, regarding the lldb failure that happened on the previous version of this patch, I ran ninja check-all on my ARM machine (with lldb included in the enable_project list) and couldn't reproduce the error. :/ As the patch is being separated, it will be a good chance to see which part is the root cause.

llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
348

It was my misunderstanding about the code, updated.

aqjune marked 2 inline comments as done.Apr 22 2020, 12:42 AM
aqjune added inline comments.
llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
348

BTW, what do you think about making this explicit in LangRef? I can make a patch for this.
If and/or blocks poison propagation, removal of trivial and/ors becomes invalid, because it makes the resulting program more poisonous.

This patch now only removes the Full part from the comments and names? If so, I think that makes sense. Let someone else give a second opinion though.

llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
348

That's a good question. I guess we could either say that bits you "overwrite" with and/or are not poison anymore but I am unsure that is what we want. The problem is that various operations could be used to fix bits and we should handle them all the same (x = y - y, x = y * 0, ...).

That said, we should have a discussion (= ask others).

nikic accepted this revision.Apr 22 2020, 9:24 AM

LG from my side. I believe this matches how we have been treating poison in practice, and matches what is most useful. The bitwise reasoning we do for undef is something of a PITA.

This revision is now accepted and ready to land.Apr 22 2020, 9:24 AM
aqjune marked an inline comment as done.Apr 22 2020, 3:56 PM
aqjune added inline comments.
llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
348

I can run Alive2 with several semantics on or/and & see what kind of optimizations are allowed/disallowed. It may take some time, but can be done by Friday.
I'll leave the result + references to relevant people at D78615.

aqjune retitled this revision from RFC: [ValueTracking] Let analyses assume a value cannot be partially poison to [ValueTracking] Let analyses assume a value cannot be partially poison.Apr 22 2020, 4:07 PM
This revision was automatically updated to reflect the committed changes.