@@ -949,6 +949,7 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) {
949
949
case Intrinsic::smax:
950
950
case Intrinsic::abs:
951
951
case Intrinsic::ctlz:
952
+ case Intrinsic::cttz:
952
953
case Intrinsic::ctpop:
953
954
return true ;
954
955
default :
@@ -987,6 +988,12 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID IntrinsicID,
987
988
assert (ZeroIsPoison->getBitWidth () == 1 && " Must be boolean" );
988
989
return Ops[0 ].ctlz (ZeroIsPoison->getBoolValue ());
989
990
}
991
+ case Intrinsic::cttz: {
992
+ const APInt *ZeroIsPoison = Ops[1 ].getSingleElement ();
993
+ assert (ZeroIsPoison && " Must be known (immarg)" );
994
+ assert (ZeroIsPoison->getBitWidth () == 1 && " Must be boolean" );
995
+ return Ops[0 ].cttz (ZeroIsPoison->getBoolValue ());
996
+ }
990
997
case Intrinsic::ctpop:
991
998
return Ops[0 ].ctpop ();
992
999
default :
@@ -1739,6 +1746,74 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) const {
1739
1746
APInt (getBitWidth (), getUnsignedMin ().countl_zero () + 1 ));
1740
1747
}
1741
1748
1749
+ static ConstantRange getUnsignedCountTrailingZerosRange (const APInt &Lower,
1750
+ const APInt &Upper) {
1751
+ assert (!ConstantRange (Lower, Upper).isWrappedSet () &&
1752
+ " Unexpected wrapped set." );
1753
+ assert (Lower != Upper && " Unexpected empty set." );
1754
+ unsigned BitWidth = Lower.getBitWidth ();
1755
+ if (Lower + 1 == Upper)
1756
+ return ConstantRange (APInt (BitWidth, Lower.countr_zero ()));
1757
+ if (Lower.isZero ())
1758
+ return ConstantRange (APInt::getZero (BitWidth),
1759
+ APInt (BitWidth, BitWidth + 1 ));
1760
+
1761
+ // Calculate longest common prefix.
1762
+ unsigned LCPLength = (Lower ^ (Upper - 1 )).countl_zero ();
1763
+ // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
1764
+ // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
1765
+ return ConstantRange (
1766
+ APInt::getZero (BitWidth),
1767
+ APInt (BitWidth,
1768
+ std::max (BitWidth - LCPLength - 1 , Lower.countr_zero ()) + 1 ));
1769
+ }
1770
+
1771
+ ConstantRange ConstantRange::cttz (bool ZeroIsPoison) const {
1772
+ if (isEmptySet ())
1773
+ return getEmpty ();
1774
+
1775
+ unsigned BitWidth = getBitWidth ();
1776
+ APInt Zero = APInt::getZero (BitWidth);
1777
+ if (ZeroIsPoison && contains (Zero)) {
1778
+ // ZeroIsPoison is set, and zero is contained. We discern three cases, in
1779
+ // which a zero can appear:
1780
+ // 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
1781
+ // 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
1782
+ // 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
1783
+
1784
+ if (Lower.isZero ()) {
1785
+ if (Upper == 1 ) {
1786
+ // We have in input interval of kind [0, 1). In this case we cannot
1787
+ // really help but return empty-set.
1788
+ return getEmpty ();
1789
+ }
1790
+
1791
+ // Compute the resulting range by excluding zero from Lower.
1792
+ return getUnsignedCountTrailingZerosRange (APInt (BitWidth, 1 ), Upper);
1793
+ } else if (Upper == 1 ) {
1794
+ // Compute the resulting range by excluding zero from Upper.
1795
+ return getUnsignedCountTrailingZerosRange (Lower, Zero);
1796
+ } else {
1797
+ ConstantRange CR1 = getUnsignedCountTrailingZerosRange (Lower, Zero);
1798
+ ConstantRange CR2 =
1799
+ getUnsignedCountTrailingZerosRange (APInt (BitWidth, 1 ), Upper);
1800
+ return CR1.unionWith (CR2);
1801
+ }
1802
+ }
1803
+
1804
+ if (isFullSet ())
1805
+ return getNonEmpty (Zero, APInt (BitWidth, BitWidth + 1 ));
1806
+ if (!isWrappedSet ())
1807
+ return getUnsignedCountTrailingZerosRange (Lower, Upper);
1808
+ // The range is wrapped. We decompose it into two ranges, [0, Upper) and
1809
+ // [Lower, 0).
1810
+ // Handle [Lower, 0)
1811
+ ConstantRange CR1 = getUnsignedCountTrailingZerosRange (Lower, Zero);
1812
+ // Handle [0, Upper)
1813
+ ConstantRange CR2 = getUnsignedCountTrailingZerosRange (Zero, Upper);
1814
+ return CR1.unionWith (CR2);
1815
+ }
1816
+
1742
1817
static ConstantRange getUnsignedPopCountRange (const APInt &Lower,
1743
1818
const APInt &Upper) {
1744
1819
assert (!ConstantRange (Lower, Upper).isWrappedSet () &&
0 commit comments