[Codegen][CPU] Drop the ACC stride from the inner_tiled ukernel ABI. (#24652)

New bottom of the LLVMCPU C-ukernel stack.

The ACC stride threaded to the C ukernels is always a compile-time
constant
equal to one intrinsic's ACC fragment size (the data-tiled ACC tile is
contiguous), so it folds to a constant after inlining and carries no
information the intrinsic-specific ukernel doesn't already encode. This
drops
it:

- `IREECPUAttrs.cpp`: remove `getAccInnermostCrossIntrinsicDim`; build
the
`ukernel.generic` with `num_strided_outer_dims=0`, so all shaped
operands
  (LHS, RHS, ACC) lower to `(base, offset)` only.
- Both seed ukernel `.c` signatures lose the `acc_stride` parameter.

This addresses review feedback on the now-merged #24569 / #24571 (why
pass a
per-operand `strided_dims` array, and why pass an ACC stride that's
statically
known). It makes the three operands uniform and removes the
`getAccInnermostCrossIntrinsicDim` swizzle machinery.

Verified: the lowered `llvm.call` to the ukernel now has no stride
argument,
and the ukernel lit tests (`lower_inner_tiled_to_bitcode_ukernel*`,
`e2e_inner_tiled_pipeline`, `select_ukernel`) pass.

Progress towards https://github.com/iree-org/iree/issues/24574.

Signed-off-by: Benoit Jacob <jacob.benoit.1@gmail.com>
diff --git a/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16.c b/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16.c
index 978c478..c7a5728 100644
--- a/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16.c
+++ b/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16.c
@@ -22,8 +22,9 @@
 // template.
 //
 // ABI: each shaped operand is passed as (base pointer, element offset) so the
-// caller doesn't need a GEP before the call; the accumulator additionally
-// gets the element stride of its innermost cross-intrinsic (N) dimension.
+// caller doesn't need a GEP before the call. No strides are passed: the ACC
+// tile is contiguous, so the ukernel addresses each intrinsic's fragment from
+// `intrinsics_{m,n}` and its own fixed fragment size.
 //
 // NOTE (seed scaffolding): this initial seed has a stub body. It exists so
 // that the surrounding *framework* -- bitcode build, embedding,
@@ -33,16 +34,14 @@
 IREE_UK_ALWAYS_INLINE
 void iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16(
     const uint16_t *lhs_base, int64_t lhs_offset, const uint16_t *rhs_base,
-    int64_t rhs_offset, float *acc_base, int64_t acc_offset, int64_t acc_stride,
-    int32_t k_outer, int32_t intrinsics_m, int32_t intrinsics_n,
-    int32_t intrinsics_k) {
+    int64_t rhs_offset, float *acc_base, int64_t acc_offset, int32_t k_outer,
+    int32_t intrinsics_m, int32_t intrinsics_n, int32_t intrinsics_k) {
   (void)lhs_base;
   (void)lhs_offset;
   (void)rhs_base;
   (void)rhs_offset;
   (void)acc_base;
   (void)acc_offset;
-  (void)acc_stride;
   (void)k_outer;
   (void)intrinsics_m;
   (void)intrinsics_n;
diff --git a/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512vnni_16x16x2_i32_i8_casti16.c b/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512vnni_16x16x2_i32_i8_casti16.c
index 478ea1a..9e27639 100644
--- a/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512vnni_16x16x2_i32_i8_casti16.c
+++ b/compiler/plugins/target/LLVMCPU/builtins/ukernel/iree_uk_mma_x86_avx512vnni_16x16x2_i32_i8_casti16.c
@@ -36,21 +36,19 @@
 // on this case.
 // ABI matches the inner_tiled -> ukernel.generic lowering (see
 // `iree_uk_mma_x86_avx512bf16_1x16x2_f32_bf16`): each shaped operand passed
-// as (base, element offset), ACC additionally as its innermost
-// cross-intrinsic stride, then the scalar `k_outer` / `intrinsics_{m,n,k}`.
+// as (base, element offset) only (no strides; the ACC tile is contiguous),
+// then the scalar `k_outer` / `intrinsics_{m,n,k}`.
 IREE_UK_ALWAYS_INLINE
 void iree_uk_mma_x86_avx512vnni_16x16x2_i32_i8_casti16(
     const void *lhs_base, int64_t lhs_offset, const void *rhs_base,
-    int64_t rhs_offset, void *acc_base, int64_t acc_offset, int64_t acc_stride,
-    int32_t k_outer, int32_t intrinsics_m, int32_t intrinsics_n,
-    int32_t intrinsics_k) {
+    int64_t rhs_offset, void *acc_base, int64_t acc_offset, int32_t k_outer,
+    int32_t intrinsics_m, int32_t intrinsics_n, int32_t intrinsics_k) {
   (void)lhs_base;
   (void)lhs_offset;
   (void)rhs_base;
   (void)rhs_offset;
   (void)acc_base;
   (void)acc_offset;
-  (void)acc_stride;
   (void)k_outer;
   (void)intrinsics_m;
   (void)intrinsics_n;
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/CPU/IR/IREECPUAttrs.cpp b/compiler/src/iree/compiler/Codegen/Dialect/CPU/IR/IREECPUAttrs.cpp
index 2eb1f43..8997f88 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/CPU/IR/IREECPUAttrs.cpp
+++ b/compiler/src/iree/compiler/Codegen/Dialect/CPU/IR/IREECPUAttrs.cpp
@@ -1255,68 +1255,19 @@
   return true;
 }
 
-// Returns the index, in the ACC operand's shape, of the innermost
-// CrossIntrinsic dimension (the N cross-intrinsic dim for our layouts), or
-// nullopt if it is dynamic / absent. The ukernel needs this dim's stride to
-// address each unrolled intrinsic's ACC fragment.
-//
-// Example: with `MMA_X86_AVX512BF16_1x16x2` (each intrinsic produces a 1x16
-// f32 fragment) and intrinsics_m = intrinsics_n = 2, the ACC tile holds a 2x2
-// grid of such fragments. The two CrossIntrinsic dims are that grid's M and N;
-// the innermost is N, so this returns the index of the N-grid dim in the ACC
-// result shape, whose stride is the element distance from fragment (m, n) to
-// (m, n+1).
-static std::optional<unsigned>
-getAccInnermostCrossIntrinsicDim(IREE::Codegen::InnerTiledOp op,
-                                 DataTiledMMAAttr mma) {
-  auto outputType = dyn_cast<ShapedType>(op.getResultTypes()[0]);
-  if (!outputType) {
-    return std::nullopt;
-  }
-  Codegen::TileSwizzle accSwizzle = getSwizzle(mma, /*operandIdx=*/2);
-  SmallVector<Codegen::TileSwizzle::Dim> swizzleDims;
-  for (const Codegen::TileSwizzle::ExpandShapeDimVectorType &group :
-       accSwizzle.expandShape()) {
-    swizzleDims.append(group.begin(), group.end());
-  }
-  applyPermutationToVector(swizzleDims, accSwizzle.permutation());
-  int rankDiff = outputType.getRank() - static_cast<int>(swizzleDims.size());
-  auto crossIntrinsic = Codegen::TileSwizzle::Dim::Kind::CrossIntrinsic;
-  for (size_t i = swizzleDims.size(); i-- > 0;) {
-    if (swizzleDims[i].kind() != crossIntrinsic) {
-      continue;
-    }
-    int outputIdx = i + rankDiff;
-    if (outputType.isDynamicDim(outputIdx)) {
-      return std::nullopt;
-    }
-    return outputIdx;
-  }
-  // No CrossIntrinsic dims (intrinsics_m == intrinsics_n == 1): the single
-  // fragment sits at the start of the inner tile.
-  if (!swizzleDims.empty()) {
-    return rankDiff;
-  }
-  return std::nullopt;
-}
-
 // Rewrites an `inner_tiled` carrying a CPU `DataTiledMMAAttr` to a
 // `ukernel.generic`, threading the data-tiled-MMA scalar parameters as
 // operands so the ukernel can loop over arbitrary `intrinsics_{m,n,k}`:
 //   ins(lhs, rhs) outs(acc) (k_outer, intrinsics_m, intrinsics_n, intrinsics_k)
-// plus a `strided_dims` entry giving the ACC's innermost cross-intrinsic
-// stride.
+// All shaped operands are passed as `(base, offset)` only, no strides: the
+// ACC tile is contiguous, so the ukernel derives each intrinsic's ACC
+// fragment offset from the compile-time `intrinsics_{m,n}` and its own
+// (fixed, per-intrinsic) fragment size.
 static LogicalResult
 handleInnerTiledMmaUkernel(RewriterBase &rewriter, StringRef name,
                            IREE::Codegen::InnerTiledOp op, DataTiledMMAAttr mma,
                            ArrayRef<Value> inputs, ArrayRef<Value> outputs,
                            DictionaryAttr fnDefAttrs) {
-  std::optional<unsigned> accInnerDim =
-      getAccInnermostCrossIntrinsicDim(op, mma);
-  if (!accInnerDim) {
-    return rewriter.notifyMatchFailure(
-        op, "ACC innermost cross-intrinsic dim is dynamic or absent");
-  }
   Location loc = op.getLoc();
   Type i32 = rewriter.getI32Type();
   auto constI32 = [&](int64_t v) {
@@ -1327,23 +1278,15 @@
   Value kOuter = arith::IndexCastOp::create(
       rewriter, loc, i32,
       tensor::DimOp::create(rewriter, loc, op.getInputs()[0], 1));
-  // `strided_dims` is the `ukernel.generic` ABI knob for which dims' strides
-  // are passed to the C function: a list per shaped operand (here LHS, RHS,
-  // ACC), each naming the dims whose stride follows that operand's
-  // `(base, offset)` in the call. An empty list passes `base, offset` only; a
-  // null attribute (the default, used by simpler ukernels) passes all strides.
-  // Here only ACC needs one — the innermost cross-intrinsic (N) dim — so the
-  // ukernel can address each unrolled intrinsic's ACC fragment. LHS/RHS are
-  // contiguous in the data-tiled layout, so they take no stride argument.
-  SmallVector<SmallVector<int64_t>> stridedDims(3, {});
-  stridedDims[2].push_back(*accInnerDim);
+  // All shaped operands (LHS, RHS, ACC) are passed as `(base, offset)` only;
+  // `num_strided_outer_dims=0` means no stride arguments are appended.
   DictionaryAttr discardableAttrs = op->getDiscardableAttrDictionary();
   auto newOp = rewriter.replaceOpWithNewOp<IREE::Codegen::UKernelGenericOp>(
       op, op.getOutputs().getTypes(), name, inputs, outputs,
       ValueRange{kOuter, constI32(mma.getIntrinsicsM()),
                  constI32(mma.getIntrinsicsN()),
                  constI32(mma.getIntrinsicsK())},
-      fnDefAttrs, stridedDims);
+      fnDefAttrs, /*num_strided_outer_dims=*/0);
   newOp->setDiscardableAttrs(discardableAttrs);
   return success();
 }