Skip to content

Commit 72ff049

Browse files
committed
[ValueTracking] Consistently propagate DemandedElts is isKnownNonZero
1 parent 6ef970b commit 72ff049

File tree

2 files changed

+57
-39
lines changed

2 files changed

+57
-39
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -303,15 +303,21 @@ bool llvm::isKnownNegative(const Value *V, const SimplifyQuery &SQ,
303303
return computeKnownBits(V, Depth, SQ).isNegative();
304304
}
305305

306-
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
306+
static bool isKnownNonEqual(const Value *V1, const Value *V2,
307+
const APInt &DemandedElts, unsigned Depth,
307308
const SimplifyQuery &Q);
308309

309310
bool llvm::isKnownNonEqual(const Value *V1, const Value *V2,
310311
const DataLayout &DL, AssumptionCache *AC,
311312
const Instruction *CxtI, const DominatorTree *DT,
312313
bool UseInstrInfo) {
314+
assert(V1->getType() == V2->getType() &&
315+
"Testing equality of non-equal types!");
316+
auto *FVTy = dyn_cast<FixedVectorType>(V1->getType());
317+
APInt DemandedElts =
318+
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
313319
return ::isKnownNonEqual(
314-
V1, V2, 0,
320+
V1, V2, DemandedElts, 0,
315321
SimplifyQuery(DL, DT, AC, safeCxtI(V2, V1, CxtI), UseInstrInfo));
316322
}
317323

@@ -2654,7 +2660,7 @@ static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
26542660
if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Q, Depth))
26552661
return true;
26562662

2657-
return ::isKnownNonEqual(X, Y, Depth, Q);
2663+
return ::isKnownNonEqual(X, Y, DemandedElts, Depth, Q);
26582664
}
26592665

26602666
static bool isNonZeroMul(const APInt &DemandedElts, unsigned Depth,
@@ -2778,8 +2784,11 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
27782784
// This all implies the 2 i16 elements are non-zero.
27792785
Type *FromTy = I->getOperand(0)->getType();
27802786
if ((FromTy->isIntOrIntVectorTy() || FromTy->isPtrOrPtrVectorTy()) &&
2781-
(BitWidth % getBitWidth(FromTy->getScalarType(), Q.DL)) == 0)
2787+
(BitWidth % getBitWidth(FromTy->getScalarType(), Q.DL)) == 0) {
2788+
if (match(I, m_ElementWiseBitCast(m_Value())))
2789+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
27822790
return isKnownNonZero(I->getOperand(0), Q, Depth);
2791+
}
27832792
} break;
27842793
case Instruction::IntToPtr:
27852794
// Note that we have to take special care to avoid looking through
@@ -2788,21 +2797,21 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
27882797
if (!isa<ScalableVectorType>(I->getType()) &&
27892798
Q.DL.getTypeSizeInBits(I->getOperand(0)->getType()).getFixedValue() <=
27902799
Q.DL.getTypeSizeInBits(I->getType()).getFixedValue())
2791-
return isKnownNonZero(I->getOperand(0), Q, Depth);
2800+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
27922801
break;
27932802
case Instruction::PtrToInt:
27942803
// Similar to int2ptr above, we can look through ptr2int here if the cast
27952804
// is a no-op or an extend and not a truncate.
27962805
if (!isa<ScalableVectorType>(I->getType()) &&
27972806
Q.DL.getTypeSizeInBits(I->getOperand(0)->getType()).getFixedValue() <=
27982807
Q.DL.getTypeSizeInBits(I->getType()).getFixedValue())
2799-
return isKnownNonZero(I->getOperand(0), Q, Depth);
2808+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
28002809
break;
28012810
case Instruction::Trunc:
28022811
// nuw/nsw trunc preserves zero/non-zero status of input.
28032812
if (auto *TI = dyn_cast<TruncInst>(I))
28042813
if (TI->hasNoSignedWrap() || TI->hasNoUnsignedWrap())
2805-
return isKnownNonZero(TI->getOperand(0), Q, Depth);
2814+
return isKnownNonZero(TI->getOperand(0), DemandedElts, Q, Depth);
28062815
break;
28072816

28082817
case Instruction::Sub:
@@ -2823,13 +2832,13 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
28232832
case Instruction::SExt:
28242833
case Instruction::ZExt:
28252834
// ext X != 0 if X != 0.
2826-
return isKnownNonZero(I->getOperand(0), Q, Depth);
2835+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
28272836

28282837
case Instruction::Shl: {
28292838
// shl nsw/nuw can't remove any non-zero bits.
28302839
const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(I);
28312840
if (Q.IIQ.hasNoUnsignedWrap(BO) || Q.IIQ.hasNoSignedWrap(BO))
2832-
return isKnownNonZero(I->getOperand(0), Q, Depth);
2841+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
28332842

28342843
// shl X, Y != 0 if X is odd. Note that the value of the shift is undefined
28352844
// if the lowest bit is shifted off the end.
@@ -2845,7 +2854,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
28452854
// shr exact can only shift out zero bits.
28462855
const PossiblyExactOperator *BO = cast<PossiblyExactOperator>(I);
28472856
if (BO->isExact())
2848-
return isKnownNonZero(I->getOperand(0), Q, Depth);
2857+
return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
28492858

28502859
// shr X, Y != 0 if X is negative. Note that the value of the shift is not
28512860
// defined if the sign bit is shifted off the end.
@@ -3100,6 +3109,8 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
31003109
/*NSW=*/true, /* NUW=*/false);
31013110
// Vec reverse preserves zero/non-zero status from input vec.
31023111
case Intrinsic::vector_reverse:
3112+
return isKnownNonZero(II->getArgOperand(0), DemandedElts.reverseBits(),
3113+
Q, Depth);
31033114
// umin/smin/smax/smin/or of all non-zero elements is always non-zero.
31043115
case Intrinsic::vector_reduce_or:
31053116
case Intrinsic::vector_reduce_umax:
@@ -3424,7 +3435,8 @@ getInvertibleOperands(const Operator *Op1,
34243435
/// Only handle a small subset of binops where (binop V2, X) with non-zero X
34253436
/// implies V2 != V1.
34263437
static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2,
3427-
unsigned Depth, const SimplifyQuery &Q) {
3438+
const APInt &DemandedElts, unsigned Depth,
3439+
const SimplifyQuery &Q) {
34283440
const BinaryOperator *BO = dyn_cast<BinaryOperator>(V1);
34293441
if (!BO)
34303442
return false;
@@ -3444,39 +3456,43 @@ static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2,
34443456
Op = BO->getOperand(0);
34453457
else
34463458
return false;
3447-
return isKnownNonZero(Op, Q, Depth + 1);
3459+
return isKnownNonZero(Op, DemandedElts, Q, Depth + 1);
34483460
}
34493461
return false;
34503462
}
34513463

34523464
/// Return true if V2 == V1 * C, where V1 is known non-zero, C is not 0/1 and
34533465
/// the multiplication is nuw or nsw.
3454-
static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
3466+
static bool isNonEqualMul(const Value *V1, const Value *V2,
3467+
const APInt &DemandedElts, unsigned Depth,
34553468
const SimplifyQuery &Q) {
34563469
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(V2)) {
34573470
const APInt *C;
34583471
return match(OBO, m_Mul(m_Specific(V1), m_APInt(C))) &&
34593472
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
3460-
!C->isZero() && !C->isOne() && isKnownNonZero(V1, Q, Depth + 1);
3473+
!C->isZero() && !C->isOne() &&
3474+
isKnownNonZero(V1, DemandedElts, Q, Depth + 1);
34613475
}
34623476
return false;
34633477
}
34643478

34653479
/// Return true if V2 == V1 << C, where V1 is known non-zero, C is not 0 and
34663480
/// the shift is nuw or nsw.
3467-
static bool isNonEqualShl(const Value *V1, const Value *V2, unsigned Depth,
3481+
static bool isNonEqualShl(const Value *V1, const Value *V2,
3482+
const APInt &DemandedElts, unsigned Depth,
34683483
const SimplifyQuery &Q) {
34693484
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(V2)) {
34703485
const APInt *C;
34713486
return match(OBO, m_Shl(m_Specific(V1), m_APInt(C))) &&
34723487
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
3473-
!C->isZero() && isKnownNonZero(V1, Q, Depth + 1);
3488+
!C->isZero() && isKnownNonZero(V1, DemandedElts, Q, Depth + 1);
34743489
}
34753490
return false;
34763491
}
34773492

34783493
static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
3479-
unsigned Depth, const SimplifyQuery &Q) {
3494+
const APInt &DemandedElts, unsigned Depth,
3495+
const SimplifyQuery &Q) {
34803496
// Check two PHIs are in same block.
34813497
if (PN1->getParent() != PN2->getParent())
34823498
return false;
@@ -3498,14 +3514,15 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
34983514

34993515
SimplifyQuery RecQ = Q;
35003516
RecQ.CxtI = IncomBB->getTerminator();
3501-
if (!isKnownNonEqual(IV1, IV2, Depth + 1, RecQ))
3517+
if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
35023518
return false;
35033519
UsedFullRecursion = true;
35043520
}
35053521
return true;
35063522
}
35073523

3508-
static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
3524+
static bool isNonEqualSelect(const Value *V1, const Value *V2,
3525+
const APInt &DemandedElts, unsigned Depth,
35093526
const SimplifyQuery &Q) {
35103527
const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
35113528
if (!SI1)
@@ -3516,12 +3533,12 @@ static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
35163533
const Value *Cond2 = SI2->getCondition();
35173534
if (Cond1 == Cond2)
35183535
return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
3519-
Depth + 1, Q) &&
3536+
DemandedElts, Depth + 1, Q) &&
35203537
isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
3521-
Depth + 1, Q);
3538+
DemandedElts, Depth + 1, Q);
35223539
}
3523-
return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
3524-
isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
3540+
return isKnownNonEqual(SI1->getTrueValue(), V2, DemandedElts, Depth + 1, Q) &&
3541+
isKnownNonEqual(SI1->getFalseValue(), V2, DemandedElts, Depth + 1, Q);
35253542
}
35263543

35273544
// Check to see if A is both a GEP and is the incoming value for a PHI in the
@@ -3577,7 +3594,8 @@ static bool isNonEqualPointersWithRecursiveGEP(const Value *A, const Value *B,
35773594
}
35783595

35793596
/// Return true if it is known that V1 != V2.
3580-
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
3597+
static bool isKnownNonEqual(const Value *V1, const Value *V2,
3598+
const APInt &DemandedElts, unsigned Depth,
35813599
const SimplifyQuery &Q) {
35823600
if (V1 == V2)
35833601
return false;
@@ -3595,40 +3613,44 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
35953613
auto *O2 = dyn_cast<Operator>(V2);
35963614
if (O1 && O2 && O1->getOpcode() == O2->getOpcode()) {
35973615
if (auto Values = getInvertibleOperands(O1, O2))
3598-
return isKnownNonEqual(Values->first, Values->second, Depth + 1, Q);
3616+
return isKnownNonEqual(Values->first, Values->second, DemandedElts,
3617+
Depth + 1, Q);
35993618

36003619
if (const PHINode *PN1 = dyn_cast<PHINode>(V1)) {
36013620
const PHINode *PN2 = cast<PHINode>(V2);
36023621
// FIXME: This is missing a generalization to handle the case where one is
36033622
// a PHI and another one isn't.
3604-
if (isNonEqualPHIs(PN1, PN2, Depth, Q))
3623+
if (isNonEqualPHIs(PN1, PN2, DemandedElts, Depth, Q))
36053624
return true;
36063625
};
36073626
}
36083627

3609-
if (isModifyingBinopOfNonZero(V1, V2, Depth, Q) ||
3610-
isModifyingBinopOfNonZero(V2, V1, Depth, Q))
3628+
if (isModifyingBinopOfNonZero(V1, V2, DemandedElts, Depth, Q) ||
3629+
isModifyingBinopOfNonZero(V2, V1, DemandedElts, Depth, Q))
36113630
return true;
36123631

3613-
if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q))
3632+
if (isNonEqualMul(V1, V2, DemandedElts, Depth, Q) ||
3633+
isNonEqualMul(V2, V1, DemandedElts, Depth, Q))
36143634
return true;
36153635

3616-
if (isNonEqualShl(V1, V2, Depth, Q) || isNonEqualShl(V2, V1, Depth, Q))
3636+
if (isNonEqualShl(V1, V2, DemandedElts, Depth, Q) ||
3637+
isNonEqualShl(V2, V1, DemandedElts, Depth, Q))
36173638
return true;
36183639

36193640
if (V1->getType()->isIntOrIntVectorTy()) {
36203641
// Are any known bits in V1 contradictory to known bits in V2? If V1
36213642
// has a known zero where V2 has a known one, they must not be equal.
3622-
KnownBits Known1 = computeKnownBits(V1, Depth, Q);
3643+
KnownBits Known1 = computeKnownBits(V1, DemandedElts, Depth, Q);
36233644
if (!Known1.isUnknown()) {
3624-
KnownBits Known2 = computeKnownBits(V2, Depth, Q);
3645+
KnownBits Known2 = computeKnownBits(V2, DemandedElts, Depth, Q);
36253646
if (Known1.Zero.intersects(Known2.One) ||
36263647
Known2.Zero.intersects(Known1.One))
36273648
return true;
36283649
}
36293650
}
36303651

3631-
if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
3652+
if (isNonEqualSelect(V1, V2, DemandedElts, Depth, Q) ||
3653+
isNonEqualSelect(V2, V1, DemandedElts, Depth, Q))
36323654
return true;
36333655

36343656
if (isNonEqualPointersWithRecursiveGEP(V1, V2, Q) ||
@@ -3640,7 +3662,7 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
36403662
// Check PtrToInt type matches the pointer size.
36413663
if (match(V1, m_PtrToIntSameSize(Q.DL, m_Value(A))) &&
36423664
match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
3643-
return isKnownNonEqual(A, B, Depth + 1, Q);
3665+
return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
36443666

36453667
return false;
36463668
}

llvm/test/Analysis/ValueTracking/known-non-zero.ll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,11 +1522,7 @@ define <4 x i1> @vec_reverse_non_zero_fail(<4 x i8> %xx) {
15221522

15231523
define i1 @vec_reverse_non_zero_demanded(<4 x i8> %xx) {
15241524
; CHECK-LABEL: @vec_reverse_non_zero_demanded(
1525-
; CHECK-NEXT: [[X:%.*]] = add nuw <4 x i8> [[XX:%.*]], <i8 1, i8 0, i8 0, i8 0>
1526-
; CHECK-NEXT: [[REV:%.*]] = call <4 x i8> @llvm.vector.reverse.v4i8(<4 x i8> [[X]])
1527-
; CHECK-NEXT: [[ELE:%.*]] = extractelement <4 x i8> [[REV]], i64 3
1528-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ELE]], 0
1529-
; CHECK-NEXT: ret i1 [[R]]
1525+
; CHECK-NEXT: ret i1 false
15301526
;
15311527
%x = add nuw <4 x i8> %xx, <i8 1, i8 0, i8 0, i8 0>
15321528
%rev = call <4 x i8> @llvm.vector.reverse(<4 x i8> %x)

0 commit comments

Comments
 (0)