[llvm] [SCEV] Fold (C * A /u C) -> A, if A is a multiple of C and C a pow-of-2. (PR #156730)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 4 08:53:46 PDT 2025
================
@@ -3215,6 +3215,15 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
return getZeroExtendExpr(Res, Ops[1]->getType(), Depth + 1);
};
}
+
+ // Try to fold (C * D /u C) -> D, if C is a power-of-2 and D is a multiple
----------------
fhahn wrote:
> I'm going to put this in my own words to see if I follow. Given C is a power of two, both the divide and the multiply are shifts (right and left respectively). Since we know that D has more trailing zero bits than we shift out, we can shift the value back without changing it. Right?
Yep exactly!
> If so, doesn't the same logic work for sdiv (i.e. ashr)?
Yes, https://alive2.llvm.org/ce/z/ekSvPh contains the same proof for UDiv and SDiv. As for SCEV, I don't think there's anything to do for those though, as they either will be UDiv (if both operands are known-positive), or SCEVUnknown otherwise unless I missed something.
> If so, can't we generalize this for different power of two constants, with the result being a D /u C3 where C3 is the net shift? (Given we didn't discard any bits.)
Yes, that should also be possibe. We also don't need to limit ourselfs to constants, at least for the case where we multiply with the same values as we are dividing.
Would you like me to include either generalization here or OK as followup?
https://github.com/llvm/llvm-project/pull/156730
More information about the llvm-commits
mailing list