[KnownBits] Add min/max shift amount handling to shl/lshr/ashr KnownBits helpers

Pulled out of the original D90479 patch - also includes the "impossible shift amount" filtering from computeKnownBitsFromShiftOperator.

Differential Revision: https://reviews.llvm.org/D90479
This commit is contained in:
Simon Pilgrim 2021-03-08 11:44:15 +00:00
parent f71cee136d
commit c2d18d7005
2 changed files with 76 additions and 1 deletions

View File

@ -187,6 +187,31 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS) {
MinTrailingZeros = std::min(MinTrailingZeros, BitWidth);
}
// If the maximum shift is in range, then find the common bits from all
// possible shifts.
APInt MaxShiftAmount = RHS.getMaxValue();
if (MaxShiftAmount.ult(BitWidth) && !LHS.isUnknown()) {
uint64_t ShiftAmtZeroMask = (~RHS.Zero).getZExtValue();
uint64_t ShiftAmtOneMask = RHS.One.getZExtValue();
assert(MinShiftAmount.ult(MaxShiftAmount) && "Illegal shift range");
Known.Zero.setAllBits();
Known.One.setAllBits();
for (uint64_t ShiftAmt = MinShiftAmount.getZExtValue(),
MaxShiftAmt = MaxShiftAmount.getZExtValue();
ShiftAmt <= MaxShiftAmt; ++ShiftAmt) {
// Skip if the shift amount is impossible.
if ((ShiftAmtZeroMask & ShiftAmt) != ShiftAmt ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
KnownBits SpecificShift;
SpecificShift.Zero = LHS.Zero << ShiftAmt;
SpecificShift.One = LHS.One << ShiftAmt;
Known = KnownBits::commonBits(Known, SpecificShift);
if (Known.isUnknown())
break;
}
}
Known.Zero.setLowBits(MinTrailingZeros);
return Known;
}
@ -215,6 +240,31 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS) {
MinLeadingZeros = std::min(MinLeadingZeros, BitWidth);
}
// If the maximum shift is in range, then find the common bits from all
// possible shifts.
APInt MaxShiftAmount = RHS.getMaxValue();
if (MaxShiftAmount.ult(BitWidth) && !LHS.isUnknown()) {
uint64_t ShiftAmtZeroMask = (~RHS.Zero).getZExtValue();
uint64_t ShiftAmtOneMask = RHS.One.getZExtValue();
assert(MinShiftAmount.ult(MaxShiftAmount) && "Illegal shift range");
Known.Zero.setAllBits();
Known.One.setAllBits();
for (uint64_t ShiftAmt = MinShiftAmount.getZExtValue(),
MaxShiftAmt = MaxShiftAmount.getZExtValue();
ShiftAmt <= MaxShiftAmt; ++ShiftAmt) {
// Skip if the shift amount is impossible.
if ((ShiftAmtZeroMask & ShiftAmt) != ShiftAmt ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
KnownBits SpecificShift = LHS;
SpecificShift.Zero.lshrInPlace(ShiftAmt);
SpecificShift.One.lshrInPlace(ShiftAmt);
Known = KnownBits::commonBits(Known, SpecificShift);
if (Known.isUnknown())
break;
}
}
Known.Zero.setHighBits(MinLeadingZeros);
return Known;
}
@ -248,6 +298,31 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS) {
}
}
// If the maximum shift is in range, then find the common bits from all
// possible shifts.
APInt MaxShiftAmount = RHS.getMaxValue();
if (MaxShiftAmount.ult(BitWidth) && !LHS.isUnknown()) {
uint64_t ShiftAmtZeroMask = (~RHS.Zero).getZExtValue();
uint64_t ShiftAmtOneMask = RHS.One.getZExtValue();
assert(MinShiftAmount.ult(MaxShiftAmount) && "Illegal shift range");
Known.Zero.setAllBits();
Known.One.setAllBits();
for (uint64_t ShiftAmt = MinShiftAmount.getZExtValue(),
MaxShiftAmt = MaxShiftAmount.getZExtValue();
ShiftAmt <= MaxShiftAmt; ++ShiftAmt) {
// Skip if the shift amount is impossible.
if ((ShiftAmtZeroMask & ShiftAmt) != ShiftAmt ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
KnownBits SpecificShift = LHS;
SpecificShift.Zero.ashrInPlace(ShiftAmt);
SpecificShift.One.ashrInPlace(ShiftAmt);
Known = KnownBits::commonBits(Known, SpecificShift);
if (Known.isUnknown())
break;
}
}
Known.Zero.setHighBits(MinLeadingZeros);
Known.One.setHighBits(MinLeadingOnes);
return Known;

View File

@ -799,7 +799,7 @@ define i1 @eq_shl_by_constant_produces_poison(i8 %x) {
define i1 @eq_shl_by_variable_produces_poison(i8 %x) {
; CHECK-LABEL: @eq_shl_by_variable_produces_poison(
; CHECK-NEXT: ret i1 false
; CHECK-NEXT: ret i1 poison
;
%clear_high_bit = and i8 %x, 127 ; 0x7f
%set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70