[llvm] 7f764fa - [ValueTracking] Add some initial isKnownNonZero DemandedElts support (PR36319)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 20 06:29:47 PDT 2020
Author: Simon Pilgrim
Date: 2020-03-20T13:29:00Z
New Revision: 7f764fa18f640bf4748ef53c39d55e52132bf95d
URL: https://github.com/llvm/llvm-project/commit/7f764fa18f640bf4748ef53c39d55e52132bf95d
DIFF: https://github.com/llvm/llvm-project/commit/7f764fa18f640bf4748ef53c39d55e52132bf95d.diff
LOG: [ValueTracking] Add some initial isKnownNonZero DemandedElts support (PR36319)
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/InstSimplify/compare.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ea6391d09ca9..b7af0d2b0ce1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -215,6 +215,9 @@ void llvm::computeKnownBits(const Value *V, KnownBits &Known,
Query(DL, AC, safeCxtI(V, CxtI), DT, UseInstrInfo, ORE));
}
+static KnownBits computeKnownBits(const Value *V, const APInt &DemandedElts,
+ unsigned Depth, const Query &Q);
+
static KnownBits computeKnownBits(const Value *V, unsigned Depth,
const Query &Q);
@@ -275,6 +278,9 @@ bool llvm::isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL,
V, OrZero, Depth, Query(DL, AC, safeCxtI(V, CxtI), DT, UseInstrInfo));
}
+static bool isKnownNonZero(const Value *V, const APInt &DemandedElts,
+ unsigned Depth, const Query &Q);
+
static bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q);
bool llvm::isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth,
@@ -1052,7 +1058,8 @@ static void computeKnownBitsFromShiftOperator(
// Early exit if we can't constrain any well-defined shift amount.
if (!(ShiftAmtKZ & (PowerOf2Ceil(BitWidth) - 1)) &&
!(ShiftAmtKO & (PowerOf2Ceil(BitWidth) - 1))) {
- ShifterOperandIsNonZero = isKnownNonZero(I->getOperand(1), Depth + 1, Q);
+ ShifterOperandIsNonZero =
+ isKnownNonZero(I->getOperand(1), DemandedElts, Depth + 1, Q);
if (!*ShifterOperandIsNonZero)
return;
}
@@ -1074,7 +1081,7 @@ static void computeKnownBitsFromShiftOperator(
if (ShiftAmt == 0) {
if (!ShifterOperandIsNonZero.hasValue())
ShifterOperandIsNonZero =
- isKnownNonZero(I->getOperand(1), Depth + 1, Q);
+ isKnownNonZero(I->getOperand(1), DemandedElts, Depth + 1, Q);
if (*ShifterOperandIsNonZero)
continue;
}
@@ -1811,6 +1818,15 @@ static void computeKnownBitsFromOperator(const Operator *I,
}
}
+/// Determine which bits of V are known to be either zero or one and return
+/// them.
+KnownBits computeKnownBits(const Value *V, const APInt &DemandedElts,
+ unsigned Depth, const Query &Q) {
+ KnownBits Known(getBitWidth(V->getType(), Q.DL));
+ computeKnownBits(V, DemandedElts, Known, Depth, Q);
+ return Known;
+}
+
/// Determine which bits of V are known to be either zero or one and return
/// them.
KnownBits computeKnownBits(const Value *V, unsigned Depth, const Query &Q) {
@@ -2223,12 +2239,13 @@ static bool rangeMetadataExcludesValue(const MDNode* Ranges, const APInt& Value)
}
/// Return true if the given value is known to be non-zero when defined. For
-/// vectors, return true if every element is known to be non-zero when
+/// 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
/// specified, perform context-sensitive analysis and return true if the
/// pointer couldn't possibly be null at the specified instruction.
/// Supports values with integer or pointer type and vectors of integers.
-bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
+bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
+ const Query &Q) {
if (auto *C = dyn_cast<Constant>(V)) {
if (C->isNullValue())
return false;
@@ -2249,6 +2266,8 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
// non-zero to determine that the whole vector is known non-zero.
if (auto *VecTy = dyn_cast<VectorType>(C->getType())) {
for (unsigned i = 0, e = VecTy->getNumElements(); i != e; ++i) {
+ if (!DemandedElts[i])
+ continue;
Constant *Elt = C->getAggregateElement(i);
if (!Elt || Elt->isNullValue())
return false;
@@ -2349,7 +2368,8 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
// X | Y != 0 if X != 0 or Y != 0.
Value *X = nullptr, *Y = nullptr;
if (match(V, m_Or(m_Value(X), m_Value(Y))))
- return isKnownNonZero(X, Depth, Q) || isKnownNonZero(Y, Depth, Q);
+ return isKnownNonZero(X, DemandedElts, Depth, Q) ||
+ isKnownNonZero(Y, DemandedElts, Depth, Q);
// ext X != 0 if X != 0.
if (isa<SExtInst>(V) || isa<ZExtInst>(V))
@@ -2364,7 +2384,7 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
return isKnownNonZero(X, Depth, Q);
KnownBits Known(BitWidth);
- computeKnownBits(X, Known, Depth, Q);
+ computeKnownBits(X, DemandedElts, Known, Depth, Q);
if (Known.One[0])
return true;
}
@@ -2376,7 +2396,7 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
if (BO->isExact())
return isKnownNonZero(X, Depth, Q);
- KnownBits Known = computeKnownBits(X, Depth, Q);
+ KnownBits Known = computeKnownBits(X, DemandedElts, Depth, Q);
if (Known.isNegative())
return true;
@@ -2390,22 +2410,23 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
return true;
// Are all the bits to be shifted out known zero?
if (Known.countMinTrailingZeros() >= ShiftVal)
- return isKnownNonZero(X, Depth, Q);
+ return isKnownNonZero(X, DemandedElts, Depth, Q);
}
}
// div exact can only produce a zero if the dividend is zero.
else if (match(V, m_Exact(m_IDiv(m_Value(X), m_Value())))) {
- return isKnownNonZero(X, Depth, Q);
+ return isKnownNonZero(X, DemandedElts, Depth, Q);
}
// X + Y.
else if (match(V, m_Add(m_Value(X), m_Value(Y)))) {
- KnownBits XKnown = computeKnownBits(X, Depth, Q);
- KnownBits YKnown = computeKnownBits(Y, Depth, Q);
+ KnownBits XKnown = computeKnownBits(X, DemandedElts, Depth, Q);
+ KnownBits YKnown = computeKnownBits(Y, DemandedElts, Depth, Q);
// If X and Y are both non-negative (as signed values) then their sum is not
// zero unless both X and Y are zero.
if (XKnown.isNonNegative() && YKnown.isNonNegative())
- if (isKnownNonZero(X, Depth, Q) || isKnownNonZero(Y, Depth, Q))
+ if (isKnownNonZero(X, DemandedElts, Depth, Q) ||
+ isKnownNonZero(Y, DemandedElts, Depth, Q))
return true;
// If X and Y are both negative (as signed values) then their sum is not
@@ -2436,13 +2457,14 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
// If X and Y are non-zero then so is X * Y as long as the multiplication
// does not overflow.
if ((Q.IIQ.hasNoSignedWrap(BO) || Q.IIQ.hasNoUnsignedWrap(BO)) &&
- isKnownNonZero(X, Depth, Q) && isKnownNonZero(Y, Depth, Q))
+ isKnownNonZero(X, DemandedElts, Depth, Q) &&
+ isKnownNonZero(Y, DemandedElts, Depth, Q))
return true;
}
// (C ? X : Y) != 0 if X != 0 and Y != 0.
else if (const SelectInst *SI = dyn_cast<SelectInst>(V)) {
- if (isKnownNonZero(SI->getTrueValue(), Depth, Q) &&
- isKnownNonZero(SI->getFalseValue(), Depth, Q))
+ if (isKnownNonZero(SI->getTrueValue(), DemandedElts, Depth, Q) &&
+ isKnownNonZero(SI->getFalseValue(), DemandedElts, Depth, Q))
return true;
}
// PHI
@@ -2472,12 +2494,31 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
if (AllNonZeroConstants)
return true;
}
+ // ExtractElement
+ else if (const auto *EEI = dyn_cast<ExtractElementInst>(V)) {
+ const Value *Vec = EEI->getVectorOperand();
+ const Value *Idx = EEI->getIndexOperand();
+ auto *CIdx = dyn_cast<ConstantInt>(Idx);
+ unsigned NumElts = Vec->getType()->getVectorNumElements();
+ APInt DemandedVecElts = APInt::getAllOnesValue(NumElts);
+ if (CIdx && CIdx->getValue().ult(NumElts))
+ DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue());
+ return isKnownNonZero(Vec, DemandedVecElts, Depth, Q);
+ }
KnownBits Known(BitWidth);
- computeKnownBits(V, Known, Depth, Q);
+ computeKnownBits(V, DemandedElts, Known, Depth, Q);
return Known.One != 0;
}
+bool isKnownNonZero(const Value* V, unsigned Depth, const Query& Q) {
+ Type *Ty = V->getType();
+ APInt DemandedElts = Ty->isVectorTy()
+ ? APInt::getAllOnesValue(Ty->getVectorNumElements())
+ : APInt(1, 1);
+ return isKnownNonZero(V, DemandedElts, Depth, Q);
+}
+
/// Return true if V2 == V1 + X, where X is known non-zero.
static bool isAddOfNonZero(const Value *V1, const Value *V2, const Query &Q) {
const BinaryOperator *BO = dyn_cast<BinaryOperator>(V1);
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index 494968c6e81c..86e1fef22f60 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -379,13 +379,7 @@ define i1 @add(i32 %x, i32 %y) {
define i1 @addv(<2 x i32> %x, <2 x i32> %y) {
; CHECK-LABEL: @addv(
-; CHECK-NEXT: [[L:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 1, i32 0>
-; CHECK-NEXT: [[Q:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 1, i32 0>
-; CHECK-NEXT: [[R:%.*]] = or <2 x i32> [[Q]], <i32 1, i32 0>
-; CHECK-NEXT: [[S:%.*]] = add <2 x i32> [[L]], [[R]]
-; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i32> [[S]], i32 0
-; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[E]], 0
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%l = lshr <2 x i32> %x, <i32 1, i32 0>
%q = lshr <2 x i32> %y, <i32 1, i32 0>
@@ -409,12 +403,7 @@ define i1 @add2(i8 %x, i8 %y) {
define i1 @add2v(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @add2v(
-; CHECK-NEXT: [[L:%.*]] = or <2 x i8> [[X:%.*]], <i8 0, i8 -128>
-; CHECK-NEXT: [[R:%.*]] = or <2 x i8> [[Y:%.*]], <i8 0, i8 -127>
-; CHECK-NEXT: [[S:%.*]] = add <2 x i8> [[L]], [[R]]
-; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[S]], i32 1
-; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[E]], 0
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%l = or <2 x i8> %x, <i8 0, i8 128>
%r = or <2 x i8> %y, <i8 0, i8 129>
More information about the llvm-commits
mailing list