This is an archive of the discontinued LLVM Phabricator instance.

[IPSCCP] Add lattice value for != constant
AbandonedPublic

Authored by fhahn on Aug 29 2018, 8:40 AM.

Details

Summary

This patch extends IPSCCP's lattice to represent val != Constant which is used to propagate
facts for the 'false' BB following an X == Const condition.

Currently there is not measurable impact on performance or code size and a very small
increase in number of constant propagated with -flto.

The main reason for adding this patch is that it brings us closer to using ValueLatticeElement
as general lattice in SCCP, which which will enable range based analysis. With integer range
support, propagating information from conditions becomes much more powerful.

Diff Detail

Event Timeline

fhahn created this revision.Aug 29 2018, 8:40 AM

Does this patch + https://reviews.llvm.org/D50039 optimizes following code?

int l = strlen(s);
if (!s) <-- remove this condition

return -1;

return len;

fhahn added a comment.Aug 29 2018, 9:33 AM

Does this patch + https://reviews.llvm.org/D50039 optimizes following code?

int l = strlen(s);
if (!s) <-- remove this condition

return -1;

return len;

Nope, this patch would add nonnull to the argument in this case

if (!s) {
   return -1:
} else {
  return strlen(s)
}

Once we have a notconst lattice value, we could however eliminate the condition in with some more work:

  1. for call sites with nonnull arguments, we could create a ssa copy of the argument and mark it as not null. (The copy ensures we only use the fact in places dominated by the call site. Not sure if inserting copies for that will have an impact on the runtime, so it might not work overall)
  2. deduce false for "x == null" with x not null
efriedma added inline comments.Aug 29 2018, 3:59 PM
lib/Transforms/Scalar/SCCP.cpp
843

I guess you could try to resolve a PHI to NotConstant...? Not sure how important that is.

1798

I'm not sure this is right: nonnull is UB if the value is null, but SCCP can merge an "Undef" into a NotConstant.

fhahn added inline comments.Aug 30 2018, 9:16 AM
lib/Transforms/Scalar/SCCP.cpp
843

Yep, there should be a TODO here (and in other places)

1798

I think I am missing something. tryToAddNonNull is used after we finished solving and a lattice value of notconstant(Null) should mean "we proved that the value is != null". If we merge an undef into a NotConstant, isn't that similar to when we merge an undef into a Constant, where it is safe to use the constant after solving?

efriedma added inline comments.Aug 30 2018, 11:44 AM
lib/Transforms/Scalar/SCCP.cpp
1798

The difference is how we're using the result. If we take a value that's undef and replace it with a constant, that's fine; the undef might have resolved to that constant anyway. If we take a value that's undef and assert it's nonnull, that will explode if the undef actually resolves to null.

Note this is specifically a problem with our weird handling of IR "undef" values; if we treated "undef" as overdefined or constant, the lattice represents what you want it to represent. It's possible that nonnull optimization is important enough that it's better to just kill off all the undef special-case optimizations to make this legal.

fhahn added inline comments.Aug 30 2018, 12:05 PM
lib/Transforms/Scalar/SCCP.cpp
1798

Right, thanks Eli! I'll see if it is feasible to go to overdefined when merging undef into notconstan to start with.

fhahn added a comment.Aug 30 2018, 1:49 PM

Does this patch + https://reviews.llvm.org/D50039 optimizes following code?

int l = strlen(s);
if (!s) <-- remove this condition

return -1;

return len;

I've put together another POC patch based on this one to optimize the code you mentioned: D51505. It's not really ready for being reviewed, but it should give an idea how we might be able to handle this. Do you have any motivating benchmarks/use cases for this in particular?

fhahn updated this revision to Diff 163693.Sep 3 2018, 5:07 AM

updated merging of unknown and notconstant values to go to overdefined

fhahn added inline comments.Sep 3 2018, 5:13 AM
lib/Transforms/Scalar/SCCP.cpp
1798

I've updated mergeInValue to go to overdefined when merging unknown and notconstant. I think that should cover the cases where we combine 2 values of unknown/notconstant to notconstant.

I've also added a test case that should be an instance where we cannot infer nonnull. What do you think?

fhahn added inline comments.Sep 14 2018, 12:12 PM
lib/Transforms/Scalar/SCCP.cpp
1798

Eli, do you think the change is enough to be correct?

fhahn added a comment.Oct 10 2018, 8:44 AM

ping :) Eli do you think it is safe after the latest update or do you think there still are potential problems?

You're making the lattice really confusing. Essentially, there are now two different merging rules: one is used if the caller calls mergeInValue, and a different one is used if the caller calls markNotConstant etc. So it's not obvious what the lattice actually represents.


And actually, thinking about it a bit more, there's a more fundamental problem with proving a value is non-null. Given that a value is possibly-undef, it could be null even for code dominated by a null-check. So the entire proposed transform is unsound unless you freeze the pointer.

This doesn't normally cause a problem for existing SCCP analysis because the only transform SCCP usually performs is refining an value to a specific constant. (It also erases dead code, but that isn't really relevant here.) Along a path where x==null is true, it's possible for x to evaluate to some non-null value. but it's still okay for SCCP to replace x with null.

fhahn added a comment.Oct 16 2018, 2:59 PM

You're making the lattice really confusing. Essentially, there are now two different merging rules: one is used if the caller calls mergeInValue, and a different one is used if the caller calls markNotConstant etc. So it's not obvious what the lattice actually represents.


And actually, thinking about it a bit more, there's a more fundamental problem with proving a value is non-null. Given that a value is possibly-undef, it could be null even for code dominated by a null-check. So the entire proposed transform is unsound unless you freeze the pointer.

Right, thanks Eli! I think we would have to same problem when we would use conditions to derive constant ranges. I am not sure what you mean by freezing the pointer I am afraid. In case you are at the dev meeting, is that something you would be interested to talk about briefly?

This doesn't normally cause a problem for existing SCCP analysis because the only transform SCCP usually performs is refining an value to a specific constant. (It also erases dead code, but that isn't really relevant here.) Along a path where x==null is true, it's possible for x to evaluate to some non-null value. but it's still okay for SCCP to replace x with null.

I am not sure what you mean by freezing the pointer I am afraid.

I mean replace all the relevant uses of the pointer with a "freeze" instruction (as in https://reviews.llvm.org/D29011) on that pointer.

In case you are at the dev meeting, is that something you would be interested to talk about briefly?

I won't be at the dev meeting this year.

fhahn added a comment.Oct 16 2018, 3:48 PM

I am not sure what you mean by freezing the pointer I am afraid.

I mean replace all the relevant uses of the pointer with a "freeze" instruction (as in https://reviews.llvm.org/D29011) on that pointer.

Ah yes, thank you very much for pointing me to D29011, this sounds exactly like what we would need!

In case you are at the dev meeting, is that something you would be interested to talk about briefly?

I won't be at the dev meeting this year.

fhahn planned changes to this revision.Oct 16 2018, 3:49 PM
fhahn added a parent revision: D29011: [IR] Add Freeze instruction.
fhahn updated this revision to Diff 173151.Nov 8 2018, 6:03 AM
fhahn marked an inline comment as done.
fhahn retitled this revision from [WIP][IPSCCP] Add lattice value for != constant and propagate nonnull. to [IPSCCP] Add lattice value for != constant .
fhahn edited the summary of this revision. (Show Details)

I stripped adding nonnull for now. Even with freeze, we have to be far too conservative about the merging rules. This patch is now more an enabler to make it easier to use ValueLAtticeElement, with range support. What do you think?

fhahn abandoned this revision.Apr 30 2019, 8:39 AM

I plan to add this on top of the integer range support patches, abandoning this for now