Add an EmitC-owned preparation pass,
`mlgo-scalarize-single-element-tensor-return`, that rewrites private
functions returning a statically-shaped ranked tensor with exactly one
element into functions returning the element type directly.
Assisted-by: Codex (refine implementation + tests). I reviewed all code
and tests before submission.
## Example
Before:
```mlir
func.func private @rank1(%arg0: tensor<1xi64>) -> tensor<1xi64> {
return %arg0 : tensor<1xi64>
}
```
After:
```mlir
func.func private @rank1(%arg0: tensor<1xi64>) -> i64 {
%c0 = arith.constant 0 : index
%0 = tensor.extract %arg0[%c0] : tensor<1xi64>
return %0 : i64
}
```
Rank-0 tensors are handled similarly with `tensor.extract %t[]`, which
canonicalization/constant-folding can simplify further.
## Motivation
`tosa-converter-for-flite` may produce functions that return
tensor-wrapped scalars. These values are semantically scalars, but
remain packaged as single-element tensors in function signatures. This
becomes problematic later in lowering, especially for EmitC, where such
returns eventually bufferize to MemRef arrays and fail with:
```bash
error: 'emitc.func' op cannot return array type
```
This patch fixes the issue while the IR is still in `func`/`tensor`
form, where the scalar intent remains explicit and the transform can
stay semantics-driven.
## Scope
The transform is intentionally conservative: it only handles private
definitions with one single-element ranked tensor result, and it blocks
on public callers, non-call symbol users, unsupported callers, and
recursive cycles.
## Analysis
The pass runs at `ModuleOp` scope because legality depends on transitive
private call users. It first computes module-level scalarization
analysis from a `SymbolUserMap` snapshot, then rewrites only the
precomputed rewritable functions.
## Rewrite
Each rewritten function gets tensor.extract inserted before
`func.return`, its result type is updated with `funcOp.setType(...)`,
and direct `func.call` users are adjusted.
Unchanged private callers that still need the original tensor type are
adapted with `tensor.from_elements`.