This is an archive of the discontinued LLVM Phabricator instance.

[IsKnownNonZero] Handle the case with non-constant phi nodes
ClosedPublic

Authored by skatkov on Sep 24 2020, 8:19 PM.

Details

Summary

Handle the case when all inputs of phi are proven to be non zero.

Constants are checked in beginning of this method before check for depth of recursion,
so it is a partial case of non-constant phi.

Recursion depth is already handled by the function.

Diff Detail

Event Timeline

skatkov created this revision.Sep 24 2020, 8:19 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 24 2020, 8:19 PM
skatkov requested review of this revision.Sep 24 2020, 8:19 PM
aqjune accepted this revision.Sep 25 2020, 12:09 AM

LGTM

This revision is now accepted and ready to land.Sep 25 2020, 12:09 AM
nikic requested changes to this revision.Sep 25 2020, 12:30 AM
nikic added inline comments.
llvm/lib/Analysis/ValueTracking.cpp
2567

It is necessary to adjust the context instruction in Q to be the terminator of the incoming edge here (see what computeKnownBits does for example).

This revision now requires changes to proceed.Sep 25 2020, 12:30 AM
aqjune added inline comments.Sep 25 2020, 12:40 AM
llvm/lib/Analysis/ValueTracking.cpp
2567

Does it mean that we need updates in a few other places as well (orthogonally from this patch)? e.g., https://github.com/llvm/llvm-project/blob/master/llvm/lib/Analysis/ValueTracking.cpp#L2970

skatkov updated this revision to Diff 294247.Sep 25 2020, 1:37 AM

Thank you for review.

Is it better?

nikic added a comment.EditedSep 25 2020, 11:56 AM

Thanks for the update, the new version should be correct. However, it can also be expensive, because we may loop through a phi multiple times until the depth limit is exhausted. I would suggest to follow the same implementation approach as computeKnownBits() does in https://github.com/llvm/llvm-project/blob/d2166076b882e38becf3657ea830ffd2b6a5695e/llvm/lib/Analysis/ValueTracking.cpp#L1574-L1606. Namely to perform the recursive call with MaxDepth - 1. (I would also suggest to handle your TODO right away, to have parity with the known bits code.)

Edit: Current compile-time results for reference: https://llvm-compile-time-tracker.com/compare.php?from=f161e84c10b6eb2255345ebfaaa2bbadb4b0fe2a&to=541eefb28e624a99b22408b4322720bc6cd6972f&stat=instructions We should be able to do better than that.

llvm/lib/Analysis/ValueTracking.cpp
2567

Yes, looks like that one needs to be fixed as well.

aqjune added inline comments.Sep 26 2020, 8:13 AM
llvm/lib/Analysis/ValueTracking.cpp
2567

Made a patch here: D88360.

Thanks for the update, the new version should be correct. However, it can also be expensive, because we may loop through a phi multiple times until the depth limit is exhausted. I would suggest to follow the same implementation approach as computeKnownBits() does in https://github.com/llvm/llvm-project/blob/d2166076b882e38becf3657ea830ffd2b6a5695e/llvm/lib/Analysis/ValueTracking.cpp#L1574-L1606. Namely to perform the recursive call with MaxDepth - 1. (I would also suggest to handle your TODO right away, to have parity with the known bits code.)

Edit: Current compile-time results for reference: https://llvm-compile-time-tracker.com/compare.php?from=f161e84c10b6eb2255345ebfaaa2bbadb4b0fe2a&to=541eefb28e624a99b22408b4322720bc6cd6972f&stat=instructions We should be able to do better than that.

Well, I can restrict the depth for phi nodes only to one level but it seems it causes the strange correlation to max depth. I tend to think that it would be better to increase depth to number of phi operands than restrict it to one level. In this case we can treat max depth as number of invocation of function. So it would be linear.

Please also note that right before phi handling we have a switch handling. It does not use one level depth as well as it does not modify the context instruction while select is actually can be considered as equivalent of phi node. Should be switch fixed as well?

skatkov updated this revision to Diff 294592.Sep 27 2020, 8:37 PM

please take a look. Still think that restriction to one level is too strong but let's start with it.

skatkov updated this revision to Diff 294595.Sep 27 2020, 9:11 PM

Do not go to recursion if we handle this phi node with the same context. If context is different, the answer might be different in theory.

@nikic thanks for catching this, these are a pain to debug later on (I remember D69571). That said, we should probably add a test that shows why this is necessary. Can you take a look at the test in D71181 and https://reviews.llvm.org/D60846#1497243 to make sure we have a similar one for coverage here?

Please also note that right before phi handling we have a switch handling. It does not use one level depth as well as it does not modify the context instruction while select is actually can be considered as equivalent of phi node. Should be switch fixed as well?

Select do not require a change in context (as far as I can tell). A PHI is "assigned/evaluated" on the incoming edge, not in the PHI block. The key difference is that the incoming value does not dominate the phi while this has to be the case for the select.


please take a look. Still think that restriction to one level is too strong but let's start with it.

(Disclaimer, I'm obviously biased towards the Attributor.)
TBH, I don't think such logic belongs here anyway. The problem is that we do not "cache" results but simply recompute them, given use-def cycles that can spiral out of control.
If you run the Attributor it will deduce and annotate various locations with nonnull, if we are missing some we can talk about ways to improve it.


Nit: typo in the commit message.
Nit: consider Q.getWithInstruction, no strong feelings.

Nit: consider Q.getWithInstruction, no strong feelings.

Q is not SimplifyQuery here, how I could take a getWithInstruction then?

Nit: consider Q.getWithInstruction, no strong feelings.

Q is not SimplifyQuery here, how I could take a getWithInstruction then?

You won't, just ignore that part ;)

skatkov edited the summary of this revision. (Show Details)Sep 27 2020, 11:00 PM

Nit: consider Q.getWithInstruction, no strong feelings.

Q is not SimplifyQuery here, how I could take a getWithInstruction then?

You won't, just ignore that part ;)

I did :)

nikic added inline comments.Sep 28 2020, 12:48 AM
llvm/lib/Analysis/ValueTracking.cpp
2569

Why the RecQ.CxtI == Q.CxtI check here? Shouldn't we always be able to skip, regardless of context?

skatkov added inline comments.Sep 28 2020, 4:49 AM
llvm/lib/Analysis/ValueTracking.cpp
2569

Not sure, just to be conservative. I have no some concrete example. Can remove until some example is found.

skatkov updated this revision to Diff 294874.Sep 28 2020, 8:21 PM

git rid of additional check for context instruction.

nikic accepted this revision.Sep 29 2020, 12:43 AM

LGTM

This revision is now accepted and ready to land.Sep 29 2020, 12:43 AM