[PATCH] D125603: [ConstantRange] Improve the implementation of binaryAnd

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 16 08:29:04 PDT 2022


nikic added inline comments.


================
Comment at: llvm/lib/IR/ConstantRange.cpp:1392
+      && getMaxPowOf2Factor(*Other.getSingleElement()).ugt(getUnsignedMax()))
+    return { APInt::getZero(getBitWidth()) };
 
----------------
nikic wrote:
> In terms of general code structure, I'd do something like this:
> 
> ```
> if (const APInt *C = getSingleElement()) {
>   if (const APInt *OtherC = Other.getSingleElement())
>     return *C & *OtherC;
> 
>   // Your code here.
> } else if (Other.isSingleElement()) {
>   return Other.binaryAnd(*this);
> }
> ```
> 
> This is to avoid to implement the single element + range case for both orders.
> 
> In https://github.com/llvm/llvm-project/commit/8ab819ad90d647b96bb4b6842a742d2552ba9e9c I've added a `toKnownBits()` method, which you should be able to use to implement a more general variant of this. I.e. to a `toKnownBits()` on the non-single-element range, and them together and then use fromKnownBits(). That should cover your case, a few additional ones, and also be more "obviously correct".
Hm, I thought that the known bits approach would be always more accurate than the below code if one operand is completely known, but that's not the case. E.g. `[0, 0b100] & -1` should be `[0, 0b100]` rather than `[0, 0b111]`.

I think we might be best off first computing a range using `fromKnownBits(toKnownBits() & toKnownBits())` and then applying the existing umin of max rule on top of that. That should be strictly better than the current implementation, and be reasonably accurate in practice.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125603/new/

https://reviews.llvm.org/D125603



More information about the llvm-commits mailing list