@@ -556,29 +556,25 @@ mlir::intrange::inferOr(ArrayRef<ConstantIntRanges> argRanges) {
556
556
/* isSigned=*/ false );
557
557
}
558
558
559
+ // / Get bitmask of all bits which can change while iterating in
560
+ // / [bound.umin(), bound.umax()].
561
+ static APInt getVaryingBitsMask (const ConstantIntRanges &bound) {
562
+ APInt leftVal = bound.umin (), rightVal = bound.umax ();
563
+ unsigned bitwidth = leftVal.getBitWidth ();
564
+ unsigned differingBits = bitwidth - (leftVal ^ rightVal).countl_zero ();
565
+ return APInt::getLowBitsSet (bitwidth, differingBits);
566
+ }
567
+
559
568
ConstantIntRanges
560
569
mlir::intrange::inferXor (ArrayRef<ConstantIntRanges> argRanges) {
561
- // TODO: The code below doesn't work for bitwidths > i1.
562
- // For input ranges lhs=[2060639849, 2060639850], rhs=[2060639849, 2060639849]
563
- // widenBitwiseBounds will produce:
564
- // lhs:
565
- // 2060639848 01111010110100101101111001101000
566
- // 2060639851 01111010110100101101111001101011
567
- // rhs:
568
- // 2060639849 01111010110100101101111001101001
569
- // 2060639849 01111010110100101101111001101001
570
- // None of those combinations xor to 0, while intermediate values does.
571
- unsigned width = argRanges[0 ].umin ().getBitWidth ();
572
- if (width > 1 )
573
- return ConstantIntRanges::maxRange (width);
574
-
575
- auto [lhsZeros, lhsOnes] = widenBitwiseBounds (argRanges[0 ]);
576
- auto [rhsZeros, rhsOnes] = widenBitwiseBounds (argRanges[1 ]);
577
- auto xori = [](const APInt &a, const APInt &b) -> std::optional<APInt> {
578
- return a ^ b;
579
- };
580
- return minMaxBy (xori, {lhsZeros, lhsOnes}, {rhsZeros, rhsOnes},
581
- /* isSigned=*/ false );
570
+ // Construct mask of varying bits for both ranges, xor values and then replace
571
+ // masked bits with 0s and 1s to get min and max values respectively.
572
+ ConstantIntRanges lhs = argRanges[0 ], rhs = argRanges[1 ];
573
+ APInt mask = getVaryingBitsMask (lhs) | getVaryingBitsMask (rhs);
574
+ APInt res = lhs.umin () ^ rhs.umin ();
575
+ APInt min = res & ~mask;
576
+ APInt max = res | mask;
577
+ return ConstantIntRanges::fromUnsigned (min, max);
582
578
}
583
579
584
580
// ===----------------------------------------------------------------------===//
0 commit comments