[llvm] [ValueTracking] Extend known bits of `mul` with self and constant (PR #81892)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 16 10:12:53 PST 2024


================
@@ -373,11 +373,24 @@ static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
 
   bool isKnownNegative = false;
   bool isKnownNonNegative = false;
+  const APInt *C;
+  unsigned BitWidth = Known.getBitWidth();
+
   // If the multiplication is known not to overflow, compute the sign bit.
   if (NSW) {
     if (Op0 == Op1) {
       // The product of a number with itself is non-negative.
       isKnownNonNegative = true;
+    } else if (((match(Op0, m_Mul(m_Specific(Op1), m_APInt(C))) &&
+                 cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap()) ||
+                (match(Op0, m_Shl(m_Specific(Op1), m_APInt(C))) &&
+                 C->ult(BitWidth))) &&
+               !C->isZero() && !Known.isZero()) {
+      // The product of a number with itself and a constant depends on the sign
+      // of the constant.
+      KnownBits KnownC = KnownBits::makeConstant(*C);
+      isKnownNonNegative = KnownC.isNonNegative();
+      isKnownNegative = KnownC.isNegative();
----------------
goldsteinn wrote:

I would start with a proof similiar to  https://alive2.llvm.org/ce/z/K98HUL where instead of testing a specific constants and specifically checking the `sge`/`slt` cases, it implements the generalized logic you are trying to implement in C++.
>From the looks of things (although there may be a bug in my "proof"), the generalized concept is not correct, in which case you can constraint the `%C` argument using `llvm.assume(i1)`. Although, additional constants on `%C` only further nikic's argument that this is hacky, so i think there is a reasonable chance this change will need to be abandoned unless you can find/show some realworld examples where it makes an impact.

https://github.com/llvm/llvm-project/pull/81892


More information about the llvm-commits mailing list