diff options
author | Yingwei Zheng <dtcxzyw2333@gmail.com> | 2024-02-08 22:34:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-08 22:34:52 +0800 |
commit | d9e92765c5f9b0fa7adafa769dd13d37b6bca038 (patch) | |
tree | 0db2be537237db745aed3d8030b8f51a2955bef6 /llvm/lib/IR/ConstantRange.cpp | |
parent | 3ad63593dac390e320808f3de0e1906c5fa45c8a (diff) | |
download | llvm-d9e92765c5f9b0fa7adafa769dd13d37b6bca038.zip llvm-d9e92765c5f9b0fa7adafa769dd13d37b6bca038.tar.gz llvm-d9e92765c5f9b0fa7adafa769dd13d37b6bca038.tar.bz2 |
[ConstantRange] Improve ConstantRange::binaryXor (#80146)
`ConstantRange::binaryXor` gives poor results as it currently depends on
`KnownBits::operator^`.
Since `sub A, B` is canonicalized into `xor A, B` if `B` is the subset
of `A`, this patch reverts the transform in `ConstantRange::binaryXor`,
which will give better results.
Alive2: https://alive2.llvm.org/ce/z/bmTMV9
Fixes #79696.
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index cbb64b2..3394a1e 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1467,7 +1467,22 @@ ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const { if (isSingleElement() && getSingleElement()->isAllOnes()) return Other.binaryNot(); - return fromKnownBits(toKnownBits() ^ Other.toKnownBits(), /*IsSigned*/false); + KnownBits LHSKnown = toKnownBits(); + KnownBits RHSKnown = Other.toKnownBits(); + KnownBits Known = LHSKnown ^ RHSKnown; + ConstantRange CR = fromKnownBits(Known, /*IsSigned*/ false); + // Typically the following code doesn't improve the result if BW = 1. + if (getBitWidth() == 1) + return CR; + + // If LHS is known to be the subset of RHS, treat LHS ^ RHS as RHS -nuw/nsw + // LHS. If RHS is known to be the subset of LHS, treat LHS ^ RHS as LHS + // -nuw/nsw RHS. + if ((~LHSKnown.Zero).isSubsetOf(RHSKnown.One)) + CR = CR.intersectWith(Other.sub(*this), PreferredRangeType::Unsigned); + else if ((~RHSKnown.Zero).isSubsetOf(LHSKnown.One)) + CR = CR.intersectWith(this->sub(Other), PreferredRangeType::Unsigned); + return CR; } ConstantRange |