@@ -1617,21 +1617,107 @@ ConstantRange::shl(const ConstantRange &Other) const {
16171617 return ConstantRange::getNonEmpty (std::move (Min), std::move (Max) + 1 );
16181618}
16191619
1620+ static ConstantRange computeShlNUW (const ConstantRange &LHS,
1621+ const ConstantRange &RHS) {
1622+ unsigned BitWidth = LHS.getBitWidth ();
1623+ bool Overflow;
1624+ APInt LHSMin = LHS.getUnsignedMin ();
1625+ unsigned RHSMin = RHS.getUnsignedMin ().getLimitedValue (BitWidth);
1626+ APInt MinShl = LHSMin.ushl_ov (RHSMin, Overflow);
1627+ if (Overflow)
1628+ return ConstantRange::getEmpty (BitWidth);
1629+ APInt LHSMax = LHS.getUnsignedMax ();
1630+ unsigned RHSMax = RHS.getUnsignedMax ().getLimitedValue (BitWidth);
1631+ APInt MaxShl = MinShl;
1632+ unsigned MaxShAmt = LHSMax.countLeadingZeros ();
1633+ if (RHSMin <= MaxShAmt)
1634+ MaxShl = LHSMax << std::min (RHSMax, MaxShAmt);
1635+ RHSMin = std::max (RHSMin, MaxShAmt + 1 );
1636+ RHSMax = std::min (RHSMax, LHSMin.countLeadingZeros ());
1637+ if (RHSMin <= RHSMax)
1638+ MaxShl = APIntOps::umax (MaxShl,
1639+ APInt::getHighBitsSet (BitWidth, BitWidth - RHSMin));
1640+ return ConstantRange::getNonEmpty (MinShl, MaxShl + 1 );
1641+ }
1642+
1643+ static ConstantRange computeShlNSWWithNNegLHS (const APInt &LHSMin,
1644+ const APInt &LHSMax,
1645+ unsigned RHSMin,
1646+ unsigned RHSMax) {
1647+ unsigned BitWidth = LHSMin.getBitWidth ();
1648+ bool Overflow;
1649+ APInt MinShl = LHSMin.sshl_ov (RHSMin, Overflow);
1650+ if (Overflow)
1651+ return ConstantRange::getEmpty (BitWidth);
1652+ APInt MaxShl = MinShl;
1653+ unsigned MaxShAmt = LHSMax.countLeadingZeros () - 1 ;
1654+ if (RHSMin <= MaxShAmt)
1655+ MaxShl = LHSMax << std::min (RHSMax, MaxShAmt);
1656+ RHSMin = std::max (RHSMin, MaxShAmt + 1 );
1657+ RHSMax = std::min (RHSMax, LHSMin.countLeadingZeros () - 1 );
1658+ if (RHSMin <= RHSMax)
1659+ MaxShl = APIntOps::umax (MaxShl,
1660+ APInt::getBitsSet (BitWidth, RHSMin, BitWidth - 1 ));
1661+ return ConstantRange::getNonEmpty (MinShl, MaxShl + 1 );
1662+ }
1663+
1664+ static ConstantRange computeShlNSWWithNegLHS (const APInt &LHSMin,
1665+ const APInt &LHSMax,
1666+ unsigned RHSMin, unsigned RHSMax) {
1667+ unsigned BitWidth = LHSMin.getBitWidth ();
1668+ bool Overflow;
1669+ APInt MaxShl = LHSMax.sshl_ov (RHSMin, Overflow);
1670+ if (Overflow)
1671+ return ConstantRange::getEmpty (BitWidth);
1672+ APInt MinShl = MaxShl;
1673+ unsigned MaxShAmt = LHSMin.countLeadingOnes () - 1 ;
1674+ if (RHSMin <= MaxShAmt)
1675+ MinShl = LHSMin.shl (std::min (RHSMax, MaxShAmt));
1676+ RHSMin = std::max (RHSMin, MaxShAmt + 1 );
1677+ RHSMax = std::min (RHSMax, LHSMax.countLeadingOnes () - 1 );
1678+ if (RHSMin <= RHSMax)
1679+ MinShl = APInt::getSignMask (BitWidth);
1680+ return ConstantRange::getNonEmpty (MinShl, MaxShl + 1 );
1681+ }
1682+
1683+ static ConstantRange computeShlNSW (const ConstantRange &LHS,
1684+ const ConstantRange &RHS) {
1685+ unsigned BitWidth = LHS.getBitWidth ();
1686+ unsigned RHSMin = RHS.getUnsignedMin ().getLimitedValue (BitWidth);
1687+ unsigned RHSMax = RHS.getUnsignedMax ().getLimitedValue (BitWidth);
1688+ APInt LHSMin = LHS.getSignedMin ();
1689+ APInt LHSMax = LHS.getSignedMax ();
1690+ if (LHSMin.isNonNegative ())
1691+ return computeShlNSWWithNNegLHS (LHSMin, LHSMax, RHSMin, RHSMax);
1692+ else if (LHSMax.isNegative ())
1693+ return computeShlNSWWithNegLHS (LHSMin, LHSMax, RHSMin, RHSMax);
1694+ return computeShlNSWWithNNegLHS (APInt::getZero (BitWidth), LHSMax, RHSMin,
1695+ RHSMax)
1696+ .unionWith (computeShlNSWWithNegLHS (LHSMin, APInt::getAllOnes (BitWidth),
1697+ RHSMin, RHSMax),
1698+ ConstantRange::Signed);
1699+ }
1700+
16201701ConstantRange ConstantRange::shlWithNoWrap (const ConstantRange &Other,
16211702 unsigned NoWrapKind,
16221703 PreferredRangeType RangeType) const {
16231704 if (isEmptySet () || Other.isEmptySet ())
16241705 return getEmpty ();
16251706
1626- ConstantRange Result = shl (Other);
1627-
1628- if (NoWrapKind & OverflowingBinaryOperator::NoSignedWrap)
1629- Result = Result.intersectWith (sshl_sat (Other), RangeType);
1630-
1631- if (NoWrapKind & OverflowingBinaryOperator::NoUnsignedWrap)
1632- Result = Result.intersectWith (ushl_sat (Other), RangeType);
1633-
1634- return Result;
1707+ switch (NoWrapKind) {
1708+ case 0 :
1709+ return shl (Other);
1710+ case OverflowingBinaryOperator::NoSignedWrap:
1711+ return computeShlNSW (*this , Other);
1712+ case OverflowingBinaryOperator::NoUnsignedWrap:
1713+ return computeShlNUW (*this , Other);
1714+ case OverflowingBinaryOperator::NoSignedWrap |
1715+ OverflowingBinaryOperator::NoUnsignedWrap:
1716+ return computeShlNSW (*this , Other)
1717+ .intersectWith (computeShlNUW (*this , Other), RangeType);
1718+ default :
1719+ llvm_unreachable (" Invalid NoWrapKind" );
1720+ }
16351721}
16361722
16371723ConstantRange
0 commit comments