diff options
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index af85ce4..1e70228 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1351,6 +1351,8 @@ static void computeKnownBitsFromOperator(const Operator *I, isa<ScalableVectorType>(I->getType())) break; + unsigned NumElts = DemandedElts.getBitWidth(); + bool IsLE = Q.DL.isLittleEndian(); // Look through a cast from narrow vector elements to wider type. // Examples: v4i32 -> v2i64, v3i8 -> v24 unsigned SubBitWidth = SrcVecTy->getScalarSizeInBits(); @@ -1369,7 +1371,6 @@ static void computeKnownBitsFromOperator(const Operator *I, // // The known bits of each sub-element are then inserted into place // (dependent on endian) to form the full result of known bits. - unsigned NumElts = DemandedElts.getBitWidth(); unsigned SubScale = BitWidth / SubBitWidth; APInt SubDemandedElts = APInt::getZero(NumElts * SubScale); for (unsigned i = 0; i != NumElts; ++i) { @@ -1381,10 +1382,32 @@ static void computeKnownBitsFromOperator(const Operator *I, for (unsigned i = 0; i != SubScale; ++i) { computeKnownBits(I->getOperand(0), SubDemandedElts.shl(i), KnownSrc, Q, Depth + 1); - unsigned ShiftElt = Q.DL.isLittleEndian() ? i : SubScale - 1 - i; + unsigned ShiftElt = IsLE ? i : SubScale - 1 - i; Known.insertBits(KnownSrc, ShiftElt * SubBitWidth); } } + // Look through a cast from wider vector elements to narrow type. + // Examples: v2i64 -> v4i32 + if (SubBitWidth % BitWidth == 0) { + unsigned SubScale = SubBitWidth / BitWidth; + KnownBits KnownSrc(SubBitWidth); + APInt SubDemandedElts = + APIntOps::ScaleBitMask(DemandedElts, NumElts / SubScale); + computeKnownBits(I->getOperand(0), SubDemandedElts, KnownSrc, Q, + Depth + 1); + + Known.Zero.setAllBits(); + Known.One.setAllBits(); + for (unsigned i = 0; i != NumElts; ++i) { + if (DemandedElts[i]) { + unsigned Shifts = IsLE ? i : NumElts - 1 - i; + unsigned Offset = (Shifts % SubScale) * BitWidth; + Known = Known.intersectWith(KnownSrc.extractBits(BitWidth, Offset)); + if (Known.isUnknown()) + break; + } + } + } break; } case Instruction::SExt: { |