[mlir][vector] Lower vector.gather with delinearization approach (#184706)
The old implementation did not handle n-D memref correctly, which leads
to wrong access. E.g.,
```
func.func @gather_memref_2d(%base: memref<?x?xf32>, %v: vector<2x3xindex>, %mask: vector<2x3xi1>, %pass_thru: vector<2x3xf32>) -> vector<2x3xf32> {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%0 = vector.gather %base[%c0, %c1][%v], %mask, %pass_thru : memref<?x?xf32>, vector<2x3xindex>, vector<2x3xi1>, vector<2x3xf32> into vector<2x3xf32>
return %0 : vector<2x3xf32>
}
```
is lowered to
```
func.func @gather_memref_2d(%arg0: memref<?x?xf32>, %arg1: vector<2x3xindex>, %arg2: vector<2x3xi1>, %arg3: vector<2x3xf32>) -> vector<2x3xf32> {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%0 = ub.poison : vector<2x3xf32>
%1 = vector.extract %arg3[0] : vector<3xf32> from vector<2x3xf32>
%2 = vector.extract %arg2[0, 0] : i1 from vector<2x3xi1>
%3 = vector.extract %arg1[0, 0] : index from vector<2x3xindex>
%4 = arith.addi %3, %c1 : index
%5 = scf.if %2 -> (vector<3xf32>) {
%29 = vector.load %arg0[%c0, %4] : memref<?x?xf32>, vector<1xf32>
%30 = vector.extract %29[0] : f32 from vector<1xf32>
%31 = vector.insert %30, %1 [0] : f32 into vector<3xf32>
scf.yield %31 : vector<3xf32>
} else {
scf.yield %1 : vector<3xf32>
}
// ...
```
The revision fixes it by by using `linearize(baseOffsets) + gatherIndex`
followed by `delinearize` to recover correct `n-D` load indices. This is
applied unconditionally for all rank > 1 memrefs.
Note that it enables the cases with strideds because we use
delinearization approach.
---------
Signed-off-by: hanhanW <hanhan0912@gmail.com>