mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-03 08:51:43 +00:00
[ValueTracking] Add some initial isKnownNonZero DemandedElts support (PR36319)
This commit is contained in:
parent
960e248f36
commit
7cc5fa5f26
@ -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);
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user