| Issue |
185188
|
| Summary |
[LoopIdiomVectorize] Crash on find-first-byte idiom with non-zero address space pointers
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
cardigan1008
|
Here is a crash case when reviewing https://github.com/llvm/llvm-project/pull/180570:
```llvm
define ptr addrspace(1) @find_first_of_i8(ptr addrspace(1) %search_start, ptr addrspace(1) %search_end, ptr addrspace(1) %needle_start, ptr addrspace(1) %needle_end) #0 {
entry:
%search_test = icmp eq ptr addrspace(1) %search_start, %search_end
%needle_test = icmp eq ptr addrspace(1) %needle_start, %needle_end
%combined_test = or i1 %search_test, %needle_test
br i1 %combined_test, label %exit, label %header
header: ; preds = %search_check, %entry
%search_ptr = phi ptr addrspace(1) [ %search_next, %search_check ], [ %search_start, %entry ]
%search_load = load i8, ptr addrspace(1) %search_ptr, align 1
br label %match_check
needle_check: ; preds = %match_check
%needle_next = getelementptr inbounds i8, ptr addrspace(1) %needle_ptr, i64 1
%needle_cmp = icmp eq ptr addrspace(1) %needle_next, %needle_end
br i1 %needle_cmp, label %search_check, label %match_check
match_check: ; preds = %needle_check, %header
%needle_ptr = phi ptr addrspace(1) [ %needle_start, %header ], [ %needle_next, %needle_check ]
%needle_load = load i8, ptr addrspace(1) %needle_ptr, align 1
%match_cmp = icmp eq i8 %search_load, %needle_load
br i1 %match_cmp, label %exit, label %needle_check
search_check: ; preds = %needle_check
%search_next = getelementptr inbounds i8, ptr addrspace(1) %search_ptr, i64 1
%search_cmp = icmp eq ptr addrspace(1) %search_next, %search_end
br i1 %search_cmp, label %exit, label %header
exit: ; preds = %search_check, %match_check, %entry
%res = phi ptr addrspace(1) [ %search_end, %entry ], [ %search_ptr, %match_check ], [ %search_end, %search_check ]
ret ptr addrspace(1) %res
}
attributes #0 = { "target-features"="+sve2" }
```
Compiler Explorer: https://alive2.llvm.org/ce/z/mbLPTD
Crash:
```sh
opt: llvm/include/llvm/IR/Instructions.h:2720: void llvm::PHINode::setIncomingValue(unsigned int, llvm::Value*): Assertion `getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"' failed.
```
Backtrace:
```sh
Stack dump:
0. Program arguments: bin/opt -S -mtriple=aarch64 -mattr=+sve -passes=loop(loop-idiom-vectorize) -verify-loop-info -verify-dom-info -S /data/tmp/tmpqwr1sb5n/orig.ll
1. Running pass "function(loop(loop-idiom-vectorize))" on module "/data/tmp/tmpqwr1sb5n/orig.ll"
2. Running pass "loop(loop-idiom-vectorize)" on function "find_first_of_i8"
#0 0x00007ac24d93665c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (bin/../lib/libLLVMSupport.so.23.0git+0x33665c)
#1 0x00007ac24d936acf PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
#2 0x00007ac24d933112 llvm::sys::RunSignalHandlers() (bin/../lib/libLLVMSupport.so.23.0git+0x333112)
#3 0x00007ac24d935632 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#4 0x00007ac24d245330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#5 0x00007ac24d29eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
#6 0x00007ac24d29eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
#7 0x00007ac24d29eb2c pthread_kill ./nptl/pthread_kill.c:89:10
#8 0x00007ac24d24527e raise ./signal/../sysdeps/posix/raise.c:27:6
#9 0x00007ac24d2288ff abort ./stdlib/abort.c:81:7
#10 0x00007ac24d22881b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#11 0x00007ac24d23b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#12 0x00007ac246d24ba3 llvm::PHINode::setIncomingValue(unsigned int, llvm::Value*) (bin/../lib/../lib/libLLVMVectorize.so.23.0git+0x124ba3)
#13 0x00007ac246d24cab llvm::PHINode::addIncoming(llvm::Value*, llvm::BasicBlock*) (bin/../lib/../lib/libLLVMVectorize.so.23.0git+0x124cab)
#14 0x00007ac246d30795 (anonymous namespace)::LoopIdiomVectorize::expandFindFirstByte(llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::DomTreeUpdater&, unsigned int, llvm::Type*, llvm::Value*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::Value*, llvm::Value*, llvm::Value*, llvm::Value*) LoopIdiomVectorize.cpp:0:0
#15 0x00007ac246d30a90 (anonymous namespace)::LoopIdiomVectorize::transformFindFirstByte(llvm::PHINode*, unsigned int, llvm::Type*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::Value*, llvm::Value*, llvm::Value*, llvm::Value*) LoopIdiomVectorize.cpp:0:0
#16 0x00007ac246d2e811 (anonymous namespace)::LoopIdiomVectorize::recognizeFindFirstByte() LoopIdiomVectorize.cpp:0:0
#17 0x00007ac246d27d8f (anonymous namespace)::LoopIdiomVectorize::run(llvm::Loop*) LoopIdiomVectorize.cpp:0:0
#18 0x00007ac246d27980 llvm::LoopIdiomVectorizePass::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (bin/../lib/../lib/libLLVMVectorize.so.23.0git+0x127980)
#19 0x00007ac24bd26441 llvm::detail::PassModel<llvm::Loop, llvm::LoopIdiomVectorizePass, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (bin/../lib/../lib/libLLVMRISCVCodeGen.so.23.0git+0x326441)
#20 0x00007ac244b91e59 std::optional<llvm::PreservedAnalyses> llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runSinglePass<llvm::Loop, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>>(llvm::Loop&, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&, llvm::PassInstrumentation&) (bin/../lib/../lib/libLLVMScalarOpts.so.23.0git+0x391e59)
#21 0x00007ac244b906e4 llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runWithoutLoopNestPasses(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (bin/../lib/../lib/libLLVMScalarOpts.so.23.0git+0x3906e4)
#22 0x00007ac244b8fc48 llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (bin/../lib/../lib/libLLVMScalarOpts.so.23.0git+0x38fc48)
#23 0x00007ac24c55f733 llvm::detail::PassModel<llvm::Loop, llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (bin/../lib/../lib/libLLVMX86CodeGen.so.23.0git+0x15f733)
#24 0x00007ac244b90f6a llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (bin/../lib/../lib/libLLVMScalarOpts.so.23.0git+0x390f6a)
#25 0x00007ac24c55c605 llvm::detail::PassModel<llvm::Function, llvm::FunctionToLoopPassAdaptor, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (bin/../lib/../lib/libLLVMX86CodeGen.so.23.0git+0x15c605)
#26 0x00007ac241b58e03 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (bin/../lib/../lib/libLLVMCore.so.23.0git+0x558e03)
#27 0x00007ac24c55cd6b llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (bin/../lib/../lib/libLLVMX86CodeGen.so.23.0git+0x15cd6b)
#28 0x00007ac241b5b656 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (bin/../lib/../lib/libLLVMCore.so.23.0git+0x55b656)
#29 0x00007ac24dca5a5f llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (bin/../lib/libLLVMOptDriver.so.23.0git+0x53a5f)
#30 0x00007ac241b589c3 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (bin/../lib/../lib/libLLVMCore.so.23.0git+0x5589c3)
#31 0x00007ac24dc7b03a llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (bin/../lib/libLLVMOptDriver.so.23.0git+0x2903a)
#32 0x00007ac24dcb27fc optMain (bin/../lib/libLLVMOptDriver.so.23.0git+0x607fc)
#33 0x0000586b9007f1e8 main (bin/opt+0x11e8)
#34 0x00007ac24d22a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#35 0x00007ac24d22a28b call_init ./csu/../csu/libc-start.c:128:20
#36 0x00007ac24d22a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#37 0x0000586b9007f0a5 _start (bin/opt+0x10a5)
```
> Note: This is a review assisted with a self-built agent. The reproducer was validated manually. Please let me know if anything is wrong.
**Bug Triggering Analysis:**
The provided test case uses pointers in `addrspace(1)` for the search and needle arrays. When `LoopIdiomVectorize` attempts to vectorize the loop, it creates a PHI node `MatchLCSSA` to hold the matching pointer. However, it hardcodes the type of this PHI node to `Builder.getPtrTy()`, which defaults to address space 0. Later, it tries to add the `Search` pointer (which is in `addrspace(1)`) as an incoming value to this PHI node. This type mismatch triggers an assertion failure in `PHINode::setIncomingValue`.
**Fix Weakness Analysis:**
The weakness in the fix is that it assumes all pointers are in address space 0 when creating the `MatchLCSSA` PHI node. The original code used `SearchStart->getType()` or similar to get the correct pointer type, but the new code uses `Builder.getPtrTy()`, which does not preserve the address space of the original pointers. This causes a crash when the optimization is applied to loops operating on pointers in non-zero address spaces.
cc @rj-jesus
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs