llvm / llvm/llvm-project

[MLIR][Affine] `AffineLoadOp::fold` crashes on zero-sized constant memref during canonicalization

Open
#223,949 2 comments 0 reactions 1 assignee Assigned to @purnima-nlp View on GitHub
crash mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

### Description

`mlir-opt` crashes with an assertion failure when running `-canonicalize` on an affine.load that reads from a constant global memref<0xi8>.
The crash occurs in `AffineLoadOp::fold`, which attempts to constant-fold the load and eventually indexes into a `DenseElementsAttr` representing a zero-sized shaped type.

### Tested commit

[3b8ee89](https://github.com/llvm/llvm-project/commit/3b8ee89006f5a228fce75528f8dd80b4229abcc1)

### Test case

```mlir
module {
memref.global "private" constant @__constant_0xi8 : memref<0xi8, #spirv.storage_class> = dense<>
func.func private @main(%arg1: tensor<1xi32>, %arg2: tensor<1xi8>, %arg3: tensor<1xi16>, %arg4: tensor<1xi16>) -> tensor<1xi32> attributes {llvm.arm_locally_streaming, llvm.arm_out_za, llvm.arm_streaming, llvm.emit_c_interface} {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%0 = llvm.mlir.constant(0 : i32) : i32
%1 = llvm.mlir.constant(-1 : i32) : i32
%2 = bufferization.to_buffer %arg1 : tensor<1xi32> to memref<1xi32, strided<[?], offset: ?>, #spirv.storage_class>
%3 = bufferization.to_buffer %arg1 : tensor<1xi32> to memref<1xi32, strided<[?], offset: ?>, #spirv.storage_class>
%4 = memref.get_global @__constant_0xi8 : memref<0xi8, #spirv.storage_class>
%collapse_shape = memref.collapse_shape %3 [] : memref<1xi32, strided<[?], offset: ?>, #spirv.storage_class> into memref, #spirv.storage_class>
%alloc = memref.alloc() {} : memref<1xi32, #spirv.storage_class>
gpu.launch blocks(%arg5, %arg6, %arg7) in (%arg11 = %c1, %arg12 = %c1, %arg13 = %c1) threads(%arg8, %arg9, %arg10) in (%arg14 = %c1, %arg15 = %c1, %arg16 = %c1) {
%6 = affine.load %2[%arg5] : memref<1xi32, strided<[?], offset: ?>, #spirv.storage_class>
%7 = affine.load %collapse_shape[] : memref, #spirv.storage_class>
%8 = affine.load %4[%arg5] : memref<0xi8, #spirv.storage_class>
%9 = tosa.apply_scale %6, %7, %8 {rounding_mode = SINGLE_ROUND} : (i32, i32, i8) -> i32
%10 = llvm.intr.smax(%9, %0) : (i32, i32) -> i32
%11 = llvm.intr.smin(%10, %1) : (i32, i32) -> i32
affine.store %11, %alloc[%arg5] : memref<1xi32, #spirv.storage_class>
affine.store %11, %alloc[%arg5] : memref<1xi32, #spirv.storage_class>
affine.store %11, %alloc[%arg5] : memref<1xi32, #spirv.storage_class>
gpu.terminator
}
%5 = bufferization.to_tensor %alloc : memref<1xi32, #spirv.storage_class> to tensor<1xi32>
return %5 : tensor<1xi32>
}
}
```

### Steps to reproduce

```
mlir-opt test.mlir -canonicalize
```

### stack trace

```
mlir-opt: /home/workdir/llvm-project-latest/mlir/lib/IR/BuiltinAttributeInterfaces.cpp:58: static uint64_t mlir::ElementsAttr::getFlattenedIndex(Type, ArrayRef): Assertion `isValidIndex(shapeType, index) && "expected valid multi-dimensional index"' 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: ./mlir-opt test.mlir -canonicalize
#0 0x00005562fa3a5d0b llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (./mlir-opt+0x1fc2d0b)
#1 0x00005562fa3a2b11 llvm::sys::RunSignalHandlers() (./mlir-opt+0x1fbfb11)
#2 0x00005562fa3a6a3b SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#3 0x00007f378678f520 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007f37867e39fc pthread_kill (/usr/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
#5 0x00007f378678f476 gsignal (/usr/lib/x86_64-linux-gnu/libc.so.6+0x42476)
#6 0x00007f37867757f3 abort (/usr/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
#7 0x00007f378677571b (/usr/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
#8 0x00007f3786786e96 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#9 0x0000556302805bd1 mlir::ElementsAttr::getFlattenedIndex(mlir::Type, llvm::ArrayRef) (./mlir-opt+0xa422bd1)
#10 0x000055630211cc3b mlir::detail::ElementsAttrRange::operator[](llvm::ArrayRef) const (./mlir-opt+0x9d39c3b)
#11 0x000055630211c9a7 mlir::affine::AffineLoadOp::fold(mlir::affine::AffineLoadOpGenericAdaptor>) (./mlir-opt+0x9d399a7)
#12 0x00005563021753f1 llvm::LogicalResult mlir::Op::Impl, mlir::OpTrait::ZeroSuccessors, mlir::OpTrait::AtLeastNOperands<1u>::Impl, mlir::OpTrait::OpInvariants, mlir::BytecodeOpInterface::Trait, mlir::affine::AffineReadOpInterface::Trait, mlir::affine::AffineMapAccessInterface::Trait, mlir::AlignmentAttrOpInterface::Trait, mlir::OpTrait::MemRefsNormalizable, mlir::MemoryEffectOpInterface::Trait>::foldSingleResultHook(mlir::Operation*, llvm::ArrayRef, llvm::SmallVectorImpl&) (./mlir-opt+0x9d923f1)
#13 0x00005563028be56b mlir::Operation::fold(llvm::ArrayRef, llvm::SmallVectorImpl&) (./mlir-opt+0xa4db56b)
#14 0x00005563028be8e6 mlir::Operation::fold(llvm::SmallVectorImpl&) (./mlir-opt+0xa4db8e6)
#15 0x000055630251e1ac (anonymous namespace)::GreedyPatternRewriteDriver::processWorklist() GreedyPatternRewriteDriver.cpp:0:0
#16 0x000055630251d890 void llvm::function_ref::callback_fn<(anonymous namespace)::RegionPatternRewriteDriver::simplify(bool*) &&::$_2>(long) GreedyPatternRewriteDriver.cpp:0:0
#17 0x000055630251a8b5 mlir::applyPatternsGreedily(mlir::Region&, mlir::FrozenRewritePatternSet const&, mlir::GreedyRewriteConfig, bool*) (./mlir-opt+0xa1378b5)
#18 0x000055630249c3a5 (anonymous namespace)::Canonicalizer::runOnOperation() Canonicalizer.cpp:0:0
#19 0x00005563025a53ee mlir::detail::OpToOpPassAdaptor::run(mlir::Pass*, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int) (./mlir-opt+0xa1c23ee)
#20 0x00005563025a6364 mlir::detail::OpToOpPassAdaptor::runPipeline(mlir::OpPassManager&, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int, mlir::PassInstrumentor*, mlir::PassInstrumentation::PipelineParentInfo const*) (./mlir-opt+0xa1c3364)
#21 0x00005563025ad0fa mlir::PassManager::runPasses(mlir::Operation*, mlir::AnalysisManager) (./mlir-opt+0xa1ca0fa)
#22 0x00005563025aca5d mlir::PassManager::run(mlir::Operation*) (./mlir-opt+0xa1c9a5d)
#23 0x00005562fa45158f performActions(llvm::raw_ostream&, std::shared_ptr const&, mlir::MLIRContext*, mlir::MlirOptMainConfig const&) MlirOptMain.cpp:0:0
#24 0x00005562fa450761 llvm::LogicalResult llvm::function_ref>, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>::callback_fn>, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&)::$_0>(long, std::unique_ptr>, llvm::MemoryBufferRef const&, llvm::raw_ostream&) MlirOptMain.cpp:0:0
#25 0x00005563028ffec6 mlir::splitAndProcessBuffer(std::unique_ptr>, llvm::function_ref>, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>, llvm::raw_ostream&, llvm::StringRef, llvm::StringRef) (./mlir-opt+0xa51cec6)
#26 0x00005562fa446ba6 mlir::MlirOptMain(llvm::raw_ostream&, std::unique_ptr>, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&) (./mlir-opt+0x2063ba6)
#27 0x00005562fa446f7a mlir::MlirOptMain(int, char**, llvm::StringRef, llvm::StringRef, mlir::DialectRegistry&) (./mlir-opt+0x2063f7a)
#28 0x00005562fa4471eb mlir::MlirOptMain(int, char**, llvm::StringRef, mlir::DialectRegistry&) (./mlir-opt+0x20641eb)
#29 0x00005562fa38b7cd main (./mlir-opt+0x1fa87cd)
#30 0x00007f3786776d90 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#31 0x00007f3786776e40 __libc_start_main (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#32 0x00005562fa38b325 _start (./mlir-opt+0x1fa8325)
Aborted (core dumped)
```

Contributor guide

Open the contributing guide

Research direction

Start with MLIR's AffineLoadOp::fold, which the stack trace identifies as the failing entry point, and reproduce the issue using the supplied test case with mlir-opt test.mlir -canonicalize. Add a regression test for the zero-sized constant memref case; done means canonicalization no longer hits the ElementsAttr assertion and the test passes.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.