James Newling 0f35244816
[mlir][vector] shape_cast(constant) -> constant fold for non-splats (#145539)
The folder `shape_cast(splat constant) -> splat constant` was first
introduced
[here](36480657d8 (diff-484cea976e0c96459027c951733bf2d22d34c5a0c0de6f577069870ef4588983R2600))
(Nov 2020). In that commit there is a comment to _Only handle splat for
now_. Based on that I assume the intention was to, at a later time,
support a general `shape_cast(constant) -> constant` folder. That is
what this PR does

One minor downside: It is possible with this folder end up with, instead
of 1 large constant and 1 shape_cast, 2 large constants:

```mlir
  func.func @foo() -> (vector<4xi32>, vector<2x2xi32>) {
    %cst = arith.constant dense<[1, 2, 3, 4]> : vector<4xi32> # 'large' constant 1
    %0 = vector.shape_cast %cst : vector<4xi32> to vector<2x2xi32>
    return %cst, %0 : vector<4xi32>, vector<2x2xi32>
  }
```
gets folded with this new folder to 

```mlir
   func.func @foo() -> (vector<4xi32>, vector<2x2xi32>) {
    %cst = arith.constant dense<[1, 2, 3, 4]> : vector<4xi32> # 'large' constant 1
    %cst_0 = arith.constant dense<[[1, 2], [3, 4]]> : vector<2x2xi32> # 'large' constant 2
    return %cst, %cst_0 : vector<4xi32>, vector<2x2xi32>
  }
```
Notes on the above case:
1) This only effects the textual IR, the actual values share the same
context storage (I've verified this by checking pointer values in the
`DenseIntOrFPElementsAttrStorage`
[constructor](da5c442550/mlir/lib/IR/AttributeDetail.h (L59)))
so no compile-time memory overhead to this folding. At the LLVM
IR level the constant is shared, too.
2) This only happens when the pre-folded constant cannot be dead code
eliminated (i.e. when it has 2+ uses) which I don't think is common.
2025-07-31 12:12:53 -07:00
..

Multi-Level Intermediate Representation

See https://mlir.llvm.org/ for more information.