Skip to content

feat(analysis): support unit-dependent loop starts - #175

Merged
zhen8838 merged 25 commits into
tile-ai:mainfrom
zhen8838:feat/unit-dependent-loop-start
Sep 22, 2026
Merged

zhen8838 merged 25 commits into
tile-ai:mainfrom
zhen8838:feat/unit-dependent-loop-start

Conversation

@zhen8838

@zhen8838 zhen8838 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Why

  • Persistent kernels need loop starts and stops derived from mesh coordinates so each unit can own a distinct tile range without losing analysis precision.
  • Review found analysis, isl interop, and visitor responsibilities co-located behind misleading names, making these contracts harder to maintain.

What

  • Carry bounded mesh coordinates through dimension ranges, loop domains, trip counts, access relations, allocation proofs, and three-argument tile(start, stop, step) round trips.
  • Split iteration scopes, access resolution, loop domains, loop terms, isl interop, and type inference into modules matching their responsibilities.
  • Add realistic tiled and grid-stride persistent GEMM fixtures; the placed-program inventory covers all analysis families, per-unit trips, access precision, unit partitioning, and memory peaks.

Contract

  • tile() accepts two arguments or (start, stop, step). Loop start and extent may depend on bounded unit values; step must be literal because Presburger arithmetic cannot represent a parametric stride.
  • Type-inference rules may return TypeInferResults with a value range; bare Type remains valid. RangeMetadata follows the expr.type lifecycle. Inference that does not write type also does not write range.
  • TypeInferVisitor and inference_type live in visitor_registry/typeinfer.py; verify, codegen, and cost visitors remain in visitors.py.
  • IterationScope, construction, and traversal live in analysis/iteration_scope.py; access resolution lives in analysis/access.py; loop domains live in analysis/loop_domain.py.
  • Access and AccessPrecision belong to analysis/access.py; bounded parameters may remain EXACT.
  • cardinality is the sole public point-counting entry. An empty parameter context counts as 0; bounded boxes up to PARAM_POINT_LIMIT are enumerated; oversized or nonempty unbounded boxes return None.
  • ir/isl_interop.py owns dim/shape-to-isl interop, including index_set; ir/types/dim.py contains only definitions and constructors, ir/types/dim_isl.py is removed, and utils/isl_utils.py remains IR-independent.
  • Interop directions are named dim_to_isl_expr, shape_to_isl_domain, and isl_to_dim; normalize_dim and dim_range retain their names. dim_range returns None when no bound is available; unsupported symbolic divisors still raise.
  • analysis/loop_terms.py (formerly affine.py) performs HIR-to-LoopTerm conversion without isl. LoopAffineTerm is renamed LoopTerm.
  • widest_allowed is public in analysis/access.py; analysis/footprint.py is retained as an empty placeholder for future footprint work.
  • resolve_program_geometry and local_duration_ns are public analysis helpers.
  • The analysis preflight does not write Expr.type; the previous specification wording claiming it did was corrected.

Risk

  • The flat fixture remains WIDENED: loop-term binding does not support floor-div/mod.
  • LoopTerm remains a custom tuple-like representation rather than an isl object; this review intentionally only renamed it.
  • Analysis still imports three IR internals: ir.hir.specialize._record_complete_bindings, function-local ir.hir.verify._verify_isolated, and ir.types.shard.mesh._positions_layout. Proper fixes require public IR-side APIs, not merely removing underscores.
  • Mesh axis naming and x/y/z fallback remain duplicated between parser and printer; they should converge on a shared mesh helper.
  • Persistent programs still lack a numerical evaluator reference because per-device MeshCoord evaluation is deferred to issue feat(evaluator): model the mesh so check can reference a coordinate-reading program #138.
  • Loop bounds still lack ShapeDim validation, so normalize_dim may retain an invalid static object.
  • Parameter boxes above 4096 points make peaks/trips unknown.
  • Converters remain outside whole-function range reinference, matching prior behavior; no range consumer reads them.

@zhen8838
zhen8838 force-pushed the feat/unit-dependent-loop-start branch from ffd8f72 to 448d74c Compare September 21, 2026 12:32
Comment thread docs/spec/analysis.md Outdated
Comment thread src/tilefoundry/analysis/allocation.py Outdated
Comment thread src/tilefoundry/analysis/scope.py Outdated
Comment thread src/tilefoundry/analysis/scope.py Outdated
Comment thread src/tilefoundry/analysis/scope.py Outdated
Comment thread tests/analysis/test_analysis_families.py Outdated
Comment thread tests/fixtures/placed/persistent_gemm_flat.py Outdated
Comment thread tests/integration/test_persistent_gemm.py Outdated
Comment thread tests/ir/test_loop_region_range_nested.py Outdated
Comment thread tests/parser/test_mesh_visibility.py Outdated
Comment thread docs/spec/code-organization.md
Comment thread src/tilefoundry/analysis/footprint.py Outdated
Comment thread src/tilefoundry/ir/isl_interop.py
@zhen8838
zhen8838 merged commit b5aaa44 into tile-ai:main Sep 22, 2026
1 check passed
@zhen8838
zhen8838 deleted the feat/unit-dependent-loop-start branch September 22, 2026 04:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant