diff options
author | Paul Walker <paul.walker@arm.com> | 2025-09-19 12:57:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-19 12:57:13 +0100 |
commit | 7b8fd8f31bc6d65a59b6e09ebbeb77fdfb95360f (patch) | |
tree | 280e311dc968465597a387cf4716811125a5f725 /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 3c862b4ba39aa53a2dfcffb2fe7862e02f7bd746 (diff) | |
download | llvm-7b8fd8f31bc6d65a59b6e09ebbeb77fdfb95360f.zip llvm-7b8fd8f31bc6d65a59b6e09ebbeb77fdfb95360f.tar.gz llvm-7b8fd8f31bc6d65a59b6e09ebbeb77fdfb95360f.tar.bz2 |
[LLVM][SCEV] Look through common vscale multiplicand when simplifying compares. (#141798)
My usecase is simplifying the control flow generated by LoopVectorize
when vectorising loops whose tripcount is a function of the runtime
vector length. This can be problematic because:
* CSE is a pre-LoopVectorize transform and so it's common for an IR
function to include several calls to llvm.vscale(). (NOTE: Code
generation will typically remove the duplicates)
* Pre-LoopVectorize instcombines will rewrite some multiplies as shifts.
This leads to a mismatch between VL based maths of the scalar loop and
that created for the vector loop, which prevents some obvious
simplifications.
SCEV does not suffer these issues because it effectively does CSE during
construction and shifts are represented as multiplies.
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 079d7da..b08399b 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -10810,6 +10810,25 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS, if (Depth >= 3) return false; + const SCEV *NewLHS, *NewRHS; + if (match(LHS, m_scev_c_Mul(m_SCEV(NewLHS), m_SCEVVScale())) && + match(RHS, m_scev_c_Mul(m_SCEV(NewRHS), m_SCEVVScale()))) { + const SCEVMulExpr *LMul = cast<SCEVMulExpr>(LHS); + const SCEVMulExpr *RMul = cast<SCEVMulExpr>(RHS); + + // (X * vscale) pred (Y * vscale) ==> X pred Y + // when both multiples are NSW. + // (X * vscale) uicmp/eq/ne (Y * vscale) ==> X uicmp/eq/ne Y + // when both multiples are NUW. + if ((LMul->hasNoSignedWrap() && RMul->hasNoSignedWrap()) || + (LMul->hasNoUnsignedWrap() && RMul->hasNoUnsignedWrap() && + !ICmpInst::isSigned(Pred))) { + LHS = NewLHS; + RHS = NewRHS; + Changed = true; + } + } + // Canonicalize a constant to the right side. if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) { // Check for both operands constant. @@ -10984,7 +11003,7 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS, // Recursively simplify until we either hit a recursion limit or nothing // changes. if (Changed) - return SimplifyICmpOperands(Pred, LHS, RHS, Depth + 1); + (void)SimplifyICmpOperands(Pred, LHS, RHS, Depth + 1); return Changed; } |