diff options
author | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-04-03 17:41:45 -0500 |
---|---|---|
committer | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-04-10 13:13:43 -0500 |
commit | 81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07 (patch) | |
tree | d1d6928ef2354dcbeacc3b025a7de4a2a97e2e84 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 2646790155f73d6cfb28ec0ee472056740e4658e (diff) | |
download | llvm-81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07.zip llvm-81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07.tar.gz llvm-81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07.tar.bz2 |
[ValueTracking] Add support for `xor`/`disjoint or` in `isKnownNonZero`
Handles cases like `X ^ Y == X` / `X disjoint| Y == X`.
Both of these cases have identical logic to the existing `add` case,
so just converting the `add` code to a more general helper.
Proofs: https://alive2.llvm.org/ce/z/Htm7pe
Closes #87706
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index f3ea73b..3a10de7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3207,20 +3207,33 @@ getInvertibleOperands(const Operator *Op1, return std::nullopt; } -/// Return true if V2 == V1 + X, where X is known non-zero. -static bool isAddOfNonZero(const Value *V1, const Value *V2, unsigned Depth, - const SimplifyQuery &Q) { +/// Return true if V1 == (binop V2, X), where X is known non-zero. +/// Only handle a small subset of binops where (binop V2, X) with non-zero X +/// implies V2 != V1. +static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2, + unsigned Depth, const SimplifyQuery &Q) { const BinaryOperator *BO = dyn_cast<BinaryOperator>(V1); - if (!BO || BO->getOpcode() != Instruction::Add) + if (!BO) return false; - Value *Op = nullptr; - if (V2 == BO->getOperand(0)) - Op = BO->getOperand(1); - else if (V2 == BO->getOperand(1)) - Op = BO->getOperand(0); - else - return false; - return isKnownNonZero(Op, Depth + 1, Q); + switch (BO->getOpcode()) { + default: + break; + case Instruction::Or: + if (!cast<PossiblyDisjointInst>(V1)->isDisjoint()) + break; + [[fallthrough]]; + case Instruction::Xor: + case Instruction::Add: + Value *Op = nullptr; + if (V2 == BO->getOperand(0)) + Op = BO->getOperand(1); + else if (V2 == BO->getOperand(1)) + Op = BO->getOperand(0); + else + return false; + return isKnownNonZero(Op, Depth + 1, Q); + } + return false; } /// Return true if V2 == V1 * C, where V1 is known non-zero, C is not 0/1 and @@ -3380,7 +3393,8 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth, }; } - if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q)) + if (isModifyingBinopOfNonZero(V1, V2, Depth, Q) || + isModifyingBinopOfNonZero(V2, V1, Depth, Q)) return true; if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q)) |