[PATCH] D141850: [SCEV] Preserve divisibility and min/max information in applyLoopGuards

Alon Kom via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 31 00:27:41 PST 2023


alonkom marked 14 inline comments as done.
alonkom added a comment.

In D141850#4072675 <https://reviews.llvm.org/D141850#4072675>, @caojoshua wrote:

>   After this patch, depending on the assume processing order applyLoopGuards could create the following SCEV:
>   max(min((8 * (TC / 8)) , 96), 8)
>
> This example looks wrong. I think min/max should be switched. Should be
>
>   min(max((8 * (TC / 8)), 96), 8)
>
> Please update description.
>
> ---
>
> In terms of overall approach, I'm not sure. Feels a bit hacky to have custom logic to check that an expressions is a min/max of mul/div. I'll let others chime in here.

I think the example is correct. 
Even before this patch:
TC > 0 is translated to max (TC, 1)
TC < 99 is translated to min (TC, 98)



================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15018
+                                        const SCEV *&LHS, const SCEV *&RHS) {
+      if (auto MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
+        SCTy = MinMax->getSCEVType();
----------------
mkazantsev wrote:
> caojoshua wrote:
> > SequentialMinMax SCEVs can be applied here as well.
> I'd prefer it to be a separate patch, if it's legal at all. Need to check carefully how poison flows in these formulae.
They are not created in this function, so I prefer only handling MinMax at this point.


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15018
+                                        const SCEV *&LHS, const SCEV *&RHS) {
+      if (auto MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
+        SCTy = MinMax->getSCEVType();
----------------
alonkom wrote:
> mkazantsev wrote:
> > caojoshua wrote:
> > > SequentialMinMax SCEVs can be applied here as well.
> > I'd prefer it to be a separate patch, if it's legal at all. Need to check carefully how poison flows in these formulae.
> They are not created in this function, so I prefer only handling MinMax at this point.
can you explain what isn't legal here?
just checking if this is a min/max of 2 operands, when the 2nd one is constant.


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15019
+      if (auto MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
+        SCTy = MinMax->getSCEVType();
+        LHS = MinMax->getOperand(0);
----------------
caojoshua wrote:
> unused var
it is used as an output of the function


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15033
+                                           const SCEV *Divisor) {
+      if (!isKnownNonNegative(Expr) || !isKnownPositive(Divisor))
+        return Expr;
----------------
mkazantsev wrote:
> If I'm reading this correctly, this is a guarantee of no-overflow for computations you are doing. Maybe add this comment explicitly?
I will only handle constants for now.


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15038
+        // return the SCEV: Expr + Divisor - Expr % Divisor
+        return getAddExpr(getMinusSCEV(Divisor, Rem), Expr);
+      }
----------------
mkazantsev wrote:
> caojoshua wrote:
> > Have not thought about it too deeply yet, but I'm concerned that we may need to take a look at when this is legal given Expr's NoWrapFlags. Same for the equivalent getMinusSCEV below
> This computation is inconsistent. If `Rem` is constant `0`, you'll return `Expr`. But if `Rem` is effectively zero, but not a constant (e.g. some complex expression which is always zero), you return `Expr + Divisor`. Bug?
I will only support constants for now


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15038
+        // return the SCEV: Expr + Divisor - Expr % Divisor
+        return getAddExpr(getMinusSCEV(Divisor, Rem), Expr);
+      }
----------------
alonkom wrote:
> mkazantsev wrote:
> > caojoshua wrote:
> > > Have not thought about it too deeply yet, but I'm concerned that we may need to take a look at when this is legal given Expr's NoWrapFlags. Same for the equivalent getMinusSCEV below
> > This computation is inconsistent. If `Rem` is constant `0`, you'll return `Expr`. But if `Rem` is effectively zero, but not a constant (e.g. some complex expression which is always zero), you return `Expr + Divisor`. Bug?
> I will only support constants for now
I will only support constants for now


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15060
+    // Divisor.
+    std::function<const SCEV *(const SCEV *, const SCEV *)>
+        ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr,
----------------
mkazantsev wrote:
> auto
can't use auto since there's a recursive call here


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15121
+    // divisibilty information expressed as (A /u B) * B, while B is a constant.
+    // Return wether the divisibilty info was found, and the divisor B in \p
+    // DividesBy.
----------------
caojoshua wrote:
> typo: wether
> 
> I'm not sure what `the divisor B in \p DividesBy` means.
> 
> I think this paragraph needs to be more clear. What does it mean to be composed on Min/Max SCEVs?
rephrased it a bit.


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15123
+    // DividesBy.
+    std::function<bool(const SCEV *, const SCEV *&)> HasDivisibiltyInfo =
+        [&](const SCEV *Expr, const SCEV *&DividesBy) {
----------------
mkazantsev wrote:
> auto
can't use auto since there's a recursive call here


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:15146
+    // Return true if Expr known to divide by \p DividesBy.
+    std::function<bool(const SCEV *, const SCEV *&)> IsKnownToDivideBy =
+        [&](const SCEV *Expr, const SCEV *DividesBy) {
----------------
mkazantsev wrote:
> auto
can't use auto, due to recursive call.


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

https://reviews.llvm.org/D141850



More information about the llvm-commits mailing list