[llvm] [Delinearization] Extract outer array dimensions using global object size (PR #175158)

Yunbo Ni via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 5 02:32:09 PST 2026


cardigan1008 wrote:

Hi, there is a related crash case:

```llvm
@test_array_10x20 = external global [0 x i8]

define void @test_2d_array(i64 %i, i64 %j, i64 %N, i64 %M) {
entry:
  br label %for.i

for.i:                                            ; preds = %for.j.end, %entry
  %i.cur = phi i64 [ 0, %entry ], [ %i.next, %for.j.end ]
  %gepi = getelementptr inbounds nuw [20 x i32], ptr @test_array_10x20, i64 %i.cur
  %i.cmp = icmp slt i64 %i.cur, %N
  br i1 %i.cmp, label %for.j, label %exit

for.j:                                            ; preds = %for.j, %for.i
  %j.cur = phi i64 [ 0, %for.i ], [ %j.next, %for.j ]
  %gepij = getelementptr inbounds nuw i32, ptr %gepi, i64 %j.cur
  %val = load i32, ptr %gepij, align 4
  %j.next = add i64 %j.cur, 1
  %j.cmp = icmp slt i64 %j.next, %M
  br i1 %j.cmp, label %for.j, label %for.j.end

for.j.end:                                        ; preds = %for.j
  %i.next = add i64 %i.cur, 1
  br label %for.i

exit:                                             ; preds = %for.i
  ret void
}
```

With opt built on this patch, a crash occurred:

```sh
Printing analysis 'Delinearization' for function 'test_2d_array':
Inst:  %val = load i32, ptr %gepij, align 4
AccessFunction: {{0,+,80}<%for.i>,+,4}<%for.j>
opt: /data/yunboni/projects/Archer/deps/llvm/llvm/llvm/lib/Support/APInt.cpp:1776: static void llvm::APInt::udivrem(const llvm::APInt&, const llvm::APInt&, llvm::APInt&, llvm::APInt&): Assertion `RHS.U.VAL != 0 && "Divide by zero?"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: ./build/llvm-build/pr/175158/bin/opt -S -passes=print<delinearization> -disable-output -delinearize-use-fixed-size-array-heuristic src.ll
1.	Running pass "function(print<delinearization>)" on module "src.ll"
2.	Running pass "print<delinearization>" on function "test_2d_array"
 #0 0x00007c09f0b3332a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMSupport.so.23.0git+0x33332a)
 #1 0x00007c09f0b3379d PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #2 0x00007c09f0b2ff68 llvm::sys::RunSignalHandlers() (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMSupport.so.23.0git+0x32ff68)
 #3 0x00007c09f0b323a2 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #4 0x00007c09f0445330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #5 0x00007c09f049eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #6 0x00007c09f049eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #7 0x00007c09f049eb2c pthread_kill ./nptl/pthread_kill.c:89:10
 #8 0x00007c09f044527e raise ./signal/../sysdeps/posix/raise.c:27:6
 #9 0x00007c09f04288ff abort ./stdlib/abort.c:81:7
#10 0x00007c09f042881b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#11 0x00007c09f043b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#12 0x00007c09f0902ad5 llvm::APInt::udivrem(llvm::APInt const&, llvm::APInt const&, llvm::APInt&, llvm::APInt&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMSupport.so.23.0git+0x102ad5)
#13 0x00007c09f0903438 llvm::APInt::sdivrem(llvm::APInt const&, llvm::APInt const&, llvm::APInt&, llvm::APInt&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMSupport.so.23.0git+0x103438)
#14 0x00007c09e5fe8358 llvm::SCEVDivision::visitConstant(llvm::SCEVConstant const*) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e8358)
#15 0x00007c09e5fe9830 llvm::SCEVVisitor<llvm::SCEVDivision, void>::visit(llvm::SCEV const*) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e9830)
#16 0x00007c09e5fe81a2 llvm::SCEVDivision::divide(llvm::ScalarEvolution&, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const**, llvm::SCEV const**) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e81a2)
#17 0x00007c09e5fe84cd llvm::SCEVDivision::visitAddRecExpr(llvm::SCEVAddRecExpr const*) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e84cd)
#18 0x00007c09e5fe9920 llvm::SCEVVisitor<llvm::SCEVDivision, void>::visit(llvm::SCEV const*) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e9920)
#19 0x00007c09e5fe81a2 llvm::SCEVDivision::divide(llvm::ScalarEvolution&, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const**, llvm::SCEV const**) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x7e81a2)
#20 0x00007c09e5b05daa llvm::computeAccessFunctions(llvm::ScalarEvolution&, llvm::SCEV const*, llvm::SmallVectorImpl<llvm::SCEV const*>&, llvm::SmallVectorImpl<llvm::SCEV const*>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x305daa)
#21 0x00007c09e5b07010 llvm::delinearizeFixedSizeArray(llvm::ScalarEvolution&, llvm::SCEV const*, llvm::SmallVectorImpl<llvm::SCEV const*>&, llvm::SmallVectorImpl<llvm::SCEV const*>&, llvm::SCEV const*) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x307010)
#22 0x00007c09e5b07d5f (anonymous namespace)::printDelinearization(llvm::raw_ostream&, llvm::Function*, llvm::LoopInfo*, llvm::ScalarEvolution*) Delinearization.cpp:0:0
#23 0x00007c09e5b0822e llvm::DelinearizationPrinterPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMAnalysis.so.23.0git+0x30822e)
#24 0x00007c09eb82e8c3 llvm::detail::PassModel<llvm::Function, llvm::DelinearizationPrinterPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMPasses.so.23.0git+0x22e8c3)
#25 0x00007c09e4b50ecd llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMCore.so.23.0git+0x550ecd)
#26 0x00007c09ef756dc3 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMX86CodeGen.so.23.0git+0x156dc3)
#27 0x00007c09e4b53720 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMCore.so.23.0git+0x553720)
#28 0x00007c09f0dfe8cf llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMOptDriver.so.23.0git+0x538cf)
#29 0x00007c09e4b50a8d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/../lib/libLLVMCore.so.23.0git+0x550a8d)
#30 0x00007c09f0dd403a 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) (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMOptDriver.so.23.0git+0x2903a)
#31 0x00007c09f0e0b68c optMain (/data/yunboni/projects/Archer/build/llvm-build/pr/175158/bin/../lib/libLLVMOptDriver.so.23.0git+0x6068c)
#32 0x0000608c4d2901e8 main (./build/llvm-build/pr/175158/bin/opt+0x11e8)
#33 0x00007c09f042a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#34 0x00007c09f042a28b call_init ./csu/../csu/libc-start.c:128:20
#35 0x00007c09f042a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#36 0x0000608c4d2900a5 _start (./build/llvm-build/pr/175158/bin/opt+0x10a5)
```

Command:  `opt -S -passes='print<delinearization>' -disable-output -delinearize-use-fixed-size-array-heuristic src.ll`

> Note: This is a review assisted with a self-built agent. The reproducer was validated manually. Please let me know if anything is wrong.

The weakness is that the logic assumes the computed `OuterDim` is non-zero and safe to use as a divisor later.

- If the global is size 0 (e.g., `[0 x i8]`), then `OuterDim` becomes 0 and is later used as a divisor, causing a crash.

A robust fix should do one (or more) of the following:

- Check `SizeInBytes == 0` or `OuterDim == 0` in `extractOuterDimFromGlobal` and bail out.
- Ensure `computeAccessFunctions` explicitly handles a 0 dimension without dividing by 0.
- Additionally, ensure the global’s type is *sized* before calling `getTypeAllocSize`
  (otherwise completely unsized types, e.g., opaque structs, could trigger a similar crash).

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


More information about the llvm-commits mailing list