SIGN IN SIGN UP

Decompose non-tile-aligned group_norm at TTIRToTTNN conversion (#8935)

### Ticket
- tenstorrent/tt-xla#5483 (blocks coqui/XTTS-v2 bring-up,
tenstorrent/tt-xla#5216)

### Problem description
`ttnn.group_norm` requires its flattened height (per-sample `H*W`) to be
tile-aligned (a multiple of 32). The `TTNN` `GroupNormOp` **verifier**
enforced this during `TTIRToTTNN` conversion, so any `GroupNorm` whose
normalized spatial length is not divisible by 32 failed to compile:

```
'ttnn.group_norm' op flattened height must be tile-aligned, got 200
Failed to run TTIRToTTNNCommon pipeline
```

`GroupNormDecompositionRewritePattern` already lowers `group_norm` to
primitives, but it only runs in a later (device) pass — *after* the
verifier has already rejected the op during conversion. So the
decomposition could never rescue these shapes, and any model with a
data-dependent group-norm length (e.g. the XTTS-v2 conditioning encoder,
whose mel length is ~269 and essentially never a multiple of 32) could
not compile.

### What's changed
Approach per @sdjordjevicTT's review — instead of decomposing at
conversion time, **relax the verifier and let the op flow into
`TTNNDecomposition`**:

- **`TTNNOps.cpp` (verifier):** removed the hard `H*W % 32`
tile-alignment rejection. Tile-alignment of the flattened height is a
*fused-kernel* constraint, not an op invariant, so it is no longer
verified here — non-tile-aligned shapes are now representable and flow
into decomposition.
- **`GroupNormDecompositionRewritePattern.cpp` (decomposition):** keeps
the fused `ttnn.group_norm` only when the per-sample `H*W` is
tile-aligned (validated via the op model); otherwise it decomposes into
primitives. At `optimization_level 0` (no op-model validation)
everything decomposes unconditionally.

**Why an explicit tile-alignment gate, and not the op model alone:** the
op model reports the fused `ttnn.group_norm` as *legal* for
non-tile-aligned `H*W`, but the fused kernel then reduces mean/variance
over the tile-padding rows and is **silently wrong** — per-group
mean/std drift from (0, 1), and abs error exceeds tt-metal's own
`atol=0.065` by 4–14×, scaling with the padding fraction. PCC stays ≈
1.0 throughout, because the contamination is a per-group *affine*
transform that Pearson correlation is invariant to (which is also why
the op model does not flag it). Confirmed at the pure-`ttnn` level on
Blackhole and filed as **tenstorrent/tt-metal#50682**. So relying on the
op model alone would keep the wrong fused kernel at `opt>=1`; once
#50682 is resolved, this gate can be removed.

Note the gate is on **per-sample `H*W`** (`inputShape[2]`), not `N*H*W`
— e.g. `N=2, H*W=16` is non-aligned even though `N*H*W=32` looks
aligned.

### Routing
| | tile-aligned `H*W` | non-tile-aligned `H*W` |
|---|---|---|
| `opt 0` | decompose | decompose |
| `opt >= 1` | fused `ttnn.group_norm` | decompose (until
tt-metal#50682) |

### Result
- Non-tile-aligned `group_norm` now lowers cleanly past `TTIRToTTNN` (no
verifier error) and decomposes into primitives — numerically the exact
group-norm definition (reduces over real elements only).
- Tile-aligned shapes are unchanged and still lower to the fused
`ttnn.group_norm` kernel.
- Verified on a minimal repro (`nn.GroupNorm(32, 1024)` on a
non-tile-aligned `H*W`) and the XTTS-v2 conditioning encoder — both
previously failed with the tile-aligned error and now compile.

### Checklist
- [x] Full model regression suite green (aligned group_norm unchanged;
new decomposition path exercised)

### Logs
- Model level tests -
[conditioning_FAIL_without_8935.log](https://github.com/user-attachments/files/29969920/conditioning_FAIL_without_8935.log),
[conditioning_PASS_with_8935.log](https://github.com/user-attachments/files/29969921/conditioning_PASS_with_8935.log)
- Lit tests -
[lit_PASS.log](https://github.com/user-attachments/files/30001157/1_lit_PASS.log),
[lit_FAIL.log](https://github.com/user-attachments/files/30001159/2_lit_FAIL.log)
A
Ashok Kumar Kannan committed
bb71bc74a04315d2163970d613ea901df8c1961f
Parent: 9f06802
Committed by GitHub <noreply@github.com> on 7/22/2026, 6:43:17 AM