Address crash in iree-reduce with complex tensors (#24674)
See issue https://github.com/iree-org/iree/issues/24673. Details are
repeated here.
`iree-reduce` crashes in `reduceLinalgOnTensorsDelta` when it tries to
replace a `linalg` op that produces a **complex**-typed tensor. The
strategy builds a zero constant via `Builder::getZeroAttr(elementType)`,
which returns a **null** attribute for `complex` (it only supports
int/index/float). Creating an `arith.constant` from the null attribute
aborts the process.
The proposed fix simply does an early-out if the type is not int, float,
or index instead of crashing.
Repro:
`interesting.sh`
```bash
#!/bin/bash
# Interestingness oracle for iree-reduce.
#
# A reduced candidate is "interesting" (exit 0) only while it still contains the
# complex-typed linalg.generic (identified by the complex.create in its body).
# This keeps the reducer from deleting the op via an earlier strategy, so it
# reaches reduceLinalgOnTensorsDelta with the complex op still present.
grep -q "complex.create" "$1"
```
`complex_repro.mlir`
```
// Minimal reproducer for the iree-reduce crash in reduceLinalgOnTensorsDelta.
//
// The linalg.generic writes a complex<f32> tensor. When the reducer decides to
// replace this op with a linalg.fill of a zero constant, it calls
// Builder::getZeroAttr(complex<f32>), which returns a null attribute. Building
// an arith.constant from that null attribute crashes ("Failed to infer result
// type(s)").
//
// The op survives the earlier reduction strategies because the interestingness
// check (interesting.sh) requires "complex.create" to remain present, so the
// reducer reaches reduceLinalgOnTensorsDelta with the complex op still in place.
func.func @main(%arg0: tensor<4xf32>) -> tensor<4xcomplex<f32>> {
%empty = tensor.empty() : tensor<4xcomplex<f32>>
%0 = linalg.generic {
indexing_maps = [affine_map<(d0) -> (d0)>, affine_map<(d0) -> (d0)>],
iterator_types = ["parallel"]
} ins(%arg0 : tensor<4xf32>) outs(%empty : tensor<4xcomplex<f32>>) {
^bb0(%in: f32, %out: complex<f32>):
%c = complex.create %in, %in : complex<f32>
linalg.yield %c : complex<f32>
} -> tensor<4xcomplex<f32>>
return %0 : tensor<4xcomplex<f32>>
}
```
Run using:
```bash
chmod +x interesting.sh
iree-reduce ./interesting.sh ./complex_repro.mlir -o reduced.mlir
```
Crashes with:
```
LLVM ERROR: Failed to infer result type(s):
"arith.constant"(...) {} : () -> ( ??? )
Please report issues to https://github.com/iree-org/iree/issues and include the crash backtrace.
Stack dump:
0. Program arguments: ../../fix-undef-global-hoist/iree-compiler/tools/iree-reduce ./interesting.sh ./complex_repro.mlir -o reduced.mlir
#0 0x00007aa82ee7cf5b llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) fix-undef-global-hoist/iree/third_party/llvm-project/llvm/lib/Support/Unix/Signals.inc:881:13
#1 0x00007aa82ee7ab83 llvm::sys::RunSignalHandlers() fix-undef-global-hoist/iree/third_party/llvm-project/llvm/lib/Support/Signals.cpp:109:18
#2 0x00007aa82ee7de71 SignalHandler(int, siginfo_t*, void*) fix-undef-global-hoist/iree/third_party/llvm-project/llvm/lib/Support/Unix/Signals.inc:448:38
#3 0x00007aa828e45330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#4 0x00007aa828e9eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
#5 0x00007aa828e9eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
#6 0x00007aa828e9eb2c pthread_kill ./nptl/pthread_kill.c:89:10
#7 0x00007aa828e4527e raise ./signal/../sysdeps/posix/raise.c:27:6
#8 0x00007aa828e288ff abort ./stdlib/abort.c:81:7
#9 0x00007aa82ee0850b llvm::report_fatal_error(llvm::Twine const&, bool) fix-undef-global-hoist/iree/third_party/llvm-project/llvm/lib/Support/ErrorHandling.cpp:137:5
#10 0x00007aa82ee0858e (fix-undef-global-hoist/iree-compiler/lib/libIREECompiler.so+0x580858e)
#11 0x00007aa837dabc21 (fix-undef-global-hoist/iree-compiler/lib/libIREECompiler.so+0xe7abc21)
#12 0x00007aa834c50cc1 llvm::SmallVectorTemplateCommon<mlir::Type, void>::begin() fix-undef-global-hoist/iree/third_party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:276:45
#13 0x00007aa834c50cc1 llvm::SmallVectorTemplateCommon<mlir::Type, void>::end() fix-undef-global-hoist/iree/third_party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:278:27
#14 0x00007aa834c50cc1 llvm::SmallVector<mlir::Type, 2u>::~SmallVector() fix-undef-global-hoist/iree/third_party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:1242:46
#15 0x00007aa834c50cc1 mlir::arith::ConstantOp::build(mlir::OpBuilder&, mlir::OperationState&, mlir::TypedAttr) fix-undef-global-hoist/iree-compiler/llvm-project/tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.cpp.inc:4379:1
#16 0x00007aa834c131be mlir::arith::ConstantOp::create(mlir::OpBuilder&, mlir::Location, mlir::TypedAttr) fix-undef-global-hoist/iree-compiler/llvm-project/tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.cpp.inc:4384:55
#17 0x00007aa8337db6af mlir::Operation::getInlineOpResult(unsigned int) fix-undef-global-hoist/iree/third_party/llvm-project/mlir/include/mlir/IR/Operation.h:1035:61
#18 0x00007aa8337db6af mlir::Operation::getOpResultImpl(unsigned int) fix-undef-global-hoist/iree/third_party/llvm-project/mlir/include/mlir/IR/Operation.h:1045:14
#19 0x00007aa8337db6af mlir::Operation::getResult(unsigned int) fix-undef-global-hoist/iree/third_party/llvm-project/mlir/include/mlir/IR/Operation.h:432:54
#20 0x00007aa8337db6af mlir::OpTrait::OneTypedResult<mlir::Type>::Impl<mlir::arith::ConstantOp>::getResult() fix-undef-global-hoist/iree/third_party/llvm-project/mlir/include/mlir/IR/OpDefinition.h:708:33
#21 0x00007aa8337db6af mlir::OpTrait::OneTypedResult<mlir::Type>::Impl<mlir::arith::ConstantOp>::operator mlir::Value() fix-undef-global-hoist/iree/third_party/llvm-project/mlir/include/mlir/IR/OpDefinition.h:713:54
#22 0x00007aa8337db6af mlir::iree_compiler::Reducer::reduceLinalgOnTensorsDelta(mlir::iree_compiler::Reducer::ChunkManager&, mlir::iree_compiler::Reducer::WorkItem&) fix-undef-global-hoist/iree/compiler/src/iree/compiler/Reducer/Strategies/ReduceLinalgOnTensorsDelta.cpp:114:18
#23 0x00007aa834d464dd mlir::iree_compiler::Reducer::Delta::checkChunk(mlir::iree_compiler::Reducer::Chunk, llvm::function_ref<void (mlir::iree_compiler::Reducer::ChunkManager&, mlir::iree_compiler::Reducer::WorkItem&)>, llvm::ArrayRef<mlir::iree_compiler::Reducer::Chunk>, llvm::DenseSet<mlir::iree_compiler::Reducer::Chunk, llvm::DenseMapInfo<mlir::iree_compiler::Reducer::Chunk, void>>&) fix-undef-global-hoist/iree/compiler/src/iree/compiler/Reducer/Framework/Delta.cpp:39:8
#24 0x00007aa834d46aa7 llvm::LogicalResult::failed() const fix-undef-global-hoist/iree/third_party/llvm-project/llvm/include/llvm/Support/LogicalResult.h:43:43
#25 0x00007aa834d46aa7 llvm::failed(llvm::LogicalResult) fix-undef-global-hoist/iree/third_party/llvm-project/llvm/include/llvm/Support/LogicalResult.h:71:58
#26 0x00007aa834d46aa7 mlir::iree_compiler::Reducer::Delta::runDeltaPass(llvm::function_ref<void (mlir::iree_compiler::Reducer::ChunkManager&, mlir::iree_compiler::Reducer::WorkItem&)>, llvm::StringRef) fix-undef-global-hoist/iree/compiler/src/iree/compiler/Reducer/Framework/Delta.cpp:105:11
#27 0x00007aa82f5d68ea mlir::iree_compiler::Reducer::ireeRunReducingStrategies(mlir::OwningOpRef<mlir::Operation*>, mlir::iree_compiler::Reducer::ReducerConfig&) fix-undef-global-hoist/iree/compiler/src/iree/compiler/Reducer/iree_reduce_lib.cc:39:9
#28 0x00007aa82edba149 ireeReduceMainFromCL(int, char**, mlir::MLIRContext&) fix-undef-global-hoist/iree/compiler/src/iree/compiler/API/Internal/IREEReduceToolEntryPoint.cpp:102:26
#29 0x00007aa82edba149 ireeReduceRunMain fix-undef-global-hoist/iree/compiler/src/iree/compiler/API/Internal/IREEReduceToolEntryPoint.cpp:134:7
#30 0x00007aa828e2a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#31 0x00007aa828e2a28b call_init ./csu/../csu/libc-start.c:128:20
#32 0x00007aa828e2a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#33 0x00005a84cb2e26e5 _start (../../fix-undef-global-hoist/iree-compiler/tools/iree-reduce+0x16e5)
```
Signed-off-by: Paul Stark <paul.stark@cdprojektred.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>diff --git a/compiler/src/iree/compiler/Reducer/Strategies/ReduceLinalgOnTensorsDelta.cpp b/compiler/src/iree/compiler/Reducer/Strategies/ReduceLinalgOnTensorsDelta.cpp
index 4d66462..d427fac 100644
--- a/compiler/src/iree/compiler/Reducer/Strategies/ReduceLinalgOnTensorsDelta.cpp
+++ b/compiler/src/iree/compiler/Reducer/Strategies/ReduceLinalgOnTensorsDelta.cpp
@@ -109,6 +109,12 @@
}
Type elType = outType.getElementType();
+ // Builder::getZeroAttr only supports int/index/float element types. For
+ // other element types (e.g. complex) we cannot synthesize a zero constant,
+ // so leave the op untouched rather than crashing.
+ if (!elType.isIntOrIndexOrFloat()) {
+ continue;
+ }
// Build a constant 0 of the type.
builder.setInsertionPoint(linalgOp);
Value zero = arith::ConstantOp::create(builder, linalgOp.getLoc(),