[PATCH] D71011: [ConstantRange] Add `shlWithNoWrap()` method
Nikita Popov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 10 11:42:06 PST 2019
nikic added a comment.
Variant with nuw+nsw support:
if (NoWrapKind & OBO::NoUnsignedWrap) {
APInt Min = getUnsignedMin(), Max = getUnsignedMax();
unsigned MinLeadingZeros = Max.countLeadingZeros();
unsigned MaxLeadingZeros = Min.countLeadingZeros();
// If additionally the nsw flag is set, we can treat this the same way as
// nuw, but with one less bit available.
unsigned EffectiveBitWidth = BitWidth;
if (NoWrapKind & OBO::NoSignedWrap) {
--EffectiveBitWidth;
if (MinLeadingZeros != 0) --MinLeadingZeros;
if (MaxLeadingZeros != 0) --MaxLeadingZeros;
}
unsigned ShAmtMax = ShAmt.getUnsignedMax().getLimitedValue();
unsigned ShAmtMin = ShAmt.getUnsignedMin().getLimitedValue();
if (ShAmtMin > MaxLeadingZeros)
// All possible shifts will overflow.
return getEmpty();
APInt ResMin = Min.shl(ShAmtMin);
// We'll pick the larger of two possible upper bounds, initialize to zero.
APInt ResMax = APInt::getNullValue(BitWidth);
// Shift the maximum as far as possible without overflowing.
if (ShAmtMin <= MinLeadingZeros)
ResMax = Max.shl(std::min(ShAmtMax, MinLeadingZeros));
// Pick the largest number with all low bits sets that is both in the LHS
// range and can be shifted without overflowing.
if (MinLeadingZeros != MaxLeadingZeros && ShAmtMax >= MinLeadingZeros + 1) {
unsigned Shift = std::max(ShAmtMin, MinLeadingZeros + 1);
ResMax = APIntOps::umax(ResMax,
APInt::getLowBitsSet(BitWidth, EffectiveBitWidth - Shift).shl(Shift));
}
return getNonEmpty(ResMin, ResMax + 1);
}
The nsw case is ... uh ... left as an exercise for the reader.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D71011/new/
https://reviews.llvm.org/D71011
More information about the llvm-commits
mailing list