| Issue |
203762
|
| Summary |
[MLIR][Affine] UNREACHABLE "unexpected op" in affine-loop-fusion getMemRef() with memref.copy inside affine.for
|
| Labels |
mlir
|
| Assignees |
|
| Reporter |
Kiritobl
|
#### Version
git commit hash: b3df06651
#### Bug Description
`mlir-opt --affine-loop-fusion` crashes with **`llvm_unreachable("unexpected op")`** when building the `MemRefDependenceGraph` for fusion analysis. The crash occurs at `Utils.cpp:256` inside `getMemRef()`, which is called from `mayDependence()` during dependence graph initialization.
#### Crash Chain & Root Cause
**Location**: `mlir/lib/Dialect/Affine/Analysis/Utils.cpp:256`
Crash flow:
```
affine-loop-fusion pass
→ LoopFusion::runOnOperation()
→ mlir::detail::walk() over all functions with affine.for
→ MemRefDependenceGraph::init()
→ addNodeToMDG()
→ LoopNestStateCollector::collect()
→ memref.copy → hasEffect<MemoryEffects::Read>() → memrefLoads ←
→ memref.copy → hasEffect<MemoryEffects::Write>() → memrefStores ← (same op in both lists)
→ mayDependence()
→ hasNonAffineDep() lambda
→ getMemRef(memref.copy) // UNREACHABLE: not handled
```
#### Steps to Reproduce
Run the following command with the provided reproducer MLIR:
```bash
mlir-opt --affine-loop-fusion reproducer.mlir -o /dev/null
```
#### Reproducer (`reproducer.mlir`)
```mlir
// BUG-3: Minimal reproducer for affine-loop-fusion crash
// Crash: llvm_unreachable("unexpected op") at Utils.cpp:256 in getMemRef()
//
// Root cause: memref.copy has both Read and Write memory effects on memrefs.
// LoopNestStateCollector classifies it into BOTH memrefLoads and memrefStores.
// Later, mayDependence() calls getMemRef() on it, but getMemRef() only handles
// memref::LoadOp, AffineReadOpInterface, memref::StoreOp, AffineWriteOpInterface.
// memref.copy does not match any of these → llvm_unreachable("unexpected op").
//
// Pipeline: --affine-loop-fusion (single pass, no preprocessing needed)
module {
func.func @minimal_bug3() {
%mem = memref.alloca() : memref<10xi32>
%mem2 = memref.alloca() : memref<10xi32>
%c0_i32 = arith.constant 0 : i32
// affine.for #1: contains memref.copy (has read+write memory effects on memrefs)
// which gets classified into BOTH memrefLoads and memrefStores
affine.for %i = 0 to 10 {
memref.copy %mem, %mem2 : memref<10xi32> to memref<10xi32>
affine.store %c0_i32, %mem[%i] : memref<10xi32>
}
// affine.for #2: reads the same memref, creating a dependence pair
// between the two affine.for nodes that triggers mayDependence()
affine.for %j = 0 to 10 {
%v = affine.load %mem[%j] : memref<10xi32>
}
return
}
}
```
#### Stack Dump
```text
UNREACHABLE executed at .../mlir/lib/Dialect/Affine/Analysis/Utils.cpp:256!
Stack dump:
0. Program arguments: mlir-opt --affine-loop-fusion reproducer.mlir -o /dev/null
#0 0x00005e5967e97518 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (mlir-opt+0x1f8c518)
#1 0x00005e5967e943b5 llvm::sys::RunSignalHandlers() (mlir-opt+0x1f893b5)
#2 0x00005e5967e98641 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#3 0x00007603ef242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007603ef2969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
#5 0x00007603ef2969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
#6 0x00007603ef2969fc pthread_kill ./nptl/pthread_kill.c:89:10
#7 0x00007603ef242476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
#8 0x00007603ef2287f3 abort ./stdlib/abort.c:81:7
#9 0x00005e5967e7df5f (mlir-opt+0x1f72f5f)
#10 0x00005e596eb9a42c (mlir-opt+0x8c8f42c)
#11 0x00005e596eb82ec6 mlir::affine::MemRefDependenceGraph::init(bool) (mlir-opt+0x8c77ec6)
#12 0x00005e596e8954f6 void llvm::function_ref<void (mlir::Operation*)>::callback_fn<(anonymous namespace)::LoopFusion::runOnOperation()::$_0>(long, mlir::Operation*) LoopFusion.cpp:0:0
#13 0x00005e5967f5e2ce void mlir::detail::walk<mlir::ForwardIterator>(mlir::Operation*, llvm::function_ref<void (mlir::Operation*)>, mlir::WalkOrder) (mlir-opt+0x20532ce)
#14 0x00005e596e892eba (anonymous namespace)::LoopFusion::runOnOperation() LoopFusion.cpp:0:0
#15 0x00005e59702f69c8 mlir::detail::OpToOpPassAdaptor::run(mlir::Pass*, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int) (mlir-opt+0xa3eb9c8)
#16 0x00005e59702f77a4 mlir::detail::OpToOpPassAdaptor::runPipeline(mlir::OpPassManager&, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int, mlir::PassInstrumentor*, mlir::PassInstrumentation::PipelineParentInfo const*) (mlir-opt+0xa3ec7a4)
#17 0x00005e59702feb32 mlir::PassManager::runPasses(mlir::Operation*, mlir::AnalysisManager) (mlir-opt+0xa3f3b32)
#18 0x00005e59702fe20a mlir::PassManager::run(mlir::Operation*) (mlir-opt+0xa3f320a)
#19 0x00005e5967f4af70 performActions(llvm::raw_ostream&, std::shared_ptr<llvm::SourceMgr> const&, mlir::MLIRContext*, mlir::MlirOptMainConfig const&) MlirOptMain.cpp:0:0
#20 0x00005e5967f4a2e8 llvm::LogicalResult llvm::function_ref<llvm::LogicalResult (std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>::callback_fn<mlir::MlirOptMain(llvm::raw_ostream&, std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&)::$_0>(long, std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, llvm::MemoryBufferRef const&, llvm::raw_ostream&) MlirOptMain.cpp:0:0
#21 0x00005e5970640145 mlir::splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, llvm::function_ref<llvm::LogicalResult (std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>, llvm::raw_ostream&, llvm::StringRef, llvm::StringRef) (mlir-opt+0xa735145)
#22 0x00005e5967f3f8e5 mlir::MlirOptMain(llvm::raw_ostream&, std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&) (mlir-opt+0x20348e5)
#23 0x00005e5967f3fcb1 mlir::MlirOptMain(int, char**, llvm::StringRef, llvm::StringRef, mlir::DialectRegistry&) (mlir-opt+0x2034cb1)
#24 0x00005e5967f3ff1b mlir::MlirOptMain(int, char**, llvm::StringRef, mlir::DialectRegistry&) (mlir-opt+0x2034f1b)
#25 0x00005e5967e7d632 main (mlir-opt+0x1f72632)
#26 0x00007603ef229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#27 0x00007603ef229e40 call_init ./csu/../csu/libc-start.c:128:20
#28 0x00007603ef229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#29 0x00005e5967e7d165 _start (mlir-opt+0x1f72165)
/bin/bash: line 1: 1462843 Aborted (core dumped) ../../../llvm-project/build/bin/mlir-opt --affine-loop-fusion minimal_BUG-3.mlir -o /dev/null 2>&1
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs