[PATCH] D98602: [SCCP] Avoid modifying AdditionalUsers while iterating over it

Dimitry Andric via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 14 11:02:49 PDT 2021


dim added a comment.

In D98602#2624871 <https://reviews.llvm.org/D98602#2624871>, @lebedev.ri wrote:

> Test missing.

I haven't yet reduced the test case, will see to that. (One issue is that any failure would only show up on FreeBSD and OpenBSD...)

> Am i understanding correctly that the problem is *only* that the inner `SmallPtrSet` may get new entries added to it?

I think so, the problem is that `SCCPSolver::AdditionalUsers` is a `DenseMap` which is iterated over:

  auto Iter = AdditionalUsers.find(I);
  if (Iter != AdditionalUsers.end()) {
    for (User *U : Iter->second)
      if (auto *UI = dyn_cast<Instruction>(U))
        OperandChangedState(UI);
  }

meanwhile, `OperandChangedState()` can change the `Instruction` pointed to, via `visit()`:

  void OperandChangedState(Instruction *I) {
    if (BBExecutable.count(I->getParent()))   // Inst is executable?
      visit(*I);
  }

Apparently, `visit()` can cause the `SmallPtrSet` to grow, which invalidates the `U` iterator, as it shows in valgrind output:

  ==1366860== Invalid read of size 8
  ==1366860==    at 0x18CD850: AdvanceIfNotValid (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:250)
  ==1366860==    by 0x18CD850: operator++ (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:301)
  ==1366860==    by 0x18CD850: (anonymous namespace)::SCCPSolver::markUsersAsChanged(llvm::Value*) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:536)
  ==1366860==    by 0x18C773A: (anonymous namespace)::SCCPSolver::Solve() (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1420)
  ==1366860==    by 0x18C4EE4: llvm::runIPSCCP(llvm::Module&, llvm::DataLayout const&, std::function<llvm::TargetLibraryInfo const& (llvm::Function&)>, llvm::function_ref<llvm::AnalysisResultsForFn (llvm::Function&)>) (sr
  c/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:0)
  ==1366860==    by 0x153E53E: llvm::IPSCCPPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm-project/llvm/lib/Transforms/IPO/SCCP.cpp:24)
  ==1366860==    by 0x28BF9BC: llvm::detail::PassModel<llvm::Module, llvm::IPSCCPPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm
  -project/llvm/include/llvm/IR/PassManagerInternal.h:85)
  ==1366860==    by 0x13E9D75: llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm-project/llvm/include/llvm/IR/PassManager.h:517)
  ==1366860==    by 0x1C254A7: (anonymous namespace)::EmitAssemblyHelper::EmitAssemblyWithNewPassManager(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (src/
  llvm/llvm-project/clang/lib/CodeGen/BackendUtil.cpp:1465)
  ==1366860==    by 0x1C1F9CF: clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::DataLayout
  const&, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (src/llvm/llvm-project/clang/lib/CodeGen/BackendUtil.cpp:1634)
  ==1366860==    by 0x27FE6DF: clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (src/llvm/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:334)
  ==1366860==    by 0x32CF2C2: clang::ParseAST(clang::Sema&, bool, bool) (src/llvm/llvm-project/clang/lib/Parse/ParseAST.cpp:171)
  ==1366860==    by 0x21D8AC3: clang::FrontendAction::Execute() (src/llvm/llvm-project/clang/lib/Frontend/FrontendAction.cpp:949)
  ==1366860==    by 0x2154162: clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (src/llvm/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:955)
  ==1366860==  Address 0x7c9c678 is 8 bytes inside a block of size 1,024 free'd
  ==1366860==    at 0x697BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==1366860==    by 0x197F06A: llvm::SmallPtrSetImplBase::Grow(unsigned int) (src/llvm/llvm-project/llvm/lib/Support/SmallPtrSet.cpp:116)
  ==1366860==    by 0x197EEF5: llvm::SmallPtrSetImplBase::insert_imp_big(void const*) (src/llvm/llvm-project/llvm/lib/Support/SmallPtrSet.cpp:0)
  ==1366860==    by 0xDA841E: insert_imp (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:154)
  ==1366860==    by 0xDA841E: llvm::SmallPtrSetImpl<llvm::User*>::insert(llvm::User*) (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:365)
  ==1366860==    by 0x18CF349: (anonymous namespace)::SCCPSolver::addAdditionalUser(llvm::Value*, llvm::User*) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:514)
  ==1366860==    by 0x18CE9BB: (anonymous namespace)::SCCPSolver::handleCallResult(llvm::CallBase&) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1332)
  ==1366860==    by 0x18D3F5B: (anonymous namespace)::SCCPSolver::visitCallBase(llvm::CallBase&) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1188)
  ==1366860==    by 0x18CD827: OperandChangedState (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:508)
  ==1366860==    by 0x18CD827: (anonymous namespace)::SCCPSolver::markUsersAsChanged(llvm::Value*) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:538)
  ==1366860==    by 0x18C773A: (anonymous namespace)::SCCPSolver::Solve() (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1420)
  ==1366860==    by 0x18C4EE4: llvm::runIPSCCP(llvm::Module&, llvm::DataLayout const&, std::function<llvm::TargetLibraryInfo const& (llvm::Function&)>, llvm::function_ref<llvm::AnalysisResultsForFn (llvm::Function&)>) (sr
  c/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:0)
  ==1366860==    by 0x153E53E: llvm::IPSCCPPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm-project/llvm/lib/Transforms/IPO/SCCP.cpp:24)
  ==1366860==    by 0x28BF9BC: llvm::detail::PassModel<llvm::Module, llvm::IPSCCPPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm
  -project/llvm/include/llvm/IR/PassManagerInternal.h:85)
  ==1366860==  Block was alloc'd at
  ==1366860==    at 0x697A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==1366860==    by 0x197EF77: safe_malloc (src/llvm/llvm-project/llvm/include/llvm/Support/MemAlloc.h:26)
  ==1366860==    by 0x197EF77: llvm::SmallPtrSetImplBase::Grow(unsigned int) (src/llvm/llvm-project/llvm/lib/Support/SmallPtrSet.cpp:100)
  ==1366860==    by 0x197EEF5: llvm::SmallPtrSetImplBase::insert_imp_big(void const*) (src/llvm/llvm-project/llvm/lib/Support/SmallPtrSet.cpp:0)
  ==1366860==    by 0xDA841E: insert_imp (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:154)
  ==1366860==    by 0xDA841E: llvm::SmallPtrSetImpl<llvm::User*>::insert(llvm::User*) (src/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:365)
  ==1366860==    by 0x18CF349: (anonymous namespace)::SCCPSolver::addAdditionalUser(llvm::Value*, llvm::User*) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:514)
  ==1366860==    by 0x18CE9BB: (anonymous namespace)::SCCPSolver::handleCallResult(llvm::CallBase&) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1332)
  ==1366860==    by 0x18D3F5B: (anonymous namespace)::SCCPSolver::visitCallBase(llvm::CallBase&) (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1188)
  ==1366860==    by 0x18C7A6B: visit<llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, false> > (src/llvm/llvm-project/llvm/include/llvm/IR/InstVisitor.h:90)
  ==1366860==    by 0x18C7A6B: visit (src/llvm/llvm-project/llvm/include/llvm/IR/InstVisitor.h:105)
  ==1366860==    by 0x18C7A6B: visit (src/llvm/llvm-project/llvm/include/llvm/IR/InstVisitor.h:111)
  ==1366860==    by 0x18C7A6B: (anonymous namespace)::SCCPSolver::Solve() (src/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:1448)
  ==1366860==    by 0x18C4EE4: llvm::runIPSCCP(llvm::Module&, llvm::DataLayout const&, std::function<llvm::TargetLibraryInfo const& (llvm::Function&)>, llvm::function_ref<llvm::AnalysisResultsForFn (llvm::Function&)>) (sr
  c/llvm/llvm-project/llvm/lib/Transforms/Scalar/SCCP.cpp:0)
  ==1366860==    by 0x153E53E: llvm::IPSCCPPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm-project/llvm/lib/Transforms/IPO/SCCP.cpp:24)
  ==1366860==    by 0x28BF9BC: llvm::detail::PassModel<llvm::Module, llvm::IPSCCPPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm
  -project/llvm/include/llvm/IR/PassManagerInternal.h:85)
  ==1366860==    by 0x13E9D75: llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (src/llvm/llvm-project/llvm/include/llvm/IR/PassManager.h:517)



> I think the fix depends on the expected behavior here, in particular, two things stand out:
>
> - when looping over that set there, if a new unique entry is added in process, should it be ignored, or handled?
> - what if said new entry isn't unique? should it be re-handled?
>
> I'm not sure about the latter, but not handling the former //seems// like a bug.
> I think we should instead change `AdditionalUsers` from `DenseMap<Value *, SmallPtrSet<User *, 2>>` to `DenseMap<Value *, SetVector<User *, 2>>`,
> and change the loop to
>
>   // NOTE: new entries may be added to the vector in-process, invalidating iterators.
>   for(int I = 0; I != Iter->second.size(); ++I) {
>     User *U = Iter->second[I];
>     <...>
>   }
>
> But it is also possible that i don't know what i'm talking about.

I'm not familiar enough with the semantics of this code to have an informed opinion. :)

The solution proposed by @mortimer was just trying to work around the iterator invalidation, but preserves the original logic. In that respect, it is a minimalistic fix, but if there is a better solution, I'm all for it.

In D98602#2624876 <https://reviews.llvm.org/D98602#2624876>, @fhahn wrote:

> Does the crash trigger with ASan/MSan? Would it be possible to add a reduced test case from the bug report?

I've only run it under valgrind, but I'll attempt to reduce a test case from the bug report. On FreeBSD it gets a SIGBUS, and on OpenBSD apparently a SIGSEGV, but this type of memory error is typically non-portable. :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D98602



More information about the llvm-commits mailing list