[PATCH] D147108: [InstCombine] Add transforms for `(rem (shl Y, X), (shl Z, X))`

Sander de Smalen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 15 03:25:53 PDT 2023


sdesmalen added inline comments.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1762
 
 // Variety of transform for (urem/srem (mul/shl X, Y), (mul/shl X, Z))
 static Instruction *simplifyIRemMulShl(BinaryOperator &I,
----------------
Can you add this new case to the description here?


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1766
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *X = nullptr;
+  APInt const *MatchY, *MatchZ;
   APInt Y, Z;
----------------
I wonder if you can do something similar to `MatchShiftOrMul`, so that we use a similar mechanism

  if (MatchShiftOrMul(Op0, X, Y) &&
      MatchShiftOrMul(Op1, X, Z, /*MatchSpecific=*/true))
    ; // Do nothing
  else if (MatchShiftConstByVal(Op0, Y, X) &&
           MatchShiftConstByVal(Op1, Z, X, /*MatchSpecific=*/true))
    ShiftX = true;
  else
    return nullptr;

Just note that this requires changing the logic in `MatchShiftOrMul` which currently checks if `V` is nullptr to use `m_Specific` only when requested through an operand to the function. This way, you don't need to 'reset' `V` in between the two calls. I'm actually thinking that this explicit behaviour may be more desirable anyway, because then there is no implicit dependence between successive calls of this function.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1809
 
+  auto GetBinOpOut = [&](Value *RemSimplification) -> BinaryOperator * {
+    return ShiftX ? BinaryOperator::CreateShl(RemSimplification, X)
----------------
Can you add a comment describing the need for this function?


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1809
 
+  auto GetBinOpOut = [&](Value *RemSimplification) -> BinaryOperator * {
+    return ShiftX ? BinaryOperator::CreateShl(RemSimplification, X)
----------------
sdesmalen wrote:
> Can you add a comment describing the need for this function?
nit: is it worth renaming this to `CreateMulOrShift` ?


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1810
+  auto GetBinOpOut = [&](Value *RemSimplification) -> BinaryOperator * {
+    return ShiftX ? BinaryOperator::CreateShl(RemSimplification, X)
+                  : BinaryOperator::CreateMul(X, RemSimplification);
----------------
nit: rename to `ShiftByX` ?

This might be overkill because there are only two options, but for readability purposes I wondered if it was worth adding an enum which describes the two options, e.g. `enum RemMatchKind { NoMatch = 0, MulValByConst = 1, ConstShiftedByVal = 2 };` or something.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1818-1820
   // (rem (mul X, Y), (mul nuw/nsw X, Z))
   //      if (rem Y, Z) == Y
   //          -> (mul nuw/nsw X, Y)
----------------
A number of these comments are now out of date. You could add a comment which describes that:

  C << X <=> C * (1 << X)

so that the same logic here still applies when you conceptually substitute `(1 << X)` by `X`.
It just requires that the return value must be implemented differently (which is why there is the `GetBinOpOut` function)


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1822
   if (RemYZ == Y && BO1NoWrap) {
-    BinaryOperator *BO =
-        BinaryOperator::CreateMul(X, ConstantInt::get(I.getType(), Y));
+    BinaryOperator *BO = GetBinOpOut(ConstantInt::get(I.getType(), Y));
     // Copy any overflow flags from Op0.
----------------
Can you pass in the APInt instead, and do the `ConstantInt::get(...)` in `GetBinOptOut`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147108



More information about the llvm-commits mailing list