This is an archive of the discontinued LLVM Phabricator instance.

[ValueTracking] Sign bit of shl cannot be both known one and known zero. Fix PR28926
AbandonedPublic

Authored by lihuang on Aug 12 2016, 2:53 PM.

Details

Summary

[ValueTracking] Sign bit of shl cannot be both known one and known zero. Fix PR28926

This is to fix PR28296 caused by r278172 (D23296). When inferring the sign bit of a SHL from nsw flag, should update both KnownZero and KnownOne's sign bit. If the result of SHL is known to be non-negative, should set the sign bit of KnownZero to 1 and KnownOne to 0, vice versa. This cannot be implemented in KZF and KOF, because KZF only modifies knownZero and KOF only modifies knownOne.

Also made a little change to computeKnownBitsFromShiftOperator: extract the computeKnownBits(...) for operand 0 to its callsite, so that the "infer sign bit from SHL with nsw" logic can be implemented only at the SHL case.

Diff Detail

Event Timeline

lihuang updated this revision to Diff 67911.Aug 12 2016, 2:53 PM
lihuang retitled this revision from to [ValueTracking] Sign bit of shl cannot be both known one and known zero. Fix PR28926 .
lihuang updated this object.
lihuang added reviewers: majnemer, sanjoy.
lihuang added a subscriber: llvm-commits.
majnemer added inline comments.Aug 15 2016, 11:16 AM
lib/Analysis/ValueTracking.cpp
842–850

Shouldn't we just add this logic to the ConstantInt branch above, right before the return?
Then we could teach InstSimplify to xform this into the non-undef arm of the select.

sanjoy requested changes to this revision.Aug 15 2016, 11:24 AM
sanjoy edited edge metadata.

I've not reviewed the patch yet, but neither of the two PR numbers mentioned here seem related -- can you please check?

lib/Analysis/ValueTracking.cpp
1078

Can you do the same thing by a "normalization" step like:

// Bits that are known to be "both" zero and one are arbitrarily selected to be zero.
KnownZero |= (KnownZero & KnownOne);
KnownOne &= ~KnownZero;

?

If not, now that you have this logic here, can we clear out the logic
from KZF and KOF?

Also, were you able to pinpoint _why_ we ended up with a bit both proved
to be 0 and 1?

This revision now requires changes to proceed.Aug 15 2016, 11:24 AM
lihuang added inline comments.Aug 15 2016, 2:05 PM
lib/Analysis/ValueTracking.cpp
1078

We can't arbitrarily select 0 if they are both known to be zero, as this will hide some cases where the shift result could be actually inferred as having the same sign (negative) as its first operand. One example is the last test I added in known-signbit-shift.ll.

Sure, I should have done that, my mistake,

This is because we could have already shifted a KnownOne bit to the sign-bit by KOF when we are setting the inferred sign-bit of KnownZero in KZF, and also the other way around. For example:

  before shift:    KnownZero = 0x70000000
                         KnownOne =  0x40000000
after SHL by 1:  KnownZero = 0x00000000   inferred to 0x70000000
                          KnownOne = 0x70000000 (conflict)

We should keep the sign-bit of KnownZero and KnownOne to be the same as the first operand of shift. Actually this inspired me to fix the problem just in KZF and KOF. Anyway, I will make another patch after you revert r278172.

lihuang added inline comments.Aug 15 2016, 2:30 PM
lib/Analysis/ValueTracking.cpp
842–850

Thank you for the advice David. We could do this, but I think I still need to fix the logic in the SHL case of computeKnownBitsFromOperator as that's the root cause.

lihuang abandoned this revision.Aug 15 2016, 2:35 PM

Abandon this patch as r278172 has been reverted.