[llvm] 5d68dc1 - [Verifier] Iteratively traverse all indirect users.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 23 14:20:52 PST 2021


Author: Florian Hahn
Date: 2021-12-23T23:20:12+01:00
New Revision: 5d68dc184ef6cdb581bfa7bb353ee138c7690edd

URL: https://github.com/llvm/llvm-project/commit/5d68dc184ef6cdb581bfa7bb353ee138c7690edd
DIFF: https://github.com/llvm/llvm-project/commit/5d68dc184ef6cdb581bfa7bb353ee138c7690edd.diff

LOG: [Verifier] Iteratively traverse all indirect users.

The recursive implementation can run into stack overflows, e.g. like in PR52844.

The order the users are visited changes, but for the current use case
this only impacts the order error messages are emitted.

Added: 
    

Modified: 
    llvm/lib/IR/Verifier.cpp
    llvm/unittests/IR/VerifierTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 50605f50769d2..fb7c423e54e2c 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -602,17 +602,22 @@ void Verifier::visit(Instruction &I) {
   InstVisitor<Verifier>::visit(I);
 }
 
-// Helper to recursively iterate over indirect users. By
-// returning false, the callback can ask to stop recursing
-// further.
+// Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further.
 static void forEachUser(const Value *User,
                         SmallPtrSet<const Value *, 32> &Visited,
                         llvm::function_ref<bool(const Value *)> Callback) {
   if (!Visited.insert(User).second)
     return;
-  for (const Value *TheNextUser : User->materialized_users())
-    if (Callback(TheNextUser))
-      forEachUser(TheNextUser, Visited, Callback);
+
+  SmallVector<const Value *> WorkList;
+  append_range(WorkList, User->materialized_users());
+  while (!WorkList.empty()) {
+   const Value *Cur = WorkList.pop_back_val();
+    if (!Visited.insert(Cur).second)
+      continue;
+    if (Callback(Cur))
+      append_range(WorkList, Cur->materialized_users());
+  }
 }
 
 void Verifier::visitGlobalValue(const GlobalValue &GV) {

diff  --git a/llvm/unittests/IR/VerifierTest.cpp b/llvm/unittests/IR/VerifierTest.cpp
index 6031c808f5842..8747e171cfba3 100644
--- a/llvm/unittests/IR/VerifierTest.cpp
+++ b/llvm/unittests/IR/VerifierTest.cpp
@@ -136,17 +136,17 @@ TEST(VerifierTest, CrossModuleRef) {
   raw_string_ostream ErrorOS(Error);
   EXPECT_TRUE(verifyModule(M2, &ErrorOS));
   EXPECT_TRUE(StringRef(ErrorOS.str())
-                  .equals("Global is used by function in a 
diff erent module\n"
-                          "i32 ()* @foo2\n"
-                          "; ModuleID = 'M2'\n"
-                          "i32 ()* @foo3\n"
-                          "; ModuleID = 'M3'\n"
-                          "Global is referenced in a 
diff erent module!\n"
+                  .equals("Global is referenced in a 
diff erent module!\n"
                           "i32 ()* @foo2\n"
                           "; ModuleID = 'M2'\n"
                           "  %call = call i32 @foo2()\n"
                           "i32 ()* @foo1\n"
-                          "; ModuleID = 'M1'\n"));
+                          "; ModuleID = 'M1'\n"
+                          "Global is used by function in a 
diff erent module\n"
+                          "i32 ()* @foo2\n"
+                          "; ModuleID = 'M2'\n"
+                          "i32 ()* @foo3\n"
+                          "; ModuleID = 'M3'\n"));
 
   Error.clear();
   EXPECT_TRUE(verifyModule(M1, &ErrorOS));


        


More information about the llvm-commits mailing list