Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JumpThreading] Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed. #58812

Closed
TatyanaDoubts opened this issue Nov 4, 2022 · 3 comments
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] llvm:optimizations

Comments

@TatyanaDoubts
Copy link

TatyanaDoubts commented Nov 4, 2022

Godbolt repro: https://godbolt.org/z/M4brh6cGo
Run clang++ on the following test:
Test.cpp.txt

Backtrace:

clang++: /root/llvm-project/llvm/lib/IR/Value.cpp:503: void llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses): Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O3 <source>
1.	<eof> parser at end of file
2.	Optimizer
 #0 0x0000561defa67194 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x0000561defa64f2c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fb8f2c)
 #2 0x0000561def9a0188 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fc701c26420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007fc7016f300b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #5 0x00007fc7016d2859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #6 0x00007fc7016d2729 (/lib/x86_64-linux-gnu/libc.so.6+0x22729)
 #7 0x00007fc7016e3fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000561def231926 llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3785926)
 #9 0x0000561def7591a3 llvm::JumpThreadingPass::processBranchOnXOR(llvm::BinaryOperator*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3cad1a3)
#10 0x0000561def75cfb1 llvm::JumpThreadingPass::processBlock(llvm::BasicBlock*) (.part.0) JumpThreading.cpp:0:0
#11 0x0000561def75d977 llvm::JumpThreadingPass::runImpl(llvm::Function&, llvm::TargetLibraryInfo*, llvm::TargetTransformInfo*, llvm::LazyValueInfo*, llvm::AAResults*, llvm::DomTreeUpdater*, bool, std::unique_ptr<llvm::BlockFrequencyInfo, std::default_delete<llvm::BlockFrequencyInfo>>, std::unique_ptr<llvm::BranchProbabilityInfo, std::default_delete<llvm::BranchProbabilityInfo>>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3cb1977)
#12 0x0000561def75eccf llvm::JumpThreadingPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3cb2ccf)
#13 0x0000561defe29126 llvm::detail::PassModel<llvm::Function, llvm::JumpThreadingPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x437d126)
#14 0x0000561ded292f44 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x17e6f44)
#15 0x0000561dee827f56 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x2d7bf56)
#16 0x0000561ded279336 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x17cd336)
#17 0x0000561dee81f8a7 llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x2d738a7)
#18 0x0000561def33e8e6 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x38928e6)
#19 0x0000561dee823d54 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x2d77d54)
#20 0x0000561def33e896 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3892896)
#21 0x0000561dee821d74 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x2d75d74)
#22 0x0000561def3452fa llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x38992fa)
#23 0x0000561df0e1c7a6 llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x53707a6)
#24 0x0000561def203a2a llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3757a2a)
#25 0x0000561defe3acd0 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&) BackendUtil.cpp:0:0
#26 0x0000561defe3d262 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4391262)
#27 0x0000561df0d9821b clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x52ec21b)
#28 0x0000561df20343a5 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x65883a5)
#29 0x0000561df0d96c98 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x52eac98)
#30 0x0000561df0627cf9 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b7bcf9)
#31 0x0000561df05ae70e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b0270e)
#32 0x0000561df070cf73 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c60f73)
#33 0x0000561decf1bc74 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x146fc74)
#34 0x0000561decf17a77 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#35 0x0000561df041a259 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#36 0x0000561def9a092a llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3ef492a)
#37 0x0000561df041aaaf clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#38 0x0000561df03e3ed9 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4937ed9)
#39 0x0000561df03e495d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x493895d)
#40 0x0000561df03ee34c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x494234c)
#41 0x0000561decf1a262 clang_main(int, char**) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x146e262)
#42 0x00007fc7016d4083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#43 0x0000561decf133ae _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x14673ae)
clang-16: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134
@EugeneZelenko EugeneZelenko added llvm:optimizations crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Nov 4, 2022
@nikic nikic changed the title Clang failed with -O3: Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed. [JumpThreading] Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed. Nov 4, 2022
@nikic
Copy link
Contributor

nikic commented Nov 4, 2022

Reduced:

; RUN: opt -S -jump-threading < %s
define void @test() {
entry:
  br i1 false, label %loop, label %exit

loop:
  %bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ]
  %cmp = icmp eq i16 0, 1
  %xor = xor i1 %cmp, %bool
  br i1 %bool, label %loop.latch, label %exit

loop.latch:
  %dummy = phi i16 [ 0, %loop ]
  br label %loop 
   
exit:
  ret void 
}

@inclyc
Copy link
Member

inclyc commented Dec 10, 2022

Hi @nikic ! Thanks for this amazing reduced IR!

This loop looks like dead code because the entry block jumps directly to exit.

Should we arrange *DCE before JumpThreading in the pipeline?

Locally I made a patch solved this issue that check %xor's operand but it does not seem to be correct (we should not do optimization on dead codes?).

diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 75bc4bb76260..43fdfd225150 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1932,7 +1932,7 @@ bool JumpThreadingPass::processBranchOnXOR(BinaryOperator *BO) {
       // If all preds provide undef, just nuke the xor, because it is undef too.
       BO->replaceAllUsesWith(UndefValue::get(BO->getType()));
       BO->eraseFromParent();
-    } else if (SplitVal->isZero()) {
+    } else if (SplitVal->isZero() && BO != BO->getOperand(isLHS)) {
       // If all preds provide 0, replace the xor with the other input.
       BO->replaceAllUsesWith(BO->getOperand(isLHS));
       BO->eraseFromParent();

@nikic
Copy link
Contributor

nikic commented Dec 10, 2022

JumpThreading already removes unreachable blocks before it runs. However, new ones may be introduced as a result of transforms. It's either necessary to consistently remove them during transforms (this is probably hard because JT cannot use DT for compile-time reasons) or be robust against unreachable code.

@inclyc inclyc closed this as completed in 84733b0 Dec 21, 2022
CarlosAlbertoEnciso pushed a commit to SNSystems/llvm-debuginfo-analyzer that referenced this issue Dec 25, 2022
Reproducer:

    ; RUN: opt -S -jump-threading < %s
    define void @test() {
    entry:
    br i1 false, label %loop, label %exit

    loop:
    %bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ]
    %cmp = icmp eq i16 0, 1
    %xor = xor i1 %cmp, %bool
    br i1 %bool, label %loop.latch, label %exit

    loop.latch:
    %dummy = phi i16 [ 0, %loop ]
    br label %loop

    exit:
    ret void
    }

On this occassion, phi node %bool is actually %xor, and doing substitution causes assertion failure.

Fixes: llvm/llvm-project#58812

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D139783
veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue Jun 10, 2024
Reproducer:

    ; RUN: opt -S -jump-threading < %s
    define void @test() {
    entry:
    br i1 false, label %loop, label %exit

    loop:
    %bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ]
    %cmp = icmp eq i16 0, 1
    %xor = xor i1 %cmp, %bool
    br i1 %bool, label %loop.latch, label %exit

    loop.latch:
    %dummy = phi i16 [ 0, %loop ]
    br label %loop

    exit:
    ret void
    }

On this occassion, phi node %bool is actually %xor, and doing substitution causes assertion failure.

Fixes: llvm/llvm-project#58812

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D139783
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] llvm:optimizations
Projects
None yet
Development

No branches or pull requests

4 participants