[llvm] [LAA] Avoid duplicate runtime-check group members (PR #226829)

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 06:49:42 PDT 2026


https://github.com/davidbolvansky updated https://github.com/llvm/llvm-project/pull/226829

>From 47a562eacff7414d976d463a2288a65aac232288 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sun, 27 Sep 2026 21:16:48 +0200
Subject: [PATCH 1/3] [LAA] Avoid duplicate runtime-check group members

---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      | 28 ++++++++++---------
 .../bounded-access-pattern.ll                 |  2 --
 .../LoopAccessAnalysis/forked-pointers.ll     |  4 ---
 .../invariant-dep-same-ptr.ll                 |  7 -----
 .../non-affine-monotonic-bounds.ll            |  8 ------
 .../LoopAccessAnalysis/pointer-phis.ll        |  9 ------
 ...ter-dependence-analysis-forked-pointers.ll |  2 --
 .../Inputs/loop-access-analysis.ll.expected   |  3 --
 .../Inputs/loop-distribute.ll.expected        |  4 ---
 9 files changed, 15 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 804ffe5bb2edd..10da96c504851 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -736,13 +736,13 @@ void RuntimePointerChecking::groupChecks(
 
   unsigned TotalComparisons = 0;
 
-  DenseMap<Value *, SmallVector<unsigned>> PositionMap;
-  for (unsigned Index = 0; Index < Pointers.size(); ++Index)
-    PositionMap[Pointers[Index].PointerValue].push_back(Index);
+  DenseMap<Value *, SmallVector<unsigned>> PointerToIndices;
+  for (unsigned I = 0; I < Pointers.size(); ++I)
+    PointerToIndices[Pointers[I].PointerValue].push_back(I);
 
   // We need to keep track of what pointers we've already seen so we
   // don't process them twice.
-  SmallSet<unsigned, 2> Seen;
+  SmallSet<unsigned, 2> SeenIndices;
 
   // Go through all equivalence classes, get the "pointer check groups"
   // and add them to the overall solution. We use the order in which accesses
@@ -750,7 +750,7 @@ void RuntimePointerChecking::groupChecks(
   for (unsigned I = 0; I < Pointers.size(); ++I) {
     // We've seen this pointer before, and therefore already processed
     // its equivalence class.
-    if (Seen.contains(I))
+    if (SeenIndices.contains(I))
       continue;
 
     MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue,
@@ -764,6 +764,7 @@ void RuntimePointerChecking::groupChecks(
     }
 
     SmallVector<RuntimeCheckingPtrGroup, 2> Groups;
+    SmallPtrSet<Value *, 2> SeenPointers;
 
     // Because DepCands is constructed by visiting accesses in the order in
     // which they appear in alias sets (which is deterministic) and the
@@ -771,15 +772,16 @@ void RuntimePointerChecking::groupChecks(
     // the order in which unions and insertions are performed on the
     // equivalence class, the iteration order is deterministic.
     for (auto M : DepCands.members(Access)) {
-      auto PointerI = PositionMap.find(M.getPointer());
-      // If we can't find the pointer in PositionMap that means we can't
-      // generate a memcheck for it.
-      if (PointerI == PositionMap.end())
+      Value *Pointer = M.getPointer();
+      // A read-modify-write access appears in DepCands in both access modes.
+      if (!SeenPointers.insert(Pointer).second)
         continue;
-      for (unsigned Pointer : PointerI->second) {
+
+      for (unsigned PointerIndex : PointerToIndices.lookup(Pointer)) {
         bool Merged = false;
+
         // Mark this pointer as seen.
-        Seen.insert(Pointer);
+        SeenIndices.insert(PointerIndex);
 
         // Go through all the existing sets and see if we can find one
         // which can include this pointer.
@@ -793,7 +795,7 @@ void RuntimePointerChecking::groupChecks(
 
           TotalComparisons++;
 
-          if (Group.addPointer(Pointer, *this)) {
+          if (Group.addPointer(PointerIndex, *this)) {
             Merged = true;
             break;
           }
@@ -803,7 +805,7 @@ void RuntimePointerChecking::groupChecks(
           // We couldn't add this pointer to any existing set or the threshold
           // for the number of comparisons has been reached. Create a new group
           // to hold the current pointer.
-          Groups.emplace_back(Pointer, *this);
+          Groups.emplace_back(PointerIndex, *this);
       }
     }
 
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/bounded-access-pattern.ll b/llvm/test/Analysis/LoopAccessAnalysis/bounded-access-pattern.ll
index 020d808f7b503..40d82b910a313 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/bounded-access-pattern.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/bounded-access-pattern.ll
@@ -936,7 +936,6 @@ define void @bounded_i24_store_size(ptr %a, ptr %b) {
 ; CHECK-NEXT:          %gep.b = getelementptr inbounds i24, ptr %b, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx
-; CHECK-NEXT:          %gep.a = getelementptr inbounds i24, ptr %a, i64 %idx
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %b High: (4095 + %b))
@@ -944,7 +943,6 @@ define void @bounded_i24_store_size(ptr %a, ptr %b) {
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %a High: (4095 + %a))
 ; CHECK-NEXT:            Member: {%a,+,4}<nw><%loop>
-; CHECK-NEXT:            Member: {%a,+,4}<nw><%loop>
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
 ; CHECK-NEXT:      SCEV assumptions:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
index fa72ae910cbbb..28e0871d123c5 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
@@ -13,20 +13,17 @@ define void @forked_ptrs_simple(ptr nocapture readonly %Base1, ptr nocapture rea
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
 ; CHECK-NEXT:      Check 1:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
 ; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
-; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
 ; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%loop>
@@ -906,7 +903,6 @@ define void @forked_ptrs_two_select(ptr nocapture readonly %Base1, ptr nocapture
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
 ; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
-; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
 ; CHECK-NEXT:      Generated run-time checks are incomplete
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/invariant-dep-same-ptr.ll b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dep-same-ptr.ll
index 777a247dd90d3..d7db75aff7a9a 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/invariant-dep-same-ptr.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dep-same-ptr.ll
@@ -20,20 +20,17 @@ define void @conditional_store_load_same_invariant_via_phi(ptr %p0, ptr %p1, ptr
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:        ptr %p2
-; CHECK-NEXT:        ptr %p2
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep0 = getelementptr i32, ptr %p0, i64 %iv
 ; CHECK-NEXT:      Check 1:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:        ptr %p2
-; CHECK-NEXT:        ptr %p2
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:          %gep1 = getelementptr i32, ptr %phip, i64 %iv
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %p2 High: (4 + %p2))
 ; CHECK-NEXT:            Member: %p2
-; CHECK-NEXT:            Member: %p2
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %p0 High: ((4 * %n) + %p0))
 ; CHECK-NEXT:            Member: {%p0,+,4}<%loop>
@@ -160,19 +157,16 @@ define void @phi_with_loads_from_same_addr(ptr %p0, ptr %p1, ptr %x, i64 %n, i1
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
-; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep0 = getelementptr i32, ptr %p0, i64 %iv
 ; CHECK-NEXT:      Check 1:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
-; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:          %gep1 = getelementptr i32, ptr %phip, i64 %iv
 ; CHECK-NEXT:      Check 2:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
-; CHECK-NEXT:          %ld1 = load ptr, ptr %x, align 8
 ; CHECK-NEXT:        Against group GRP3:
 ; CHECK-NEXT:          %ld2 = load ptr, ptr %x, align 8
 ; CHECK-NEXT:      Check 3:
@@ -184,7 +178,6 @@ define void @phi_with_loads_from_same_addr(ptr %p0, ptr %p1, ptr %x, i64 %n, i1
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %ld1 High: (4 + %ld1))
 ; CHECK-NEXT:            Member: %ld1
-; CHECK-NEXT:            Member: %ld1
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %p0 High: ((4 * %n) + %p0))
 ; CHECK-NEXT:            Member: {%p0,+,4}<%loop>
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-affine-monotonic-bounds.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-affine-monotonic-bounds.ll
index e008eb011fadb..d721d1fe7a2db 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/non-affine-monotonic-bounds.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/non-affine-monotonic-bounds.ll
@@ -11,14 +11,12 @@ define void @bitset_udiv64_const_tc(ptr %words, ptr %out) {
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
-; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep.words = getelementptr inbounds i8, ptr %words, i64 %div
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %out High: (441 + %out))
 ; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
-; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %words High: (7 + %words))
 ; CHECK-NEXT:            Member: (({0,+,1}<nuw><nsw><%loop> /u 64) + %words)<nuw>
@@ -58,14 +56,12 @@ define void @bitset_udiv64_symbolic_tc(ptr %words, ptr %out, i64 %N) {
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
-; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep.words = getelementptr inbounds i8, ptr %words, i64 %div
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %out High: (%N + %out))
 ; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
-; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %words High: (1 + ((-1 + %N) /u 64) + %words))
 ; CHECK-NEXT:            Member: (({0,+,1}<nuw><nsw><%loop> /u 64) + %words)<nuw>
@@ -591,14 +587,12 @@ define void @bitset_udiv_neg_4_symbolic_tc(ptr %words, ptr %out, i64 %N) {
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
-; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep.words = getelementptr inbounds i8, ptr %words, i64 %div
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %out High: (%N + %out))
 ; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
-; CHECK-NEXT:            Member: {%out,+,1}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %words High: (1 + ((-1 + %N) /u -4) + %words))
 ; CHECK-NEXT:            Member: (({0,+,1}<nuw><nsw><%loop> /u -4) + %words)<nuw>
@@ -640,14 +634,12 @@ define void @bitset_udiv64_symbolic_start_and_tc(ptr %words, ptr %out, i64 %N, i
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
-; CHECK-NEXT:          %gep.out = getelementptr inbounds i8, ptr %out, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %gep.words = getelementptr inbounds i8, ptr %words, i64 %div
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: (%start + %out) High: (%N + %out))
 ; CHECK-NEXT:            Member: {(%start + %out),+,1}<nw><%loop>
-; CHECK-NEXT:            Member: {(%start + %out),+,1}<nw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: ((%start /u 64) + %words) High: (1 + ((-1 + %N) /u 64) + %words))
 ; CHECK-NEXT:            Member: (({%start,+,1}<nuw><nsw><%loop> /u 64) + %words)<nuw>
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll b/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll
index db6013a69bf6d..6bfaec8af22a8 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll
@@ -509,37 +509,28 @@ define void @phi_load_store_memdep_check(i1 %c, ptr %A, ptr %B, ptr %C) {
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:        ptr %A
-; CHECK-NEXT:        ptr %A
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:        ptr %C
-; CHECK-NEXT:        ptr %C
 ; CHECK-NEXT:      Check 1:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:        ptr %A
-; CHECK-NEXT:        ptr %A
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:        ptr %B
-; CHECK-NEXT:        ptr %B
 ; CHECK-NEXT:      Check 2:
 ; CHECK-NEXT:        Comparing group GRP1:
 ; CHECK-NEXT:        ptr %C
-; CHECK-NEXT:        ptr %C
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:        ptr %B
-; CHECK-NEXT:        ptr %B
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %A High: (2 + %A))
 ; CHECK-NEXT:            Member: %A
-; CHECK-NEXT:            Member: %A
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %C High: (2 + %C))
 ; CHECK-NEXT:            Member: %C
-; CHECK-NEXT:            Member: %C
 ; CHECK-NEXT:        Group GRP2:
 ; CHECK-NEXT:          (Low: %B High: (2 + %B))
 ; CHECK-NEXT:            Member: %B
-; CHECK-NEXT:            Member: %B
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were found in loop.
 ; CHECK-NEXT:      SCEV assumptions:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
index 19c52c7dfa88b..0e81226d5212e 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
@@ -163,7 +163,6 @@ define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_m
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %a High: ((4 * %n) + %a))
 ; CHECK-NEXT:            Member: {%a,+,4}<nuw><%loop>
-; CHECK-NEXT:            Member: {%a,+,4}<nuw><%loop>
 ; CHECK-NEXT:      Generated run-time checks are incomplete
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
@@ -212,7 +211,6 @@ define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_m
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %a High: ((4 * %n) + %a))
 ; CHECK-NEXT:            Member: {%a,+,4}<nuw><%loop>
-; CHECK-NEXT:            Member: {%a,+,4}<nuw><%loop>
 ; CHECK-NEXT:      Generated run-time checks are incomplete
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
diff --git a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll.expected b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll.expected
index 6d7b0655acdce..052c12488267a 100644
--- a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll.expected
@@ -10,20 +10,17 @@ define void @laa(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, p
 ; CHECK-NEXT:      Check 0:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
 ; CHECK-NEXT:        Against group GRP1:
 ; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
 ; CHECK-NEXT:      Check 1:
 ; CHECK-NEXT:        Comparing group GRP0:
 ; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
 ; CHECK-NEXT:        Against group GRP2:
 ; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
 ; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
 ; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
-; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
 ; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%loop>
diff --git a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
index e3e62c44f6ce4..1901747ed1b07 100644
--- a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
@@ -57,17 +57,13 @@ define void @ldist(i1 %cond, ptr %A, ptr %B, ptr %C) {
 ; CHECK-NEXT:  Check 0:
 ; CHECK-NEXT:    Comparing group GRP0:
 ; CHECK-NEXT:    ptr %A
-; CHECK-NEXT:    ptr %A
 ; CHECK-NEXT:    Against group GRP1:
 ; CHECK-NEXT:    ptr %C
-; CHECK-NEXT:    ptr %C
 ; CHECK-NEXT:  Check 1:
 ; CHECK-NEXT:    Comparing group GRP0:
 ; CHECK-NEXT:    ptr %A
-; CHECK-NEXT:    ptr %A
 ; CHECK-NEXT:    Against group GRP2:
 ; CHECK-NEXT:    ptr %B
-; CHECK-NEXT:    ptr %B
 ; CHECK-NEXT:  LDist: After removing unused Instrs:
 ; CHECK-NEXT:  LDist: Partition 0:
 ; CHECK-NEXT:  for.body.ldist1: ; preds = %if.end.ldist1, %for.body.ph.ldist1

>From 8866b5146399067d75ed61134cc40365bcb3c8e7 Mon Sep 17 00:00:00 2001
From: David Bolvansky <david.bolvansky at gmail.com>
Date: Tue, 29 Sep 2026 11:26:31 +0200
Subject: [PATCH 2/3] Address review comments

---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 10da96c504851..ed7e1f0729c1d 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -764,7 +764,6 @@ void RuntimePointerChecking::groupChecks(
     }
 
     SmallVector<RuntimeCheckingPtrGroup, 2> Groups;
-    SmallPtrSet<Value *, 2> SeenPointers;
 
     // Because DepCands is constructed by visiting accesses in the order in
     // which they appear in alias sets (which is deterministic) and the
@@ -773,15 +772,12 @@ void RuntimePointerChecking::groupChecks(
     // equivalence class, the iteration order is deterministic.
     for (auto M : DepCands.members(Access)) {
       Value *Pointer = M.getPointer();
-      // A read-modify-write access appears in DepCands in both access modes.
-      if (!SeenPointers.insert(Pointer).second)
-        continue;
-
       for (unsigned PointerIndex : PointerToIndices.lookup(Pointer)) {
-        bool Merged = false;
+        // A read-modify-write access appears in DepCands in both access modes.
+        if (!SeenIndices.insert(PointerIndex).second)
+          continue;
 
-        // Mark this pointer as seen.
-        SeenIndices.insert(PointerIndex);
+        bool Merged = false;
 
         // Go through all the existing sets and see if we can find one
         // which can include this pointer.

>From 62921fcb9d635ed81f0ec103c9ace23cece01106 Mon Sep 17 00:00:00 2001
From: David Bolvansky <david.bolvansky at gmail.com>
Date: Wed, 30 Sep 2026 15:49:09 +0200
Subject: [PATCH 3/3] Address review comments

---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 23c04fa6704c5..c668d86b2e552 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -736,13 +736,14 @@ void RuntimePointerChecking::groupChecks(
 
   unsigned TotalComparisons = 0;
 
-  DenseMap<Value *, SmallVector<unsigned>> PointerToIndices;
-  for (unsigned I = 0; I < Pointers.size(); ++I)
-    PointerToIndices[Pointers[I].PointerValue].push_back(I);
+  DenseMap<MemoryDepChecker::MemAccessInfo, SmallVector<unsigned>> PositionMap;
+  for (unsigned Index = 0; Index < Pointers.size(); ++Index)
+    PositionMap[{Pointers[Index].PointerValue, Pointers[Index].IsWritePtr}]
+        .push_back(Index);
 
   // We need to keep track of what pointers we've already seen so we
   // don't process them twice.
-  SmallSet<unsigned, 2> SeenIndices;
+  SmallSet<unsigned, 2> Seen;
 
   // Go through all equivalence classes, get the "pointer check groups"
   // and add them to the overall solution. We use the order in which accesses
@@ -750,7 +751,7 @@ void RuntimePointerChecking::groupChecks(
   for (unsigned I = 0; I < Pointers.size(); ++I) {
     // We've seen this pointer before, and therefore already processed
     // its equivalence class.
-    if (SeenIndices.contains(I))
+    if (Seen.contains(I))
       continue;
 
     MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue,
@@ -771,12 +772,8 @@ void RuntimePointerChecking::groupChecks(
     // the order in which unions and insertions are performed on the
     // equivalence class, the iteration order is deterministic.
     for (auto M : DepCands.members(Access)) {
-      Value *Pointer = M.getPointer();
-      for (unsigned PointerIndex : PointerToIndices.lookup(Pointer)) {
-        // A read-modify-write access appears in DepCands in both access modes.
-        if (!SeenIndices.insert(PointerIndex).second)
-          continue;
-
+      for (unsigned Pointer : PositionMap.lookup(M)) {
+        assert(Seen.insert(Pointer).second && "pointer already processed");
         bool Merged = false;
 
         // Go through all the existing sets and see if we can find one
@@ -791,7 +788,7 @@ void RuntimePointerChecking::groupChecks(
 
           TotalComparisons++;
 
-          if (Group.addPointer(PointerIndex, *this)) {
+          if (Group.addPointer(Pointer, *this)) {
             Merged = true;
             break;
           }
@@ -801,7 +798,7 @@ void RuntimePointerChecking::groupChecks(
           // We couldn't add this pointer to any existing set or the threshold
           // for the number of comparisons has been reached. Create a new group
           // to hold the current pointer.
-          Groups.emplace_back(PointerIndex, *this);
+          Groups.emplace_back(Pointer, *this);
       }
     }
 



More information about the llvm-commits mailing list