This is an archive of the discontinued LLVM Phabricator instance.

[ConstantRange] Add abs() support
ClosedPublic

Authored by nikic on Apr 24 2019, 12:44 PM.

Details

Summary

Add support for abs() to ConstantRange. This will allow to handle abs select flavor in LVI and I think it will also come in handy for srem implementation.

The implementation is slightly tricky, because a) abs of signed min is signed min and b) sign-wrapped ranges may have an abs() that is smaller than a full range, so we need to explicitly handle them.

Diff Detail

Event Timeline

nikic created this revision.Apr 24 2019, 12:44 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 24 2019, 12:44 PM

I agree that the test makes sense, and the *logic* of the ConstantRange::abs() implementation makes sense.
But i'm not sure about INT_MIN handling.
The test certainly works, because we are only checking 4-bit values, while APInt is 64-bit or more.
What happens for ConstantRange's of larger width?
Maybe you should return ConstantRange with bitwidth larger by one if INT_MIN is included?

nikic added a comment.Apr 24 2019, 3:01 PM

The test certainly works, because we are only checking 4-bit values, while APInt is 64-bit or more.
What happens for ConstantRange's of larger width?

The bit width doesn't make a difference here: If the signed min for the particular bitwidth is in the original range, it will also be in the result range.

Maybe you should return ConstantRange with bitwidth larger by one if INT_MIN is included?

I don't think this would be particularly useful, at least in the context where this is intended to be used: The abs() implementation here models the semantics of SPF_ABS, which maps signed min onto signed min, and it's important to preserve that edge-case behavior.

We have similar code for handling abs of signed min in ValueTracking: https://github.com/llvm-mirror/llvm/blob/4d4155f08ea87c6909ddd6db4610c3d6c8034983/lib/Analysis/ValueTracking.cpp#L5669-L5679

lebedev.ri accepted this revision.Apr 25 2019, 2:30 PM

The test certainly works, because we are only checking 4-bit values, while APInt is 64-bit or more.
What happens for ConstantRange's of larger width?

The bit width doesn't make a difference here: If the signed min for the particular bitwidth is in the original range, it will also be in the result range.

Maybe you should return ConstantRange with bitwidth larger by one if INT_MIN is included?

I don't think this would be particularly useful, at least in the context where this is intended to be used: The abs() implementation here models the semantics of SPF_ABS, which maps signed min onto signed min, and it's important to preserve that edge-case behavior.

We have similar code for handling abs of signed min in ValueTracking: https://github.com/llvm-mirror/llvm/blob/4d4155f08ea87c6909ddd6db4610c3d6c8034983/lib/Analysis/ValueTracking.cpp#L5669-L5679

Okay, that clarifies things, thank you for pointing that out.
I believe ubsan will not complain here about negations, since APInt::negate() is always used.
LG.

This revision is now accepted and ready to land.Apr 25 2019, 2:30 PM
This revision was automatically updated to reflect the committed changes.