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

Loop vectorizer causes error in backend (COMDAT symbol of string literal does not exist) #100076

Open
vossjannik opened this issue Jul 23, 2024 · 1 comment

Comments

@vossjannik
Copy link

vossjannik commented Jul 23, 2024

Problem Description

After upgrading from clang 14, we experience an error in the LLVM backend when compiling for armv7a-none-windows-eabi.
The problem seems to be in the loop vectorizer and happens only with string literals that are longer than 15 characters.
It happens with clang 15, 16, 17, and 18.
The way the string buffer is allocated seems to be important, I was not able to reproduce the error when allocating the string buffer with "operator new".

Workaround

The code snippet in the repro steps includes an alternative implementation that apparently is optimized differently by the vectorizer.

Repro steps

Reproduce in Compiler Explorer

Compile the code snippet with the following command line arguments:

-Og -target armv7a-none-windows-eabi -fvectorize

using size_t = decltype(sizeof(0));

void* malloc(size_t);
void free(void*);

inline void move_chars(char* dest, const char* src, size_t nCount) {
	if (src < dest) {
#if 1
		// broken
		src  += nCount;
		dest += nCount;
		for (; nCount > 0; --nCount)
			*(--dest) = *(--src);
#else
		// working
		for (; nCount > 0; --nCount)
			dest[nCount - 1] =  src[nCount - 1];
#endif
	}
	else
		for (; nCount > 0; --nCount, ++src, ++dest)
			*dest =  *src;
}

void ReproduceCompilationError(){
	// strlen("Failed to flush.") == 16, no error with shorter string literals
	char* pData = static_cast<char*>(malloc(16 + 1));
	move_chars(pData, "Failed to flush.", 16);
	free(pData);
}

Error Message

fatal error: error in backend: Associative COMDAT symbol '??_C@_0BB@GABOHBIL@Failed?5to?5flush?4?$AA@' does not exist.
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-18.1.0/bin/clang++ -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-13.2.0 -fcolor-diagnostics -fno-crash-diagnostics -Og -target armv7a-none-windows-eabi -fvectorize <source>
1.	<eof> parser at end of file
2.	Code generation
 #0 0x000000000351ae38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x351ae38)
 #1 0x0000000003518f84 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3518f84)
 #2 0x0000000003467543 llvm::CrashRecoveryContext::HandleExit(int) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3467543)
 #3 0x000000000351097e llvm::sys::Process::Exit(int, bool) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x351097e)
 #4 0x0000000000c17976 (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0xc17976)
 #5 0x0000000003470593 llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3470593)
 #6 0x0000000002c16bda getComdatGVForCOFF(llvm::GlobalValue const*) TargetLoweringObjectFileImpl.cpp:0:0
 #7 0x0000000002c174db llvm::TargetLoweringObjectFileCOFF::SelectSectionForGlobal(llvm::GlobalObject const*, llvm::SectionKind, llvm::TargetMachine const&) const (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x2c174db)
 #8 0x00000000049e2b65 llvm::TargetLoweringObjectFile::SectionForGlobal(llvm::GlobalObject const*, llvm::SectionKind, llvm::TargetMachine const&) const (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x49e2b65)
 #9 0x000000000424d56d llvm::AsmPrinter::emitGlobalVariable(llvm::GlobalVariable const*) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x424d56d)
#10 0x00000000042553b9 llvm::AsmPrinter::doFinalization(llvm::Module&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x42553b9)
#11 0x0000000002edbc6d llvm::FPPassManager::doFinalization(llvm::Module&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x2edbc6d)
#12 0x0000000002ee84d0 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x2ee84d0)
#13 0x000000000378ad99 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x378ad99)
#14 0x0000000003d5b2d1 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3d5b2d1)
#15 0x0000000005b965d9 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x5b965d9)
#16 0x0000000003d5a725 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3d5a725)
#17 0x0000000003fe2aa1 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3fe2aa1)
#18 0x0000000003f6010b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3f6010b)
#19 0x00000000040c2473 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x40c2473)
#20 0x0000000000c19746 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0xc19746)
#21 0x0000000000c1211d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#22 0x0000000003da1979 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#23 0x0000000003467443 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3467443)
#24 0x0000000003da1b99 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#25 0x0000000003d69d17 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3d69d17)
#26 0x0000000003d6a6cd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3d6a6cd)
#27 0x0000000003d7445c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0x3d7445c)
#28 0x0000000000c16a21 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0xc16a21)
#29 0x0000000000b0fa84 main (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0xb0fa84)
#30 0x00007461aa629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#31 0x00007461aa629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#32 0x0000000000c1191e _start (/opt/compiler-explorer/clang-18.1.0/bin/clang+++0xc1191e)
clang++: error: clang frontend command failed with exit code 70 (use -v to see invocation)
@ghost
Copy link

ghost commented Jul 23, 2024

When I uncomment this line: https://github.com/llvm/llvm-project/blob/llvmorg-18.1.7/llvm/lib/IR/ValueSymbolTable.cpp#L94 (Line 94) and call the compiler with -mllvm -debug -mllvm -debug-only=valuesymtab, I get this output:

Removing Value: ??_C@_0BB@GABOHBIL@Failed?5to?5flush?4?$AA@

This happens in this stack:

clang.exe!llvm::ValueSymbolTable::removeValueName(llvm::StringMapEntry<llvm::Value *> * V) Line 97	C++
clang.exe!llvm::Value::setNameImpl(const llvm::Twine & NewName) Line 366	C++
clang.exe!llvm::Value::setName(const llvm::Twine & NewName) Line 378	C++
clang.exe!llvm::InnerLoopVectorizer::createInductionResumeValue(llvm::PHINode * OrigPhi, const llvm::InductionDescriptor & II, llvm::Value * Step, llvm::ArrayRef<llvm::BasicBlock *> BypassBlocks, std::pair<llvm::BasicBlock *,llvm::Value *> AdditionalBypass) Line 3088	C++
clang.exe!llvm::InnerLoopVectorizer::createInductionResumeValues(const llvm::DenseMap<llvm::SCEV const *,llvm::Value *,llvm::DenseMapInfo<llvm::SCEV const *,void>,llvm::detail::DenseMapPair<llvm::SCEV const *,llvm::Value *>> & ExpandedSCEVs, std::pair<llvm::BasicBlock *,llvm::Value *> AdditionalBypass) Line 3153	C++
clang.exe!llvm::InnerLoopVectorizer::createVectorizedLoopSkeleton(const llvm::DenseMap<llvm::SCEV const *,llvm::Value *,llvm::DenseMapInfo<llvm::SCEV const *,void>,llvm::detail::DenseMapPair<llvm::SCEV const *,llvm::Value *>> & ExpandedSCEVs) Line 3262	C++
clang.exe!llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount BestVF, unsigned int BestUF, llvm::VPlan & BestVPlan, llvm::InnerLoopVectorizer & ILV, llvm::DominatorTree * DT, bool IsEpilogueVectorization, const llvm::DenseMap<llvm::SCEV const *,llvm::Value *,llvm::DenseMapInfo<llvm::SCEV const *,void>,llvm::detail::DenseMapPair<llvm::SCEV const *,llvm::Value *>> * ExpandedSCEVs) Line 7579	C++
clang.exe!llvm::LoopVectorizePass::processLoop(llvm::Loop * L) Line 10239	C++
clang.exe!llvm::LoopVectorizePass::runImpl(llvm::Function & F, llvm::ScalarEvolution & SE_, llvm::LoopInfo & LI_, llvm::TargetTransformInfo & TTI_, llvm::DominatorTree & DT_, llvm::BlockFrequencyInfo * BFI_, llvm::TargetLibraryInfo * TLI_, llvm::DemandedBits & DB_, llvm::AssumptionCache & AC_, llvm::LoopAccessInfoManager & LAIs_, llvm::OptimizationRemarkEmitter & ORE_, llvm::ProfileSummaryInfo * PSI_) Line 10330	C++
clang.exe!llvm::LoopVectorizePass::run(llvm::Function & F, llvm::AnalysisManager<llvm::Function> & AM) Line 10369	C++
clang.exe!llvm::detail::PassModel<llvm::Function,llvm::LoopVectorizePass,llvm::PreservedAnalyses,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 89	C++
clang.exe!llvm::PassManager<llvm::Function,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 547	C++
clang.exe!llvm::detail::PassModel<llvm::Function,llvm::PassManager<llvm::Function,llvm::AnalysisManager<llvm::Function>>,llvm::PreservedAnalyses,llvm::AnalysisManager<llvm::Function>>::run(llvm::Function & IR, llvm::AnalysisManager<llvm::Function> & AM) Line 89	C++
clang.exe!llvm::ModuleToFunctionPassAdaptor::run(llvm::Module & M, llvm::AnalysisManager<llvm::Module> & AM) Line 123	C++
clang.exe!llvm::detail::PassModel<llvm::Module,llvm::ModuleToFunctionPassAdaptor,llvm::PreservedAnalyses,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 89	C++
clang.exe!llvm::PassManager<llvm::Module,llvm::AnalysisManager<llvm::Module>>::run(llvm::Module & IR, llvm::AnalysisManager<llvm::Module> & AM) Line 547	C++
clang.exe!`anonymous namespace'::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction Action, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> & OS, std::unique_ptr<llvm::ToolOutputFile,std::default_delete<llvm::ToolOutputFile>> & ThinLinkOS, clang::BackendConsumer * BC) Line 1101	C++
clang.exe!`anonymous namespace'::EmitAssemblyHelper::EmitAssembly(clang::BackendAction Action, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> OS, clang::BackendConsumer * BC) Line 1167	C++
clang.exe!clang::EmitBackendOutput(clang::DiagnosticsEngine & Diags, const clang::HeaderSearchOptions & HeaderOpts, const clang::CodeGenOptions & CGOpts, const clang::TargetOptions & TOpts, const clang::LangOptions & LOpts, llvm::StringRef TDesc, llvm::Module * M, clang::BackendAction Action, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, std::unique_ptr<llvm::raw_pwrite_stream,std::default_delete<llvm::raw_pwrite_stream>> OS, clang::BackendConsumer * BC) Line 1328	C++
clang.exe!clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext & C) Line 379	C++
clang.exe!clang::ParseAST(clang::Sema & S, bool PrintStats, bool SkipFunctionBodies) Line 183	C++
clang.exe!clang::ASTFrontendAction::ExecuteAction() Line 1183	C++
clang.exe!clang::CodeGenAction::ExecuteAction() Line 1153	C++
clang.exe!clang::FrontendAction::Execute() Line 1069	C++
clang.exe!clang::CompilerInstance::ExecuteAction(clang::FrontendAction & Act) Line 1057	C++
clang.exe!clang::ExecuteCompilerInvocation(clang::CompilerInstance * Clang) Line 272	C++
clang.exe!cc1_main(llvm::ArrayRef<char const *> Argv, const char * Argv0, void * MainAddr) Line 294	C++
clang.exe!ExecuteCC1Tool(llvm::SmallVectorImpl<char const *> & ArgV, const llvm::ToolContext & ToolContext) Line 365	C++
clang.exe!clang_main(int Argc, char * * Argv, const llvm::ToolContext & ToolContext) Line 405	C++
clang.exe!main(int argc, char * * argv) Line 17	C++
clang.exe!invoke_main() Line 79	C++
clang.exe!__scrt_common_main_seh() Line 288	C++
clang.exe!__scrt_common_main() Line 331	C++
clang.exe!mainCRTStartup(void * __formal) Line 17	C++
kernel32.dll!BaseThreadInitThunk()	Unknown
ntdll.dll!RtlUserThreadStart()	Unknown

The important place, where the symbol is rename, is in InnerLoopVectorizer::createInductionResumeValue here: https://github.com/llvm/llvm-project/blob/llvmorg-18.1.7/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp#L3088

EndValue->setName("ind.end");

It seems like, that the associated COMDAT (member llvm::GlobalObject::ObjComdat) is not updated. It has it's own name. And this name is initially equal to the name of the global variable ("??_C@_0BB@GABOHBIL@Failed?5to?5flush?4?$AA@"). The name of the COMDAT is still "??_C@_0BB@GABOHBIL@Failed?5to?5flush?4?$AA@" after the global Variable was renamed to "ind.end".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants