aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2023-04-18 16:34:56 -0500
committerNoah Goldstein <goldstein.w.n@gmail.com>2023-04-18 17:17:57 -0500
commite846ec57cb80cd482b3a05b2b68c89775f806e6c (patch)
tree95716019b5810771b4fdc749fc15737ac754ec7c /llvm/lib/Analysis/ValueTracking.cpp
parent726f8ecac23bf04b60f9f079ee922b8a7a30457f (diff)
downloadllvm-e846ec57cb80cd482b3a05b2b68c89775f806e6c.zip
llvm-e846ec57cb80cd482b3a05b2b68c89775f806e6c.tar.gz
llvm-e846ec57cb80cd482b3a05b2b68c89775f806e6c.tar.bz2
Recommit "[ValueTracking] Apply the isKnownNonZero techniques in `ashr`/`lshl` to `shl` and vice-versa" (2nd Try)
Wasn't related to the bug it was original thought to be causing.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp76
1 files changed, 53 insertions, 23 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 9fbd995..3f2ee99 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2512,6 +2512,57 @@ static bool isNonZeroRecurrence(const PHINode *PN) {
}
}
+static bool isNonZeroShift(const Operator *I, const APInt &DemandedElts,
+ unsigned Depth, const Query &Q,
+ const KnownBits &KnownVal) {
+ auto ShiftOp = [&](const APInt &Lhs, const APInt &Rhs) {
+ switch (I->getOpcode()) {
+ case Instruction::Shl:
+ return Lhs.shl(Rhs);
+ case Instruction::LShr:
+ return Lhs.lshr(Rhs);
+ case Instruction::AShr:
+ return Lhs.ashr(Rhs);
+ default:
+ llvm_unreachable("Unknown Shift Opcode");
+ }
+ };
+
+ auto InvShiftOp = [&](const APInt &Lhs, const APInt &Rhs) {
+ switch (I->getOpcode()) {
+ case Instruction::Shl:
+ return Lhs.lshr(Rhs);
+ case Instruction::LShr:
+ case Instruction::AShr:
+ return Lhs.shl(Rhs);
+ default:
+ llvm_unreachable("Unknown Shift Opcode");
+ }
+ };
+
+ if (KnownVal.isUnknown())
+ return false;
+
+ KnownBits KnownCnt =
+ computeKnownBits(I->getOperand(1), DemandedElts, Depth, Q);
+ APInt MaxShift = KnownCnt.getMaxValue();
+ unsigned NumBits = KnownVal.getBitWidth();
+ if (MaxShift.uge(NumBits))
+ return false;
+
+ if (!ShiftOp(KnownVal.One, MaxShift).isZero())
+ return true;
+
+ // If all of the bits shifted out are known to be zero, and Val is known
+ // non-zero then at least one non-zero bit must remain.
+ if (InvShiftOp(KnownVal.Zero, NumBits - MaxShift)
+ .eq(InvShiftOp(APInt::getAllOnes(NumBits), NumBits - MaxShift)) &&
+ isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q))
+ return true;
+
+ return false;
+}
+
/// Return true if the given value is known to be non-zero when defined. For
/// vectors, return true if every demanded element is known to be non-zero when
/// defined. For pointers, if the context instruction and dominator tree are
@@ -2682,16 +2733,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
if (Known.One[0])
return true;
- if (!Known.isUnknown()) {
- KnownBits KnownCnt =
- computeKnownBits(I->getOperand(1), DemandedElts, Depth, Q);
-
- if (KnownCnt.getMaxValue().ult(Known.getBitWidth()) &&
- !Known.One.shl(KnownCnt.getMaxValue()).isZero())
- return true;
- }
-
- break;
+ return isNonZeroShift(I, DemandedElts, Depth, Q, Known);
}
case Instruction::LShr:
case Instruction::AShr: {
@@ -2707,19 +2749,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
if (Known.isNegative())
return true;
- // If the shifter operand is a constant, and all of the bits shifted
- // out are known to be zero, and X is known non-zero then at least one
- // non-zero bit must remain.
- if (ConstantInt *Shift = dyn_cast<ConstantInt>(I->getOperand(1))) {
- auto ShiftVal = Shift->getLimitedValue(BitWidth - 1);
- // Is there a known one in the portion not shifted out?
- if (Known.countMaxLeadingZeros() < BitWidth - ShiftVal)
- return true;
- // Are all the bits to be shifted out known zero?
- if (Known.countMinTrailingZeros() >= ShiftVal)
- return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
- }
- break;
+ return isNonZeroShift(I, DemandedElts, Depth, Q, Known);
}
case Instruction::UDiv:
case Instruction::SDiv: