[PATCH] D148210: [InstCombine] Reassociate (C * X) * Y in foldICmpMulConstant

Jun Zhang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 20 00:48:25 PDT 2023


junaire marked 8 inline comments as done.
junaire added inline comments.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp:2043
 
+// Reassociate (C * X) * Y to (X * Y) * C to enable further
+// optimizations.
----------------
bcl5980 wrote:
> I'm not sure what are you going to do now. If you just want to reassociate C to outer mul, there is no extra condition. https://alive2.llvm.org/ce/z/v-f92Q
> The code should be simple:
> 
> ```
>   BinaryOperator *InnerMul;
>   Value *Y;
>   Constant *InnerC;
>   if (match(Mul, m_OneUse(m_c_Mul(m_BinOp(InnerMul), m_Value(Y)))) &&
>       match(InnerMul, m_Mul(m_Value(X), m_Constant(InnerC)))) {
>     Value *NewInner = Builder.CreateMul(X, Y);
>     Value *NewMul = Builder.CreateMul(NewInner, InnerC);
>     return new ICmpInst(Pred, NewMul, Mul->getOperand(1));
>   }```
> If you want to keep nsw/nuw flags, you can set the flag after create NewMul like:
> 
> ```
>     if (!InnerC->isZeroValue() && Mul->hasNoUnsignedWrap() &&
>         InnerMul->hasNoUnsignedWrap()) {
>       cast<BinaryOperator>(NewInner)->setHasNoUnsignedWrap();
>       cast<BinaryOperator>(NewMul)->setHasNoUnsignedWrap();
>     } else {
>       Constant *Zero = Constant::getNullValue(InnerC->getType());
>       Constant *InnerCSleZero =
>           ConstantExpr::getCompare(ICmpInst::ICMP_SLE, InnerC, Zero);
>       if (InnerCSleZero->isZeroValue() && Mul->hasNoSignedWrap() &&
>           InnerMul->hasNoSignedWrap()) {
>         cast<BinaryOperator>(NewInner)->setHasNoSignedWrap();
>         cast<BinaryOperator>(NewMul)->setHasNoSignedWrap();
>       }
>     }
> ```
> 
IIUC we want to reassociate `(X * C) * Y` to `(X * Y) * C` if they both has nsw/nuw flags so they can be folded by the existing logic in `foldICmpMulConstant`.
> I'm not sure what are you going to do now. If you just want to reassociate C to outer mul, there is no extra condition. https://alive2.llvm.org/ce/z/v-f92Q
> The code should be simple:
> 
> ```
>   BinaryOperator *InnerMul;
>   Value *Y;
>   Constant *InnerC;
>   if (match(Mul, m_OneUse(m_c_Mul(m_BinOp(InnerMul), m_Value(Y)))) &&
>       match(InnerMul, m_Mul(m_Value(X), m_Constant(InnerC)))) {
>     Value *NewInner = Builder.CreateMul(X, Y);
>     Value *NewMul = Builder.CreateMul(NewInner, InnerC);
>     return new ICmpInst(Pred, NewMul, Mul->getOperand(1));
>   }```

The issue is that if the inner mul's constant operand is a power of 2, it will be folded to an `shl`. like:
```
  %mul = shl nsw i8 %a, i8 1
  %mul2 = mul nsw i8 %b, %mul
```
Then the pattern match you proposed doesn't work anymore.
> If you want to keep nsw/nuw flags, you can set the flag after create NewMul like:
> 
> ```
>     if (!InnerC->isZeroValue() && Mul->hasNoUnsignedWrap() &&
>         InnerMul->hasNoUnsignedWrap()) {
>       cast<BinaryOperator>(NewInner)->setHasNoUnsignedWrap();
>       cast<BinaryOperator>(NewMul)->setHasNoUnsignedWrap();
>     } else {
>       Constant *Zero = Constant::getNullValue(InnerC->getType());
>       Constant *InnerCSleZero =
>           ConstantExpr::getCompare(ICmpInst::ICMP_SLE, InnerC, Zero);
>       if (InnerCSleZero->isZeroValue() && Mul->hasNoSignedWrap() &&
>           InnerMul->hasNoSignedWrap()) {
>         cast<BinaryOperator>(NewInner)->setHasNoSignedWrap();
>         cast<BinaryOperator>(NewMul)->setHasNoSignedWrap();
>       }
>     }
> ```
> 


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp:2052
+
+  auto Reassociate = [&](Value *X, Value *Y, Constant *CI) -> llvm::Value * {
+    if (Mul->hasNoSignedWrap() && Inner->hasNoSignedWrap() &&
----------------
bcl5980 wrote:
> Do we really need llvm:: here? There is already using namespace llvm in this file at line 30.
> Do we really need llvm:: here? There is already using namespace llvm in this file at line 30.

Thanks, fixed.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp:2071
+      if (Value *NewMul =
+              Reassociate(X, Y, ConstantInt::get(Mul->getType(), C->shl(*C))))
+        return NewMul;
----------------
goldstein.w.n wrote:
> 1 << C, not C << C?
> 1 << C, not C << C?

good catch, fixed. Thx.


================
Comment at: llvm/test/Transforms/InstCombine/icmp.ll:5345
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[TMP1]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
----------------
goldstein.w.n wrote:
> Add some tests for the `shl` case. Better yet split adding the `shl` logic to a follow up patch.
I thought I already added tests for `mul(shl(X, C), Y)`? I don't have a strong opinion about whether we should delay `shl` support, I think that's easy to do?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148210/new/

https://reviews.llvm.org/D148210



More information about the llvm-commits mailing list