[llvm] [SCEV] Try to re-use pointer LCSSA phis when expanding SCEVs. (PR #147824)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 26 12:39:37 PDT 2025


================
@@ -1224,18 +1226,37 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) {
 }
 
 Value *SCEVExpander::tryToReuseLCSSAPhi(const SCEVAddRecExpr *S) {
+  Type *STy = S->getType();
   const Loop *L = S->getLoop();
   BasicBlock *EB = L->getExitBlock();
   if (!EB || !EB->getSinglePredecessor() ||
       !SE.DT.dominates(EB, Builder.GetInsertBlock()))
     return nullptr;
 
   for (auto &PN : EB->phis()) {
-    if (!SE.isSCEVable(PN.getType()) || PN.getType() != S->getType())
+    if (!SE.isSCEVable(PN.getType()))
       continue;
-    auto *ExitV = SE.getSCEV(&PN);
-    if (S == ExitV)
-      return &PN;
+    auto *ExitSCEV = SE.getSCEV(&PN);
+    Type *PhiTy = PN.getType();
+    if (STy->isIntegerTy() && PhiTy->isPointerTy())
+      ExitSCEV = SE.getPtrToIntExpr(ExitSCEV, STy);
+    else if (S->getType() != PN.getType())
+      continue;
+
+    // Check if we can re-use the existing PN, by adjusting it with an expanded
+    // offset, if the offset is simpler.
+    const SCEV *Diff = SE.getMinusSCEV(S, ExitSCEV);
+    const SCEV *Op = Diff;
+    match(Diff, m_scev_Mul(m_scev_AllOnes(), m_SCEV(Op)));
+    match(Op, m_scev_PtrToInt(m_SCEV(Op)));
+    if (!isa<SCEVConstant, SCEVUnknown>(Op))
+      continue;
+
+    Value *DiffV = expand(Diff);
+    Value *BaseV = &PN;
+    if (DiffV->getType()->isIntegerTy() && PhiTy->isPointerTy())
+      return Builder.CreatePtrAdd(BaseV, DiffV);
----------------
fhahn wrote:

Unfortuantely a common case where this helps is when the phi is a pointer but the SCEV is of integer type. This is generated by LV to compute and check the distance between 2 pointers (example is in https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/LoopVectorize/reuse-lcssa-phi-scev-expansion.ll#L122).

For now we will only generate this for integral pointers, so I'm not sure if there's a good way to write a test for it. I could add a speculative continue to skip non-integral pointers?

https://github.com/llvm/llvm-project/pull/147824


More information about the llvm-commits mailing list