[mlir] Add splitForOpAtBound utility and use it in loop unrolling (#215108)
## Summary
Adds `splitForOpAtPoint` to split an `scf.for` at a given split point:
- first loop: `[lowerBound, splitPoint)`
- second loop: `[splitPoint, upperBound)`
The original loop is not mutated in place. Two new loops are cloned,
iter-args
are chained from the first to the second, uses of the original results
are
rewired, and the original op is erased. The helper returns `{first,
second}`.
The split point is validated as:
- `lowerBound <= splitPoint < upperBound`
- `step > 0`
- `splitPoint == lowerBound + k * step`
When the needed values are constant, an invalid split fails at compile
time.
When any of them is dynamic, the same conditions are emitted as runtime
`arith.cmpi` / `cf.assert`. Signed vs unsigned follows the loop's
`unsignedCmp` attribute (`getConstantIntValue` /
`getConstantUIntValue`).
`loopUnrollByFactor` uses this helper for the epilogue instead of
inlining
clone-and-rewire logic. The first returned loop is the main loop to
unroll;
the second is the epilogue.
Also adds `getConstantUIntValue` (zero-extend to `uint64_t`) next to
`getConstantIntValue`, and links the ControlFlow dialect from SCF Utils
so
runtime asserts can be created.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>