isVectorConstantLegal calls findFirstSet and findLastSet, but we don't
rely on their ability to return std::numeric_limits<T>::max() on input
0.
This patch replaces those calls with calls to llvm::countl_zero and
llvm::countr_zero.
Due to an off-by-one error in the original code, the value of Upper
could change at bit N, where N is the index of the highest set bit in
SplatBitsZ, but the difference doesn't matter at the end. Without
this patch, Upper could have bit N set. With this patch, Upper never
has bit N set. Either way, both calls to tryValue have this bit set
because the argument is ORed with SplatBitsZ.
// IMMEDIATE or a wraparound mask in VECTOR GENERATE MASK.
uint64_t SplatBitsZ = SplatBits.getZExtValue();
uint64_t SplatUndefZ = SplatUndef.getZExtValue();
- uint64_t Lower =
- (SplatUndefZ & ((uint64_t(1) << findFirstSet(SplatBitsZ)) - 1));
- uint64_t Upper =
- (SplatUndefZ & ~((uint64_t(1) << findLastSet(SplatBitsZ)) - 1));
+ unsigned LowerBits = llvm::countr_zero(SplatBitsZ);
+ unsigned UpperBits = llvm::countl_zero(SplatBitsZ);
+ uint64_t Lower = SplatUndefZ & maskTrailingOnes<uint64_t>(LowerBits);
+ uint64_t Upper = SplatUndefZ & maskLeadingOnes<uint64_t>(UpperBits);
if (tryValue(SplatBitsZ | Upper | Lower))
return true;