[llvm] [InstCombine] Fold (X << Y) / (X << Z) -> (1 << Y) / (1 << Z) (PR #68863)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 12 02:16:42 PDT 2023


================
@@ -980,6 +980,28 @@ static Instruction *foldIDivShl(BinaryOperator &I,
       Ret = BinaryOperator::CreateSDiv(X, Y);
   }
 
+  // If X << Y and X << Z does not overflow, then:
+  // (X << Y) / (X << Z) -> (1 << Y) / (1 << Z)
+  // Ignore it when X == 1, to avoid infinite loop.
+  if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
+      match(Op1, m_Shl(m_Specific(X), m_Value(Z))) && !match(X, m_One()) &&
+      (Op0->hasOneUse() || Op1->hasOneUse())) {
+    auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
+    auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
+
+    Constant *One = ConstantInt::get(
+        X->getType(), APInt(X->getType()->getScalarSizeInBits(), 1));
+
+    if (!IsSigned && (Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap()))
+      Ret = BinaryOperator::CreateUDiv(
+          Builder.CreateShl(One, Y, "common.shl.lhs"),
+          Builder.CreateShl(One, Z, "common.shl.rhs"));
+    if (IsSigned && (Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap()))
----------------
dtcxzyw wrote:

```suggestion
    if (IsSigned && (Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() && Shl1->hasNoUnsignedWrap()))
```
See also: https://github.com/llvm/llvm-project/blob/2ceabf6bdc649f06a316f917a0f508fe10ea7faa/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp#L976-L980
Alive2: https://alive2.llvm.org/ce/z/sscBF7
Please add a negative test.


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


More information about the llvm-commits mailing list