[PATCH] D158875: [ADT] Fix IntEqClasses::join to return the leader in all cases.

Joshua Cranmer via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 11 13:50:42 PDT 2023


jcranmer-intel updated this revision to Diff 556481.
jcranmer-intel added a comment.

Add support for path compression to IntEqClasses::findLeader.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158875/new/

https://reviews.llvm.org/D158875

Files:
  llvm/include/llvm/ADT/IntEqClasses.h
  llvm/lib/Support/IntEqClasses.cpp
  llvm/unittests/ADT/IntEqClassesTest.cpp


Index: llvm/unittests/ADT/IntEqClassesTest.cpp
===================================================================
--- llvm/unittests/ADT/IntEqClassesTest.cpp
+++ llvm/unittests/ADT/IntEqClassesTest.cpp
@@ -103,4 +103,46 @@
   EXPECT_EQ(0u, ec.findLeader(9));
 }
 
+TEST(IntEqClasses, JoinReturnsLeader) {
+  IntEqClasses ec(10);
+  EXPECT_EQ(1u, ec.join(1, 2));
+  EXPECT_EQ(1u, ec.join(1, 3));
+  EXPECT_EQ(0u, ec.join(0, 1));
+  EXPECT_EQ(0u, ec.findLeader(1));
+  // At this point, EC[2] = EC[3] = 1, but EC[1] = 0. Be sure that trying to
+  // join EC[2] and EC[3] returns the correct leader, 0, and not their common
+  // node 1.
+  EXPECT_EQ(0u, ec.join(2, 3));
+  EXPECT_EQ(0u, ec.findLeader(2));
+}
+
+TEST(IntEqClasses, FindLeader) {
+  IntEqClasses ec(10);
+
+  // Join all the elements in such a way that most nodes will not point to the
+  // root immediately.
+  ec.join(8, 9);
+  ec.join(7, 8);
+  ec.join(6, 7);
+  ec.join(5, 6);
+  ec.join(4, 5);
+  ec.join(3, 4);
+  ec.join(2, 3);
+  ec.join(1, 2);
+  ec.join(0, 1);
+
+  // Ensure that any path compression that happens doesn't mess up the results
+  // of finding the leader.
+  EXPECT_EQ(0u, ec.findLeader(9));
+  EXPECT_EQ(0u, ec.findLeader(8));
+  EXPECT_EQ(0u, ec.findLeader(7));
+  EXPECT_EQ(0u, ec.findLeader(6));
+  EXPECT_EQ(0u, ec.findLeader(5));
+  EXPECT_EQ(0u, ec.findLeader(4));
+  EXPECT_EQ(0u, ec.findLeader(3));
+  EXPECT_EQ(0u, ec.findLeader(2));
+  EXPECT_EQ(0u, ec.findLeader(1));
+  EXPECT_EQ(0u, ec.findLeader(0));
+}
+
 } // end anonymous namespace
Index: llvm/lib/Support/IntEqClasses.cpp
===================================================================
--- llvm/lib/Support/IntEqClasses.cpp
+++ llvm/lib/Support/IntEqClasses.cpp
@@ -47,13 +47,19 @@
       eca = EC[a];
     }
 
+  // Make sure that eca is actually the leader of the equivalence class (this
+  // can happen if a and b were already in the same equivalence class).
+  eca = findLeader(eca);
   return eca;
 }
 
 unsigned IntEqClasses::findLeader(unsigned a) const {
   assert(NumClasses == 0 && "findLeader() called after compress().");
-  while (a != EC[a])
-    a = EC[a];
+  while (a != EC[a]) {
+    unsigned eca = EC[a];
+    EC[a] = EC[eca];
+    a = eca;
+  }
   return a;
 }
 
Index: llvm/include/llvm/ADT/IntEqClasses.h
===================================================================
--- llvm/include/llvm/ADT/IntEqClasses.h
+++ llvm/include/llvm/ADT/IntEqClasses.h
@@ -31,7 +31,7 @@
   /// itself.
   ///
   /// When compressed, EC[i] is the equivalence class of i.
-  SmallVector<unsigned, 8> EC;
+  mutable SmallVector<unsigned, 8> EC;
 
   /// NumClasses - The number of equivalence classes when compressed, or 0 when
   /// uncompressed.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D158875.556481.patch
Type: text/x-patch
Size: 2719 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230911/81267b5e/attachment.bin>


More information about the llvm-commits mailing list