[llvm] [SCEV] Fix ScalarEvolution::getBackedgeTakenInfo when L not found (PR #201502)

Thurston Dang via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 21:22:37 PDT 2026


https://github.com/thurstond created https://github.com/llvm/llvm-project/pull/201502

By the end of ScalarEvolution::getBackEdgeTakenInfo():
```
  ...
  BackedgeTakenInfo Result = computeBackedgeTakenCount(L);

  if (Result.hasAnyInfo()) {
    // Invalidate any expression using an addrec in this loop.
    ...
  }

  return BackedgeTakenCounts.find(L)->second = std::move(Result);
```
BackedgeTakenCounts may no longer contain an entry for L, resulting in a crash (https://github.com/llvm/llvm-project/issues/195176). This patch fixes the issue by inserting the entry if it does not exist (and otherwise keeping the same behavior).

This adds a regression test (crash on opt 19.1.0 onwards e.g., https://godbolt.org/z/Wq3n3rEqT), metarenamed from
https://github.com/dtcxzyw/llvm-autoreduce/issues/106, which in turn was derived from https://github.com/llvm/llvm-project/issues/195176.

>From ca91081f76e879f11bbde602f27d50b6af69464f Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 4 Jun 2026 04:11:04 +0000
Subject: [PATCH] [SCEV] Fix ScalarEvolution::getBackedgeTakenInfo when L not
 found

In ScalarEvolution::getBackEdgeTakenInfo():
  ...
  BackedgeTakenInfo Result = computeBackedgeTakenCount(L);

  if (Result.hasAnyInfo()) {
    // Invalidate any expression using an addrec in this loop.
    ...
  }

  return BackedgeTakenCounts.find(L)->second = std::move(Result);

BackedgeTakenCounts may no longer contain an entry for L, resulting in a
crash (https://github.com/llvm/llvm-project/issues/195176). This patch
fixes the issue by inserting the entry if it does not exist (and
otherwise keeping the same behavior).

This adds a regression test, metarenamed from
https://github.com/dtcxzyw/llvm-autoreduce/issues/106, which in turn was
derived from https://github.com/llvm/llvm-project/issues/195176.
---
 llvm/lib/Analysis/ScalarEvolution.cpp         |  2 +-
 .../Transforms/IndVarSimplify/issue195176.ll  | 78 +++++++++++++++++++
 2 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Transforms/IndVarSimplify/issue195176.ll

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ddf583082b2de..9e0058e4b724a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8746,7 +8746,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
   // recusive call to getBackedgeTakenInfo (on a different
   // loop), which would invalidate the iterator computed
   // earlier.
-  return BackedgeTakenCounts.find(L)->second = std::move(Result);
+  return BackedgeTakenCounts[L] = std::move(Result);
 }
 
 void ScalarEvolution::forgetAllLoops() {
diff --git a/llvm/test/Transforms/IndVarSimplify/issue195176.ll b/llvm/test/Transforms/IndVarSimplify/issue195176.ll
new file mode 100644
index 0000000000000..fc9ef42a1d7d5
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/issue195176.ll
@@ -0,0 +1,78 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=indvars -S | FileCheck %s
+
+define i32 @ham(ptr %arg) {
+; CHECK-LABEL: define i32 @ham(
+; CHECK-SAME: ptr [[ARG:%.*]]) {
+; CHECK-NEXT:  [[BBLOCK:.*:]]
+; CHECK-NEXT:    br label %[[BBLOCK2:.*]]
+; CHECK:       [[BBLOCK1:.*]]:
+; CHECK-NEXT:    unreachable
+; CHECK:       [[BBLOCK2_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[BBLOCK2]]
+; CHECK:       [[BBLOCK2]]:
+; CHECK-NEXT:    br i1 true, label %[[BBLOCK1]], label %[[BBLOCK3_PREHEADER:.*]]
+; CHECK:       [[BBLOCK3_PREHEADER]]:
+; CHECK-NEXT:    br label %[[BBLOCK3:.*]]
+; CHECK:       [[BBLOCK3]]:
+; CHECK-NEXT:    [[PHI4:%.*]] = phi i64 [ [[ADD14:%.*]], %[[BBLOCK13:.*]] ], [ 0, %[[BBLOCK3_PREHEADER]] ]
+; CHECK-NEXT:    [[PHI5:%.*]] = phi ptr [ null, %[[BBLOCK13]] ], [ [[ARG]], %[[BBLOCK3_PREHEADER]] ]
+; CHECK-NEXT:    [[PHI6:%.*]] = phi ptr [ [[GETELEMENTPTR:%.*]], %[[BBLOCK13]] ], [ null, %[[BBLOCK3_PREHEADER]] ]
+; CHECK-NEXT:    br label %[[BBLOCK11:.*]]
+; CHECK:       [[BBLOCK7:.*]]:
+; CHECK-NEXT:    unreachable
+; CHECK:       [[BBLOCK8:.*]]:
+; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[PHI6]] to i64
+; CHECK-NEXT:    [[ICMP9:%.*]] = icmp ugt ptr [[PHI5]], null
+; CHECK-NEXT:    [[XOR:%.*]] = xor i64 [[PTRTOINT]], -1
+; CHECK-NEXT:    [[ICMP10:%.*]] = icmp ult i64 [[PHI4]], [[XOR]]
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[ICMP9]], i1 [[ICMP10]], i1 false
+; CHECK-NEXT:    br i1 [[SELECT]], label %[[BBLOCK13]], label %[[BBLOCK7]]
+; CHECK:       [[BBLOCK11]]:
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i64 [[PHI4]], 1
+; CHECK-NEXT:    [[ICMP12:%.*]] = icmp eq i64 [[ADD]], 1
+; CHECK-NEXT:    br i1 [[ICMP12]], label %[[BBLOCK8]], label %[[BBLOCK11]]
+; CHECK:       [[BBLOCK13]]:
+; CHECK-NEXT:    [[ADD14]] = add nuw nsw i64 [[PHI4]], 1
+; CHECK-NEXT:    [[GETELEMENTPTR]] = getelementptr nusw i8, ptr [[PHI6]], i64 [[ADD14]]
+; CHECK-NEXT:    br i1 false, label %[[BBLOCK2_LOOPEXIT]], label %[[BBLOCK3]]
+;
+bblock:
+  br label %bblock2
+
+bblock1:                                              ; preds = %bblock2
+  unreachable
+
+bblock2:                                              ; preds = %bblock13, %bblock
+  %phi = phi i64 [ 0, %bblock ], [ 1, %bblock13 ]
+  %icmp = icmp ult i64 %phi, 1
+  br i1 %icmp, label %bblock1, label %bblock3
+
+bblock3:                                              ; preds = %bblock13, %bblock2
+  %phi4 = phi i64 [ %add14, %bblock13 ], [ 0, %bblock2 ]
+  %phi5 = phi ptr [ null, %bblock13 ], [ %arg, %bblock2 ]
+  %phi6 = phi ptr [ %getelementptr, %bblock13 ], [ null, %bblock2 ]
+  br label %bblock11
+
+bblock7:                                              ; preds = %bblock8
+  unreachable
+
+bblock8:                                              ; preds = %bblock11
+  %ptrtoint = ptrtoint ptr %phi6 to i64
+  %icmp9 = icmp ugt ptr %phi5, null
+  %xor = xor i64 %ptrtoint, -1
+  %icmp10 = icmp ult i64 %phi4, %xor
+  %select = select i1 %icmp9, i1 %icmp10, i1 false
+  br i1 %select, label %bblock13, label %bblock7
+
+bblock11:                                             ; preds = %bblock11, %bblock3
+  %add = add i64 %phi4, 1
+  %icmp12 = icmp eq i64 %add, 1
+  br i1 %icmp12, label %bblock8, label %bblock11
+
+bblock13:                                             ; preds = %bblock8
+  %add14 = add i64 %phi4, 1
+  %getelementptr = getelementptr nusw i8, ptr %phi6, i64 %add14
+  %icmp15 = icmp eq i64 %phi4, 1
+  br i1 %icmp15, label %bblock2, label %bblock3
+}



More information about the llvm-commits mailing list