[Mlir-commits] [clang] [llvm] [mlir] pr/densemap nfc mlir (PR #199365)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat May 23 11:26:55 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

- **[llvm,clang] Don't assume non-erased DenseMap entries remain valid after erase. NFC**
- **[mlir] Don't assume non-erased DenseMap entries remain valid after erase. NFC**


---

Patch is 33.16 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/199365.diff


27 Files Affected:

- (modified) clang/lib/AST/ASTImporter.cpp (+9-4) 
- (modified) clang/lib/CodeGen/CoverageMappingGen.cpp (+3-7) 
- (modified) clang/lib/Interpreter/IncrementalParser.cpp (+6-1) 
- (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+5-1) 
- (modified) llvm/include/llvm/ADT/DenseMap.h (+27) 
- (modified) llvm/include/llvm/ADT/DenseSet.h (+10) 
- (modified) llvm/lib/Analysis/IRSimilarityIdentifier.cpp (+6-1) 
- (modified) llvm/lib/Analysis/LoopAccessAnalysis.cpp (+5-6) 
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+5-17) 
- (modified) llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp (+8-11) 
- (modified) llvm/lib/CodeGen/MachineCopyPropagation.cpp (+1-1) 
- (modified) llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp (+7-5) 
- (modified) llvm/lib/CodeGen/PeepholeOptimizer.cpp (+7-8) 
- (modified) llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp (+3-5) 
- (modified) llvm/lib/ExecutionEngine/Orc/Core.cpp (+8-13) 
- (modified) llvm/lib/IR/LegacyPassManager.cpp (+13-27) 
- (modified) llvm/lib/MC/MCObjectStreamer.cpp (+8-5) 
- (modified) llvm/lib/Support/CommandLine.cpp (+10-3) 
- (modified) llvm/lib/Transforms/IPO/FunctionImport.cpp (+2-6) 
- (modified) llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp (+2-1) 
- (modified) llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp (+5-11) 
- (modified) llvm/unittests/ADT/DenseMapTest.cpp (+45) 
- (modified) llvm/unittests/ADT/DenseSetTest.cpp (+16) 
- (modified) llvm/unittests/Support/JSONTest.cpp (+1-1) 
- (modified) mlir/include/mlir/Support/ThreadLocalCache.h (+7-9) 
- (modified) mlir/lib/Conversion/PDLToPDLInterp/RootOrdering.cpp (+20-20) 
- (modified) mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp (+9-2) 


``````````diff
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 7bab2d7dcddfa..f8527af2bfe6f 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9864,10 +9864,15 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
     // Failed to import.
 
     auto Pos = ImportedDecls.find(FromD);
-    if (Pos != ImportedDecls.end()) {
+    bool ToDWasCreated = Pos != ImportedDecls.end();
+    // Capture the mapped decl before erasing: the iterator is invalidated by
+    // the erase below under backward-shift deletion, but it is still needed
+    // further down to record the import error.
+    Decl *CreatedToD = ToDWasCreated ? Pos->second : nullptr;
+    if (ToDWasCreated) {
       // Import failed after the object was created.
       // Remove all references to it.
-      auto *ToD = Pos->second;
+      auto *ToD = CreatedToD;
       ImportedDecls.erase(Pos);
 
       // ImportedDecls and ImportedFromDecls are not symmetric.  It may happen
@@ -9903,8 +9908,8 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
                     [&ErrOut](const ASTImportError &E) { ErrOut = E; });
     setImportDeclError(FromD, ErrOut);
     // Set the error for the mapped to Decl, which is in the "to" context.
-    if (Pos != ImportedDecls.end())
-      SharedState->setImportDeclError(Pos->second, ErrOut);
+    if (ToDWasCreated)
+      SharedState->setImportDeclError(CreatedToD, ErrOut);
 
     // Set the error for all nodes which have been created before we
     // recognized the error.
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index eadb6e3bb25a8..c90afacbde293 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2260,13 +2260,9 @@ struct CounterCoverageMappingBuilder
     (void)FoundCount;
 
     // Tell CodeGenPGO not to instrument.
-    for (auto I = MCDCState.BranchByStmt.begin(),
-              E = MCDCState.BranchByStmt.end();
-         I != E;) {
-      auto II = I++;
-      if (II->second.DecisionStmt == Decision)
-        MCDCState.BranchByStmt.erase(II);
-    }
+    MCDCState.BranchByStmt.remove_if([&](const auto &Entry) {
+      return Entry.second.DecisionStmt == Decision;
+    });
     MCDCState.DecisionByStmt.erase(Decision);
   }
 
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index 16a954f3c15e7..f6d2779d64b2b 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -174,6 +174,9 @@ IncrementalParser::Parse(llvm::StringRef input) {
 
 void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
   if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
+    // Collect the keys to erase: erasing during iteration invalidates the map
+    // iterator under backward-shift deletion.
+    llvm::SmallVector<DeclarationName, 16> KeysToErase;
     for (auto &&[Key, List] : *Map) {
       DeclContextLookupResult R = List.getLookupResult();
       std::vector<NamedDecl *> NamedDeclsToRemove;
@@ -185,12 +188,14 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) {
           RemoveAll = false;
       }
       if (LLVM_LIKELY(RemoveAll)) {
-        Map->erase(Key);
+        KeysToErase.push_back(Key);
       } else {
         for (NamedDecl *D : NamedDeclsToRemove)
           List.remove(D);
       }
     }
+    for (DeclarationName Key : KeysToErase)
+      Map->erase(Key);
   }
 
   ExternCContextDecl *ECCD = S.getASTContext().getExternCContextDecl();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 449b32a215631..ae61b590a1f71 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -726,6 +726,10 @@ void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
   auto It = Completions.find(Record);
   if (It == Completions.end())
     return;
-  It->second(Record);
+  // Move out the callback and erase before invoking it: the callback can
+  // re-enter CompleteType and mutate Completions, which invalidates It under
+  // backward-shift deletion.
+  CompletionFunction Fn = std::move(It->second);
   Completions.erase(It);
+  Fn(Record);
 }
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index b8b548a31acbc..e13b64b3e6bf4 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -344,6 +344,33 @@ class DenseMapBase : public DebugEpochBase {
     incrementNumTombstones();
   }
 
+  /// Remove entries that match the given predicate. \p Pred is invoked
+  /// with a reference to each live bucket and must not access the map being
+  /// modified. This is the safe replacement for erase-while-iterating.
+  ///
+  /// Returns whether anything was removed. If so, all iterators and references
+  /// into the map are invalidated.
+  template <typename Predicate> bool remove_if(Predicate Pred) {
+    const KeyT EmptyKey = KeyInfoT::getEmptyKey();
+    const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
+    bool Removed = false;
+    for (BucketT &B : buckets()) {
+      if (KeyInfoT::isEqual(B.getFirst(), EmptyKey) ||
+          KeyInfoT::isEqual(B.getFirst(), TombstoneKey))
+        continue;
+      if (Pred(B)) {
+        B.getSecond().~ValueT();
+        B.getFirst() = TombstoneKey;
+        decrementNumEntries();
+        incrementNumTombstones();
+        Removed = true;
+      }
+    }
+    if (Removed)
+      incrementEpoch();
+    return Removed;
+  }
+
   ValueT &operator[](const KeyT &Key) {
     return lookupOrInsertIntoBucket(Key).first->second;
   }
diff --git a/llvm/include/llvm/ADT/DenseSet.h b/llvm/include/llvm/ADT/DenseSet.h
index eec800d07b6df..645d6d1568f35 100644
--- a/llvm/include/llvm/ADT/DenseSet.h
+++ b/llvm/include/llvm/ADT/DenseSet.h
@@ -99,6 +99,16 @@ class DenseSetImpl {
 
   bool erase(const ValueT &V) { return TheMap.erase(V); }
 
+  /// Remove all elements for which \p Pred returns true.  This is the safe
+  /// replacement for erase-while-iterating; see DenseMap::remove_if.  The
+  /// predicate must not access the set being modified.  Returns whether
+  /// anything was removed; if so, all iterators are invalidated.
+  template <typename Predicate> bool remove_if(Predicate Pred) {
+    return TheMap.remove_if([&](const typename MapTy::value_type &KV) {
+      return Pred(KV.getFirst());
+    });
+  }
+
   void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
 
 private:
diff --git a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp
index e5ebd1f908d55..11a824973de60 100644
--- a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp
+++ b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp
@@ -720,7 +720,12 @@ bool IRSimilarityCandidate::compareAssignmentMapping(
   if (!WasInserted && !ValueMappingIt->second.contains(InstValB))
     return false;
   else if (ValueMappingIt->second.size() != 1) {
-    for (unsigned OtherVal : ValueMappingIt->second) {
+    // Snapshot the set before iterating: when InstValA maps to itself the
+    // erase below removes InstValA from the very set being iterated, which
+    // invalidates the range iterator under backward-shift deletion.
+    SmallVector<unsigned> OtherVals(ValueMappingIt->second.begin(),
+                                    ValueMappingIt->second.end());
+    for (unsigned OtherVal : OtherVals) {
       if (OtherVal == InstValB)
         continue;
       auto OtherValIt = ValueNumberMappingA.find(OtherVal);
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 2b9efd22131c6..60e15b2a5bd82 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -3229,12 +3229,11 @@ void LoopAccessInfoManager::clear() {
   // analyzed loop or SCEVs that may have been modified or invalidated. At the
   // moment, that is loops requiring memory or SCEV runtime checks, as those cache
   // SCEVs, e.g. for pointer expressions.
-  for (const auto &[L, LAI] : LoopAccessInfoMap) {
-    if (LAI->getRuntimePointerChecking()->getChecks().empty() &&
-        LAI->getPSE().getPredicate().isAlwaysTrue())
-      continue;
-    LoopAccessInfoMap.erase(L);
-  }
+  LoopAccessInfoMap.remove_if([](const auto &Entry) {
+    const auto &LAI = Entry.second;
+    return !(LAI->getRuntimePointerChecking()->getChecks().empty() &&
+             LAI->getPSE().getPredicate().isAlwaysTrue());
+  });
 }
 
 bool LoopAccessInfoManager::invalidate(
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 657984aa0c3a8..855ab3bb5d621 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8763,8 +8763,8 @@ void ScalarEvolution::visitAndClearUsers(
     ValueExprMapType::iterator It =
         ValueExprMap.find_as(static_cast<Value *>(I));
     if (It != ValueExprMap.end()) {
-      eraseValueFromMap(It->first);
       ToForget.push_back(It->second);
+      eraseValueFromMap(It->first);
       if (PHINode *PN = dyn_cast<PHINode>(I))
         ConstantEvolutionLoopExitValue.erase(PN);
     }
@@ -8788,14 +8788,8 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
     forgetBackedgeTakenCounts(CurrL, /* Predicated */ true);
 
     // Drop information about predicated SCEV rewrites for this loop.
-    for (auto I = PredicatedSCEVRewrites.begin();
-         I != PredicatedSCEVRewrites.end();) {
-      std::pair<const SCEV *, const Loop *> Entry = I->first;
-      if (Entry.second == CurrL)
-        PredicatedSCEVRewrites.erase(I++);
-      else
-        ++I;
-    }
+    PredicatedSCEVRewrites.remove_if(
+        [&](const auto &Entry) { return Entry.first.second == CurrL; });
 
     auto LoopUsersItr = LoopUsers.find(CurrL);
     if (LoopUsersItr != LoopUsers.end())
@@ -14581,14 +14575,8 @@ void ScalarEvolution::forgetMemoizedResults(ArrayRef<SCEVUse> SCEVs) {
   for (const auto *S : ToForget)
     forgetMemoizedResultsImpl(S);
 
-  for (auto I = PredicatedSCEVRewrites.begin();
-       I != PredicatedSCEVRewrites.end();) {
-    std::pair<const SCEV *, const Loop *> Entry = I->first;
-    if (ToForget.count(Entry.first))
-      PredicatedSCEVRewrites.erase(I++);
-    else
-      ++I;
-  }
+  PredicatedSCEVRewrites.remove_if(
+      [&](const auto &Entry) { return ToForget.count(Entry.first.first); });
 }
 
 void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
index 2bd278614f8ac..d4da80a49bc71 100644
--- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
+++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
@@ -543,18 +543,15 @@ class MemLocFragmentFill {
     // Meet A and B.
     //
     // Result = meet(a, b) for a in A, b in B where Var(a) == Var(b)
-    for (auto It = A.begin(), End = A.end(); It != End; ++It) {
-      unsigned AVar = It->first;
-      FragsInMemMap &AFrags = It->second;
-      auto BIt = B.find(AVar);
-      if (BIt == B.end()) {
-        A.erase(It);
-        continue; // Var has no bits defined in B.
-      }
+    A.remove_if([&](auto &Entry) {
+      auto BIt = B.find(Entry.first);
+      if (BIt == B.end())
+        return true; // Var has no bits defined in B.
       LLVM_DEBUG(dbgs() << "meet fragment maps for "
-                        << Aggregates[AVar].first->getName() << "\n");
-      AFrags = meetFragments(AFrags, BIt->second);
-    }
+                        << Aggregates[Entry.first].first->getName() << "\n");
+      Entry.second = meetFragments(Entry.second, BIt->second);
+      return false;
+    });
   }
 
   bool meet(const BasicBlock &BB,
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 1d8fdcab64909..6bfd21b215706 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -255,7 +255,7 @@ class CopyTracker {
         }
       }
       // Now we can erase the copy.
-      Copies.erase(I);
+      Copies.erase(Unit);
     }
   }
 
diff --git a/llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp b/llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp
index 4f281fa1361ca..811cc4fe65f3f 100644
--- a/llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp
+++ b/llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp
@@ -243,15 +243,17 @@ bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) {
     }
 
     // Clear any entries in map that MI clobbers.
-    for (auto DefI : llvm::make_early_inc_range(MBBDefs)) {
-      Register Reg = DefI.first;
+    MBBDefs.remove_if([&](const auto &Entry) {
+      Register Reg = Entry.first;
       if (MI.modifiesRegister(Reg, TRI)) {
-        MBBDefs.erase(Reg);
         MBBKills.erase(Reg);
-      } else if (MI.findRegisterUseOperandIdx(Reg, TRI, true /*isKill*/) != -1)
+        return true;
+      }
+      if (MI.findRegisterUseOperandIdx(Reg, TRI, true /*isKill*/) != -1)
         // Keep track of all instructions that fully or partially kills Reg.
         MBBKills[Reg].push_back(&MI);
-    }
+      return false;
+    });
 
     // Record this MI for potential later reuse.
     if (IsCandidate) {
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
index cfbffb920ef36..19a81e3363086 100644
--- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
@@ -1813,14 +1813,13 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
             }
           } else if (MO.isRegMask()) {
             const uint32_t *RegMask = MO.getRegMask();
-            for (auto &RegMI : NAPhysToVirtMIs) {
-              Register Def = RegMI.first;
-              if (MachineOperand::clobbersPhysReg(RegMask, Def)) {
-                LLVM_DEBUG(dbgs()
-                           << "NAPhysCopy: invalidating because of " << *MI);
-                NAPhysToVirtMIs.erase(Def);
-              }
-            }
+            NAPhysToVirtMIs.remove_if([&](const auto &RegMI) {
+              if (!MachineOperand::clobbersPhysReg(RegMask, RegMI.first))
+                return false;
+              LLVM_DEBUG(dbgs()
+                         << "NAPhysCopy: invalidating because of " << *MI);
+              return true;
+            });
           }
         }
       }
diff --git a/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
index 11468245f8400..30057317a6383 100644
--- a/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
+++ b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp
@@ -128,11 +128,9 @@ static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) {
       continue;
 
     // Stop tracking any location that is clobbered by this instruction.
-    for (auto &Var : VariableMap) {
-      auto &LocOp = Var.second.first;
-      if (MI.modifiesRegister(LocOp->getReg(), TRI))
-        VariableMap.erase(Var.first);
-    }
+    VariableMap.remove_if([&](const auto &Var) {
+      return MI.modifiesRegister(Var.second.first->getReg(), TRI);
+    });
   }
 
   for (auto &Instr : DbgValsToBeRemoved) {
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index ac780dc82ae5a..1838397f7b270 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -1065,9 +1065,7 @@ void JITDylib::removeFromLinkOrder(JITDylib &JD) {
 Error JITDylib::remove(const SymbolNameSet &Names) {
   return ES.runSessionLocked([&]() -> Error {
     assert(State == Open && "JD is defunct");
-    using SymbolMaterializerItrPair =
-        std::pair<SymbolTable::iterator, UnmaterializedInfosMap::iterator>;
-    std::vector<SymbolMaterializerItrPair> SymbolsToRemove;
+    SmallVector<SymbolStringPtr, 0> SymbolsToRemove;
     SymbolNameSet Missing;
     SymbolNameSet Materializing;
 
@@ -1087,10 +1085,7 @@ Error JITDylib::remove(const SymbolNameSet &Names) {
         continue;
       }
 
-      auto UMII = I->second.hasMaterializerAttached()
-                      ? UnmaterializedInfos.find(Name)
-                      : UnmaterializedInfos.end();
-      SymbolsToRemove.push_back(std::make_pair(I, UMII));
+      SymbolsToRemove.push_back(Name);
     }
 
     // If any of the symbols are not defined, return an error.
@@ -1103,18 +1098,18 @@ Error JITDylib::remove(const SymbolNameSet &Names) {
       return make_error<SymbolsCouldNotBeRemoved>(ES.getSymbolStringPool(),
                                                   std::move(Materializing));
 
-    // Remove the symbols.
-    for (auto &SymbolMaterializerItrPair : SymbolsToRemove) {
-      auto UMII = SymbolMaterializerItrPair.second;
-
+    // Remove the symbols. Erase by key rather than holding iterators across the
+    // loop: a prior erase invalidates other stored iterators under
+    // backward-shift deletion.
+    for (const SymbolStringPtr &Name : SymbolsToRemove) {
       // If there is a materializer attached, call discard.
+      auto UMII = UnmaterializedInfos.find(Name);
       if (UMII != UnmaterializedInfos.end()) {
         UMII->second->MU->doDiscard(*this, UMII->first);
         UnmaterializedInfos.erase(UMII);
       }
 
-      auto SymI = SymbolMaterializerItrPair.first;
-      Symbols.erase(SymI);
+      Symbols.erase(Name);
     }
 
     shrinkMaterializationInfoMemory();
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp
index 7b9ad89038dc6..b8efa7a399734 100644
--- a/llvm/lib/IR/LegacyPassManager.cpp
+++ b/llvm/lib/IR/LegacyPassManager.cpp
@@ -903,40 +903,26 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
     return;
 
   const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
-  for (auto I = AvailableAnalysis.begin(), E = AvailableAnalysis.end();
-       I != E;) {
-    auto Info = I++;
-    if (Info->second->getAsImmutablePass() == nullptr &&
-        !is_contained(PreservedSet, Info->first)) {
-      // Remove this analysis
-      if (PassDebugging >= Details) {
-        Pass *S = Info->second;
-        dbgs() << " -- '" <<  P->getPassName() << "' is not preserving '";
-        dbgs() << S->getPassName() << "'\n";
-      }
-      AvailableAnalysis.erase(Info);
+  auto IsNotPreserved = [&](const auto &Entry) {
+    if (Entry.second->getAsImmutablePass() != nullptr ||
+        is_contained(PreservedSet, Entry.first))
+      return false;
+    // Remove this analysis
+    if (PassDebugging >= Details) {
+      Pass *S = Entry.second;
+      dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
+      dbgs() << S->getPassName() << "'\n";
     }
-  }
+    return true;
+  };
+  AvailableAnalysis.remove_if(IsNotPreserved);
 
   // Check inherited analysis also. If P is not preserving analysis
   // provided by parent manager then remove it here.
   for (DenseMap<AnalysisID, Pass *> *IA : InheritedAnalysis) {
     if (!IA)
       continue;
-
-    for (auto I = IA->begin(), E = IA->end(); I != E;) {
-      auto Info = I++;
-      if (Info->second->getAsImmutablePass() == nullptr &&
-          !is_contained(PreservedSet, Info->first)) {
-        // Remove this analysis
-        if (PassDebugging >= Details) {
-          Pass *S = Info->second;
-          dbgs() << " -- '" <<  P->getPassName() << "' is not preserving '";
-          dbgs() << S->getPassName() << "'\n";
-        }
-        IA->erase(Info);
-      }
-    }
+    IA->remove_if(IsNotPreserved);
   }
 }
 
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 88dafb94a4aaa..2bf5f05c1c315 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -272,12 +272,15 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
 
 void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
   auto Assignments = pendingAssignments.find(Symbol);
-  if (Assignments != pendingAssignments.end()) {
-    for (const PendingAssignment &A : Assignments->second)
-      emitAssignment(A.Symbol, A.Value);
+  if (Assignments == pendingAssignments.end())
+    return;
 
-    pendingAssignments.erase(Assignments);
-  }
+  // emitAssignment can recursively re-enter emitPendingAssignments for
+  // other symbols, so move the list out and erase before iterating.
+  SmallVector<PendingAssignment, 1> Pending = std::move(Assignments->second);
+  pendingAs...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/199365


More information about the Mlir-commits mailing list