[llvm] [SCEV] Fix infinite recursion in getZeroExtendExpr via missing Depth propagation (PR #184958)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 6 06:30:53 PST 2026
https://github.com/dean-mccoppin updated https://github.com/llvm/llvm-project/pull/184958
>From 23d93f38d38e837be049f5e3994fc87eb091b321 Mon Sep 17 00:00:00 2001
From: hshira6 <hshira6 at wgu.edu>
Date: Fri, 6 Mar 2026 01:50:24 -0500
Subject: [PATCH 1/2] [SCEV] Fix infinite recursion in getZeroExtendExpr via
missing Depth propagation
getZeroExtendExprImpl called getAddExpr with a proper Depth argument, but
getAddExpr called back into getZeroExtendExpr without propagating Depth
(defaulting to 0), defeating the MaxCastDepth recursion guard and causing
a stack overflow when compiling loops with two interacting induction variables.
Fix by passing Depth through all getZeroExtendExpr call sites inside
getAddExpr and the missing sites inside getZeroExtendExprImpl itself
(2^K mul-trunc and umin/umax/umin_seq folding paths).
Fixes https://github.com/llvm/llvm-project/issues/184947
---
llvm/lib/Analysis/ScalarEvolution.cpp | 12 +++---
.../Transforms/LoopStrengthReduce/pr184947.ll | 43 +++++++++++++++++++
2 files changed, 49 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/Transforms/LoopStrengthReduce/pr184947.ll
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 083988f948069..732a32a7101e4 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1879,8 +1879,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
getTypeSizeInBits(SM->getOperand(1)->getType()) - C->logBase2();
Type *NewTruncTy = IntegerType::get(getContext(), NewTruncBits);
return getMulExpr(
- getZeroExtendExpr(SM->getOperand(0), Ty),
- getZeroExtendExpr(getTruncateExpr(TruncRHS, NewTruncTy), Ty),
+ getZeroExtendExpr(SM->getOperand(0), Ty, Depth + 1),
+ getZeroExtendExpr(getTruncateExpr(TruncRHS, NewTruncTy), Ty, Depth + 1),
SCEV::FlagNUW, Depth + 1);
}
}
@@ -1891,7 +1891,7 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
auto *MinMax = cast<SCEVMinMaxExpr>(Op);
SmallVector<const SCEV *, 4> Operands;
for (auto *Operand : MinMax->operands())
- Operands.push_back(getZeroExtendExpr(Operand, Ty));
+ Operands.push_back(getZeroExtendExpr(Operand, Ty, Depth + 1));
if (isa<SCEVUMinExpr>(MinMax))
return getUMinExpr(Operands);
return getUMaxExpr(Operands);
@@ -1902,7 +1902,7 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
assert(isa<SCEVSequentialUMinExpr>(MinMax) && "Not supported!");
SmallVector<const SCEV *, 4> Operands;
for (auto *Operand : MinMax->operands())
- Operands.push_back(getZeroExtendExpr(Operand, Ty));
+ Operands.push_back(getZeroExtendExpr(Operand, Ty, Depth + 1));
return getUMinExpr(Operands, /*Sequential*/ true);
}
@@ -2719,11 +2719,11 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
if (match(B, m_scev_ZExt(m_scev_Add(InnerAdd)))) {
const SCEV *NarrowA = getTruncateExpr(A, InnerAdd->getType());
if (NarrowA == getNegativeSCEV(InnerAdd->getOperand(0)) &&
- getZeroExtendExpr(NarrowA, B->getType()) == A &&
+ getZeroExtendExpr(NarrowA, B->getType(), Depth) == A &&
hasFlags(StrengthenNoWrapFlags(this, scAddExpr, {NarrowA, InnerAdd},
SCEV::FlagAnyWrap),
SCEV::FlagNUW)) {
- return getZeroExtendExpr(getAddExpr(NarrowA, InnerAdd), B->getType());
+ return getZeroExtendExpr(getAddExpr(NarrowA, InnerAdd, SCEV::FlagAnyWrap, Depth + 1), B->getType(), Depth);
}
}
}
diff --git a/llvm/test/Transforms/LoopStrengthReduce/pr184947.ll b/llvm/test/Transforms/LoopStrengthReduce/pr184947.ll
new file mode 100644
index 0000000000000..10d5bb8ac6289
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/pr184947.ll
@@ -0,0 +1,43 @@
+; RUN: opt -S -passes=loop-reduce < %s | FileCheck %s
+;
+; Make sure loop-reduce doesn't crash with infinite recursion in
+; getZeroExtendExpr via getAddExpr calling getZeroExtendExpr without
+; propagating the depth argument.
+; See https://github.com/llvm/llvm-project/issues/184947
+
+; Corresponds to:
+; a() {
+; int b = 0, c = 0;
+; for (;; a) {
+; c++;
+; if (c <= 14) continue;
+; b++;
+; if (b <= 45) continue;
+; return;
+; }
+; }
+
+; CHECK-LABEL: @a(
+define void @a() {
+entry:
+ br label %for.body
+
+for.body:
+ %b.0 = phi i32 [ 0, %entry ], [ %b.next, %for.latch ]
+ %c.0 = phi i32 [ 0, %entry ], [ %c.inc, %for.latch ]
+ %c.inc = add i32 %c.0, 1
+ %cmp.c = icmp sle i32 %c.inc, 14
+ br i1 %cmp.c, label %for.latch, label %b.inc.blk
+
+b.inc.blk:
+ %b.inc = add i32 %b.0, 1
+ %cmp.b = icmp sle i32 %b.inc, 45
+ br i1 %cmp.b, label %for.latch, label %return
+
+for.latch:
+ %b.next = phi i32 [ %b.0, %for.body ], [ %b.inc, %b.inc.blk ]
+ br label %for.body
+
+return:
+ ret void
+}
>From a000e3a85dbfe8eaa530788de7f6562f532bf76d Mon Sep 17 00:00:00 2001
From: hshira6 <hshira6 at wgu.edu>
Date: Fri, 6 Mar 2026 09:30:34 -0500
Subject: [PATCH 2/2] [SCEV] Use Depth+1 consistently in getAddExpr ->
getZeroExtendExpr calls
Per review feedback, use Depth+1 (not Depth) at the two getZeroExtendExpr
call sites in the A + zext(-A + B) folding path in getAddExpr, consistent
with every other recursive call site in this file.
---
llvm/lib/Analysis/ScalarEvolution.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 732a32a7101e4..71a1cb4301c73 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2719,11 +2719,11 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
if (match(B, m_scev_ZExt(m_scev_Add(InnerAdd)))) {
const SCEV *NarrowA = getTruncateExpr(A, InnerAdd->getType());
if (NarrowA == getNegativeSCEV(InnerAdd->getOperand(0)) &&
- getZeroExtendExpr(NarrowA, B->getType(), Depth) == A &&
+ getZeroExtendExpr(NarrowA, B->getType(), Depth + 1) == A &&
hasFlags(StrengthenNoWrapFlags(this, scAddExpr, {NarrowA, InnerAdd},
SCEV::FlagAnyWrap),
SCEV::FlagNUW)) {
- return getZeroExtendExpr(getAddExpr(NarrowA, InnerAdd, SCEV::FlagAnyWrap, Depth + 1), B->getType(), Depth);
+ return getZeroExtendExpr(getAddExpr(NarrowA, InnerAdd, SCEV::FlagAnyWrap, Depth + 1), B->getType(), Depth + 1);
}
}
}
More information about the llvm-commits
mailing list