[Reassociate] Distribute multiply over add to enable factorization (#178201)
### This patch improves ReassociatePass to handle patterns like:
(x*C1) - ((y+x)*C2) → x*(C1-C2) - (y*C2)
The optimization consists of two changes:
1. Distribution pre-processing: Transform (A+B)*C → A*C + B*C when:
- The add has exactly one use (avoids code bloat)
- Both add operands are non-constant (avoids unprofitable cases)
This exposes common factors that would otherwise be hidden inside
the addition, enabling subsequent factorization.
2. Factorization heuristic: Prefer extracting non-constant factors
(Instructions/Arguments) over constant factors when occurrence
counts are equal. This enables better constant folding opportunities.
Note: undef is excluded from this preference to maintain existing
test expectations.
Example transformation:
Input IR:
```
%add = add nsw i16 %y, %x
%mul1 = mul nsw i16 %x, 8697
%mul2 = mul nsw i16 %add, 6436
%sub = sub nsw i16 %mul1, %mul2
ret i16 %sub
```
After distribution:
```
%1 = mul nsw i16 %y, 6436
%2 = mul nsw i16 %x, 6436
%3 = add nsw i16 %1, %2
%sub = sub nsw i16 %mul1, %3
```
After reassociation (factors %x, folds 8697-6436):
```
%neg = mul i16 %y, -6436
%reass.mul = mul i16 %x, 2261
%result = add i16 %reass.mul, %neg
```
The transformation preserves nsw/nuw flags during distribution.
Note that flags may be dropped by subsequent reassociation passes;
comprehensive flag preservation can be addressed in future work.
Fixes #167190