[MLIR][Affine] Crash: `affine-scalrep` replaces a load with another load it has already scheduled for erasure
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
`loadCSE` in `mlir/lib/Dialect/Affine/Utils/Utils.cpp` replaces a load with an equivalent dominating load and records the replaced one in `loadOpsToErase`, which `affineScalarReplace` drains after the whole walk. The candidate search never asks whether the load it is about to replace *with* is itself already in that list, so a later load can be pointed at an operation that is about to be destroyed.
## Reproducer
### small.mlir
```mlir
module {
memref.global "private" @g : memref<4xi64> = dense<[1, 2, 3, 4]>
func.func @f() -> index {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
%c7 = arith.constant 7 : i64
%m = memref.get_global @g : memref<4xi64>
%a = affine.load %m[3] : memref<4xi64>
affine.store %c7, %m[0] : memref<4xi64>
%b = affine.load %m[3] : memref<4xi64>
%s = scf.for %i = %c0 to %c2 step %c1 iter_args(%acc = %c0) -> (index) {
%c = affine.load %m[3] : memref<4xi64>
%x = index.castu %c : i64 to index
%y = index.add %acc, %x
scf.yield %y : index
}
%p = index.castu %a : i64 to index
%q = index.castu %b : i64 to index
%r = index.add %s, %p
%t = index.add %r, %q
return %t : index
}
}
```
### To reproduce:
```
mlir-opt small.mlir --affine-scalrep -o /dev/null
```
### Crash:
```
small.mlir:11:10: error: 'affine.load' op operation destroyed but still has uses
%b = affine.load %m[3] : memref<4xi64>
^
small.mlir:11:10: note: see current operation: %0 = "affine.load"(<>) <{map = affine_map<() -> (3)>}> : (memref<4xi64>) -> i64
small.mlir:14:12: note: - use: %12 = "index.castu"(<>) : (i64) -> index
%x = index.castu %c : i64 to index
^
LLVM ERROR: operation destroyed but still has uses
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 small.mlir --affine-scalrep -o /dev/null
#0 0x0000aaaacf51a308 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:935:3
#1 0x0000aaaacf51727c llvm::sys::RunSignalHandlers() /data/x27zhou/compiler-nightly/src/llvm-project/llvm/lib/Support/Signals.cpp:109:18
#2 0x0000aaaacf517948 SignalHandler(int, siginfo_t*, void*) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:474:14
#3 0x0000ffff951ad7dc (linux-vdso.so.1+0x7dc)
#4 0x0000ffff94d12008 (/lib/aarch64-linux-gnu/libc.so.6+0x82008)
#5 0x0000ffff94cca83c gsignal (/lib/aarch64-linux-gnu/libc.so.6+0x3a83c)
#6 0x0000ffff94cb7134 abort (/lib/aarch64-linux-gnu/libc.so.6+0x27134)
#7 0x0000aaaacf4ff150 llvm::report_fatal_error(llvm::StringRef, bool) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/lib/Support/ErrorHandling.cpp:99:68
#8 0x0000aaaacf4ff1d4 (/data/x27zhou/compiler-nightly/build/mlir/bin/mlir-opt+0x210f1d4)
#9 0x0000aaaad72c06c0 llvm::detail::indexed_accessor_range_base::iterator std::__find_if::iterator, __gnu_cxx::__ops::_Iter_negate >(llvm::detail::indexed_accessor_range_base::iterator, llvm::detail::indexed_accessor_range_base::iterator, __gnu_cxx::__ops::_Iter_negate, std::random_access_iterator_tag) /usr/include/c++/11/bits/stl_algobase.h:2067:27
#10 0x0000aaaad72c06c0 llvm::detail::indexed_accessor_range_base::iterator std::__find_if_not::iterator, __gnu_cxx::__ops::_Iter_pred >(llvm::detail::indexed_accessor_range_base::iterator, llvm::detail::indexed_accessor_range_base::iterator, __gnu_cxx::__ops::_Iter_pred) /usr/include/c++/11/bits/stl_algo.h:106:28
#11 0x0000aaaad72c06c0 llvm::detail::indexed_accessor_range_base::iterator std::find_if_not::iterator, mlir::ResultRange::use_empty() const::'lambda'(mlir::OpResult)>(llvm::detail::indexed_accessor_range_base::iterator, llvm::detail::indexed_accessor_range_base::iterator, mlir::ResultRange::use_empty() const::'lambda'(mlir::OpResult)) /usr/include/c++/11/bits/stl_algo.h:513:32
#12 0x0000aaaad72c06c0 bool std::all_of::iterator, mlir::ResultRange::use_empty() const::'lambda'(mlir::OpResult)>(llvm::detail::indexed_accessor_range_base::iterator, llvm::detail::indexed_accessor_range_base::iterator, mlir::ResultRange::use_empty() const::'lambda'(mlir::OpResult)) /usr/include/c++/11/bits/stl_algo.h:453:40
#13 0x0000aaaad72c06c0 bool llvm::all_of(mlir::ResultRange const&, mlir::ResultRange::use_empty() const::'lambda'(mlir::OpResult)) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1740:21
#14 0x0000aaaad72c06c0 mlir::ResultRange::use_empty() const /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/ValueRange.h:279:24
#15 0x0000aaaad72c06c0 mlir::Operation::use_empty() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/Operation.h:877:51
#16 0x0000aaaad72c06c0 mlir::Operation::~Operation() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/IR/Operation.cpp:178:17
#17 0x0000aaaad72c0724 mlir::Operation::destroy() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/IR/Operation.cpp:208:69
#18 0x0000aaaad5636d34 mlir::affine::affineScalarReplace(mlir::func::FuncOp, mlir::DominanceInfo&, mlir::PostDominanceInfo&, mlir::AliasAnalysis&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Dialect/Affine/Utils/Utils.cpp:1110:19
#19 0x0000aaaad6fbd320 operator() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:612:33
#20 0x0000aaaad6fbd320 callback_fn > /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:52
#21 0x0000aaaad6fbd320 llvm::function_ref::operator()() const /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12
#22 0x0000aaaad6fbd320 void mlir::MLIRContext::executeAction(llvm::function_ref, llvm::ArrayRef, mlir::Pass&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/MLIRContext.h:296:15
#23 0x0000aaaad6fbd320 mlir::detail::OpToOpPassAdaptor::run(mlir::Pass*, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:606:57
#24 0x0000aaaad6fbd5dc mlir::detail::OpToOpPassAdaptor::runPipeline(mlir::OpPassManager&, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int, mlir::PassInstrumentor*, mlir::PassInstrumentation::PipelineParentInfo const*) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:688:5
#25 0x0000aaaad6fbde64 mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool)::'lambda12'(mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool)::OpPMInfo&)::operator()(mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool)::OpPMInfo&) const /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:1004:5
#26 0x0000aaaad6fbc360 operator++ /usr/include/c++/11/bits/stl_iterator.h:1054:2
#27 0x0000aaaad6fbc360 failableParallelForEach<__gnu_cxx::__normal_iterator >, mlir::parallelForEach<__gnu_cxx::__normal_iterator >, mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool):: >(mlir::MLIRContext*, __gnu_cxx::__normal_iterator >, __gnu_cxx::__normal_iterator >, mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool)::&&):: > /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/Threading.h:45:26
#28 0x0000aaaad6fbc360 parallelForEach<__gnu_cxx::__normal_iterator >, mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool):: > /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/Threading.h:119:32
#29 0x0000aaaad6fbc360 parallelForEach&, mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool):: > /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/Threading.h:131:18
#30 0x0000aaaad6fbc360 mlir::detail::OpToOpPassAdaptor::runOnOperationAsyncImpl(bool) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:991:18
#31 0x0000aaaad6fbd1f4 operator() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:613:24
#32 0x0000aaaad6fbd1f4 callback_fn > /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:52
#33 0x0000aaaad6fbd1f4 llvm::function_ref::operator()() const /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12
#34 0x0000aaaad6fbd1f4 void mlir::MLIRContext::executeAction(llvm::function_ref, llvm::ArrayRef, mlir::Pass&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/IR/MLIRContext.h:296:15
#35 0x0000aaaad6fbd1f4 mlir::detail::OpToOpPassAdaptor::run(mlir::Pass*, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:606:57
#36 0x0000aaaad6fbd5dc mlir::detail::OpToOpPassAdaptor::runPipeline(mlir::OpPassManager&, mlir::Operation*, mlir::AnalysisManager, bool, unsigned int, mlir::PassInstrumentor*, mlir::PassInstrumentation::PipelineParentInfo const*) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:688:5
#37 0x0000aaaad6fc03b4 mlir::PassManager::run(mlir::Operation*) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Pass/Pass.cpp:1102:69
#38 0x0000aaaacf5c65dc performActions(llvm::raw_ostream&, std::shared_ptr const&, mlir::MLIRContext*, mlir::MlirOptMainConfig const&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:596:3
#39 0x0000aaaacf5c6f00 processBuffer /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:686:26
#40 0x0000aaaacf5c6f00 operator() /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:784:25
#41 0x0000aaaacf5c6f00 llvm::LogicalResult llvm::function_ref >, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>::callback_fn >, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&)::'lambda'(std::unique_ptr >, llvm::MemoryBufferRef, llvm::raw_ostream&)>(long, std::unique_ptr >, llvm::MemoryBufferRef const&, llvm::raw_ostream&) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:52
#42 0x0000aaaad7308308 llvm::function_ref >, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>::operator()(std::unique_ptr >, llvm::MemoryBufferRef const&, llvm::raw_ostream&) const /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12
#43 0x0000aaaad7308308 mlir::splitAndProcessBuffer(std::unique_ptr >, llvm::function_ref >, llvm::MemoryBufferRef const&, llvm::raw_ostream&)>, llvm::raw_ostream&, llvm::StringRef, llvm::StringRef) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Support/ToolUtilities.cpp:30:30
#44 0x0000aaaacf5c0428 mlir::MlirOptMain(llvm::raw_ostream&, std::unique_ptr >, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&) (.part.0) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:789:47
#45 0x0000aaaacf5c7510 mlir::MlirOptMain(llvm::raw_ostream&, std::unique_ptr >, mlir::DialectRegistry&, mlir::MlirOptMainConfig const&) /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/Support/LogicalResult.h:62:42
#46 0x0000aaaacf5c7510 mlir::MlirOptMain(int, char**, llvm::StringRef, llvm::StringRef, mlir::DialectRegistry&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:835:13
#47 0x0000aaaacf5c76c0 mlir::MlirOptMain(int, char**, llvm::StringRef, mlir::DialectRegistry&) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:851:21
#48 0x0000aaaacf496f2c mlir::asMainReturnCode(llvm::LogicalResult) /data/x27zhou/compiler-nightly/src/llvm-project/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h:436:24
#49 0x0000aaaacf496f2c main /data/x27zhou/compiler-nightly/src/llvm-project/mlir/tools/mlir-opt/mlir-opt.cpp:345:32
#50 0x0000ffff94cb7400 (/lib/aarch64-linux-gnu/libc.so.6+0x27400)
#51 0x0000ffff94cb74d8 __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x274d8)
#52 0x0000aaaacf4fe970 _start (/data/x27zhou/compiler-nightly/build/mlir/bin/mlir-opt+0x210e970)
```
Contributor guide
Research direction
Start in mlir/lib/Dialect/Affine/Utils/Utils.cpp, focusing on loadCSE and affineScalarReplace, then run mlir-opt small.mlir --affine-scalrep -o /dev/null with the reproducer. Ensure the pass no longer leaves uses pointing to an operation scheduled for erasure, and add regression coverage for this crash if the surrounding test structure identifies a suitable location.
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
- Clearly specified
- Newbie friendliness
- 76/100