@@ -1520,15 +1520,102 @@ ConstantRange ConstantRange::binaryNot() const {
1520
1520
return ConstantRange (APInt::getAllOnes (getBitWidth ())).sub (*this );
1521
1521
}
1522
1522
1523
+ // / Estimate the 'bit-masked AND' operation's lower bound.
1524
+ // /
1525
+ // / E.g., given two ranges as follows (single quotes are separators and
1526
+ // / have no meaning here),
1527
+ // /
1528
+ // / LHS = [10'001'010, ; LLo
1529
+ // / 10'100'000] ; LHi
1530
+ // / RHS = [10'111'010, ; RLo
1531
+ // / 10'111'100] ; RHi
1532
+ // /
1533
+ // / we know that the higher 2 bits of the result is always '10'; and note that
1534
+ // / there's at least one bit is 1 in LHS[3:6] (since the range is continuous),
1535
+ // / and all bits in RHS[3:6] are 1, so we know the lower bound of the result is
1536
+ // / 10'001'000.
1537
+ // /
1538
+ // / The algorithm is as follows,
1539
+ // / 1. we first calculate a mask to mask out the higher common bits by
1540
+ // / Mask = (LLo ^ LHi) | (LLo ^ LHi) | (LLo ^ RLo);
1541
+ // / Mask = set all non-leading-zero bits to 1 for Mask;
1542
+ // / 2. find the bit field with at least 1 in LHS (i.e., bit 3:6 in the example)
1543
+ // / after applying the mask, with
1544
+ // / StartBit = BitWidth - (LLo & Mask).clz() - 1;
1545
+ // / EndBit = BitWidth - (LHi & Mask).clz();
1546
+ // / 3. check if all bits in [StartBit:EndBit] in RHS are 1, and all bits of
1547
+ // / RLo and RHi in [StartBit:BitWidth] are same, and if so, the lower bound
1548
+ // / can be updated to
1549
+ // / LowerBound = LLo & Keep;
1550
+ // / where Keep is a mask to mask out trailing bits (the lower 3 bits in the
1551
+ // / example);
1552
+ // / 4. repeat the step 2 and 3 with LHS and RHS swapped, and update the lower
1553
+ // / bound with the smaller one.
1554
+ static APInt estimateBitMaskedAndLowerBound (const ConstantRange &LHS,
1555
+ const ConstantRange &RHS) {
1556
+ auto BitWidth = LHS.getBitWidth ();
1557
+ // If either is full set or unsigned wrapped, then the range must contain '0'
1558
+ // which leads the lower bound to 0.
1559
+ if ((LHS.isFullSet () || RHS.isFullSet ()) ||
1560
+ (LHS.isWrappedSet () || RHS.isWrappedSet ()))
1561
+ return APInt::getZero (BitWidth);
1562
+
1563
+ auto LLo = LHS.getLower ();
1564
+ auto LHi = LHS.getUpper () - 1 ;
1565
+ auto RLo = RHS.getLower ();
1566
+ auto RHi = RHS.getUpper () - 1 ;
1567
+
1568
+ // Calculate the mask that mask out the higher common bits.
1569
+ auto Mask = (LLo ^ LHi) | (RLo ^ RHi) | (LLo ^ RLo);
1570
+ unsigned LeadingZeros = Mask.countLeadingZeros ();
1571
+ Mask.setLowBits (BitWidth - LeadingZeros);
1572
+
1573
+ auto estimateBound =
1574
+ [BitWidth, &Mask](const APInt &ALo, const APInt &AHi, const APInt &BLo,
1575
+ const APInt &BHi) -> std::optional<APInt> {
1576
+ unsigned LeadingZeros = (ALo & Mask).countLeadingZeros ();
1577
+ if (LeadingZeros == BitWidth)
1578
+ return std::nullopt;
1579
+
1580
+ unsigned StartBit = BitWidth - LeadingZeros - 1 ;
1581
+
1582
+ if (BLo.extractBits (BitWidth - StartBit, StartBit) !=
1583
+ BHi.extractBits (BitWidth - StartBit, StartBit))
1584
+ return std::nullopt;
1585
+
1586
+ unsigned EndBit = BitWidth - (AHi & Mask).countLeadingZeros ();
1587
+ if (!(BLo.extractBits (EndBit - StartBit, StartBit) &
1588
+ BHi.extractBits (EndBit - StartBit, StartBit))
1589
+ .isAllOnes ())
1590
+ return std::nullopt;
1591
+
1592
+ APInt Keep (BitWidth, 0 );
1593
+ Keep.setBits (StartBit, BitWidth);
1594
+ return Keep & ALo;
1595
+ };
1596
+
1597
+ auto LowerBoundByLHS = estimateBound (LLo, LHi, RLo, RHi);
1598
+ auto LowerBoundByRHS = estimateBound (RLo, RHi, LLo, LHi);
1599
+
1600
+ if (LowerBoundByLHS && LowerBoundByRHS)
1601
+ return LowerBoundByLHS->ult (*LowerBoundByRHS) ? *LowerBoundByLHS
1602
+ : *LowerBoundByRHS;
1603
+ if (LowerBoundByLHS)
1604
+ return *LowerBoundByLHS;
1605
+ if (LowerBoundByRHS)
1606
+ return *LowerBoundByRHS;
1607
+ return APInt::getZero (BitWidth);
1608
+ }
1609
+
1523
1610
ConstantRange ConstantRange::binaryAnd (const ConstantRange &Other) const {
1524
1611
if (isEmptySet () || Other.isEmptySet ())
1525
1612
return getEmpty ();
1526
1613
1527
1614
ConstantRange KnownBitsRange =
1528
1615
fromKnownBits (toKnownBits () & Other.toKnownBits (), false );
1529
- ConstantRange UMinUMaxRange =
1530
- getNonEmpty (APInt::getZero ( getBitWidth ()),
1531
- APIntOps::umin (Other.getUnsignedMax (), getUnsignedMax ()) + 1 );
1616
+ auto LowerBound = estimateBitMaskedAndLowerBound (* this , Other);
1617
+ ConstantRange UMinUMaxRange = getNonEmpty (
1618
+ LowerBound, APIntOps::umin (Other.getUnsignedMax (), getUnsignedMax ()) + 1 );
1532
1619
return KnownBitsRange.intersectWith (UMinUMaxRange);
1533
1620
}
1534
1621
@@ -1538,10 +1625,17 @@ ConstantRange ConstantRange::binaryOr(const ConstantRange &Other) const {
1538
1625
1539
1626
ConstantRange KnownBitsRange =
1540
1627
fromKnownBits (toKnownBits () | Other.toKnownBits (), false );
1628
+
1629
+ // ~a & ~b >= x
1630
+ // <=> ~(~a & ~b) <= ~x
1631
+ // <=> a | b <= ~x
1632
+ // <=> a | b < ~x + 1
1633
+ // thus, UpperBound(a | b) == ~LowerBound(~a & ~b) + 1
1634
+ auto UpperBound =
1635
+ ~estimateBitMaskedAndLowerBound (binaryNot(), Other.binaryNot ()) + 1 ;
1541
1636
// Upper wrapped range.
1542
- ConstantRange UMaxUMinRange =
1543
- getNonEmpty (APIntOps::umax (getUnsignedMin (), Other.getUnsignedMin ()),
1544
- APInt::getZero (getBitWidth ()));
1637
+ ConstantRange UMaxUMinRange = getNonEmpty (
1638
+ APIntOps::umax (getUnsignedMin (), Other.getUnsignedMin ()), UpperBound);
1545
1639
return KnownBitsRange.intersectWith (UMaxUMinRange);
1546
1640
}
1547
1641
0 commit comments