[SCEV] Fix ScalarEvolution::getBackedgeTakenInfo when L not found (#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.
This commit is contained in:
Thurston Dang 2026-06-04 09:33:10 -07:00 committed by GitHub
parent a7a53bfbcf
commit b7e08b6467
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 83 additions and 1 deletions

View file

@ -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() {

View file

@ -0,0 +1,82 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=indvars -S | FileCheck %s
; Regression test for https://github.com/llvm/llvm-project/issues/195176:
; at the end of ScalarEvolution::getBackEdgeTakenInfo(), BackEdgeTakenCounts
; may no longer contain an entry for Loop *L.
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
}