Skip to content

refactor(ir): extract wrapper-call finders into shared utility + drop InferFunctionCoreType body-walking#1321

Merged
Hzfengsy merged 4 commits intohw-native-sys:mainfrom
lyfne123:worktree-phase2-codegen-analysis
May 9, 2026
Merged

refactor(ir): extract wrapper-call finders into shared utility + drop InferFunctionCoreType body-walking#1321
Hzfengsy merged 4 commits intohw-native-sys:mainfrom
lyfne123:worktree-phase2-codegen-analysis

Conversation

@lyfne123
Copy link
Copy Markdown
Collaborator

@lyfne123 lyfne123 commented May 9, 2026

Summary

Phase 2 of the codegen-analysis migration. Two related cleanups in one PR:

Commit 1 — #12: extract wrapper-call finders into shared IR utility

Pull three duplicated visitor classes (`InnerCallFinder` x2 + `CalleeFinder`) out of `src/codegen/orchestration/` into a shared IR-layer utility `include/pypto/ir/transforms/utils/wrapper_call_utils.h`, exposing three named functions:

  • `FindFirstInnerCall(wrapper, program)` — first non-builtin Call
  • `FindGroupCallees(group_func, program)` — AIC/AIV name + first AIC/AIV/InCore inner call
  • `CollectInnerCalls(wrapper, program)` — all non-Orchestration, non-Opaque inner calls

A small `CallVisitor` scaffold inside the cpp handles tree traversal + `GlobalVar` resolution; each named function plugs in a callback. Pure refactor.

Commit 2 — #10: drop `InferFunctionCoreType` body-walking fallback

`InferFunctionCoreType` used to fall through to a 38-line tile-memory-space walk when the function arrived as plain `InCore`. That branch was reached only when a caller bypassed the IR pipeline (so `ExpandMixedKernel` never got to convert `InCore` → `AIC`/`AIV`). The only such callers are 23 tests in `test_orchestration_codegen.py` that hand-build user-style IR.

Decision: explicitly mark those test kernels with their concrete core type. All 32 affected kernels operate on `Vec` memory only (`pl.load` + `pl.add` + `pl.store`, no matmul / Mat / Left / Right), so `pl.FunctionType.AIV` is the correct type. Tests that already run the pipeline (`pm.run_passes` / `PassManager.get_strategy` / direct `expand_mixed_kernel` / `outline_incore_scopes` calls) keep `InCore` so the pipeline can convert them.

`InferFunctionCoreType` is now an exact-match `FunctionType` lookup with `INTERNAL_UNREACHABLE_SPAN` on anything else, with a clear error message pointing maintainers at the two recovery options if it ever fires.

Why one PR (and not two)

Both cleanups touch `src/codegen/orchestration/orchestration_codegen.cpp` and aim at the same goal (remove embedded analysis from codegen). Reviewing them together makes the codegen contract clearer in one place. Each commit stands alone if you want to land them separately.

Test plan

  • `tests/ut/` — 4439 passed, 33 skipped on darwin/Apple Silicon (same as main baseline)
  • Build clean (cmake + clang-tidy + cpplint + clang-format pass via `pre-commit run --all-files`)
  • CI (clang-tidy / pre-commit / system-tests / unit-tests x2 / fuzz / pypto-lib-model)
  • `compare-codegen` byte-equal verification on `examples/kernels/` + `examples/models/` — to be run manually before merge

Stats

Lines
New `wrapper_call_utils.{h,cpp}` +175
`orchestration_codegen.cpp` removed -71 (#12) -38 (#10)
`orchestration_analysis.cpp` removed -28
Test type swaps (`InCore` → `AIV`) 32 lines
Net codegen change -141 LoC
`IRVisitor` subclasses removed from `src/codegen/orchestration/` -3

InnerCallFinder / CalleeFinder were duplicated three times across
codegen and analysis: two inside orchestration codegen
(FindWrapperInnerCall, FindGroupCallees) and one inside
orchestration_analysis.cpp's ComputeGroupEffectiveDirections. Each
walked a wrapper body, resolved GlobalVar callees via
Program::GetFunction, and collected matches by a slightly different
predicate.

Pull the scaffold out into wrapper_call_utils.{h,cpp} under
include/pypto/ir/transforms/utils/, exposing three named functions:

- FindFirstInnerCall(wrapper, program) -- first matching call
- FindGroupCallees(group_func, program) -- AIC/AIV name + first inner
  call (priority AIC > AIV > InCore)
- CollectInnerCalls(wrapper, program) -- all non-Orchestration,
  non-Opaque inner calls

Each user calls the named function it wants; the shared CallVisitor
under the hood handles tree traversal, GlobalVar resolution, and early
termination via a std::function callback.

Pure refactor, no behavior change; all 4439 unit tests pass.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Extract inner-call discovery into a new IR utility module (header + implementation), refactor orchestration_codegen and orchestration_analysis to use the utilities, add the new source to the build, and update tests to mark many kernel/task functions as AIV instead of InCore.

Changes

Inner-Call Discovery Utility Extraction

Layer / File(s) Summary
Data Structures
include/pypto/ir/transforms/utils/wrapper_call_utils.h
Adds WrapperCallInfo and GroupCalleeInfo and declares FindFirstInnerCall, FindGroupCallees, and CollectInnerCalls.
Implementation
src/ir/transforms/utils/wrapper_call_utils.cpp
Implements visitor-based discovery: first-match, group-callee capture (AIC/AIV/InCore fallback), and collection of non-Orchestration/non-Opaque inner calls.
Call Site Integration
src/codegen/orchestration/...
Replaces local IRVisitor logic in orchestration_analysis and orchestration_codegen with calls to CollectInnerCalls, FindFirstInnerCall, and FindGroupCallees; refactors InferFunctionCoreType to use FunctionType switch.
Build Configuration
CMakeLists.txt
Adds src/ir/transforms/utils/wrapper_call_utils.cpp to PYPTO_SOURCES.
Tests / Annotations
tests/ut/codegen/test_orchestration_codegen.py
Updates many test programs to change kernel/task pl.function annotations from pl.FunctionType.InCore to pl.FunctionType.AIV.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • hw-native-sys/pypto#848: Modifies the same orchestration_analysis and orchestration_codegen call-discovery paths and inner/group callee discovery functions.

Suggested reviewers

  • Hzfengsy

Poem

🐰 I hop through calls and trace each name,
Unify the paths where duplicates came.
New helpers hum, the visitors sleep—
Small rabbit fixes make the trees less deep. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: extracting wrapper-call finders into a shared utility and simplifying InferFunctionCoreType by removing body-walking logic.
Description check ✅ Passed The description clearly explains both refactoring efforts, their rationale, test updates, and provides comprehensive context for the changes made throughout the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the codebase by extracting redundant IR visitor logic into a new utility module, wrapper_call_utils. It introduces centralized functions—FindFirstInnerCall, FindGroupCallees, and CollectInnerCalls—to handle the identification of inner function calls and group callees. These utilities replace local visitor implementations in orchestration_analysis.cpp and orchestration_codegen.cpp, improving code maintainability and reuse. I have no feedback to provide.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/ir/transforms/utils/wrapper_call_utils.cpp`:
- Around line 73-90: The lambda passed to CallVisitor currently sets
info.inner_call only on the first match which allows lower-priority InCore/AIV
to win over later AIC; change the selection to enforce AIC > AIV > InCore by
updating info based on callee->func_type_: when you see an AIC, always
set/override info.aic_name, info.inner_call and info.inner_callee; when you see
an AIV, set/override info.aiv_name and set inner_call/inner_callee only if the
current inner is not an AIC; when you see an InCore, set inner_call/inner_callee
only if neither AIC nor AIV have been recorded. Keep using the existing
CallPtr/FunctionPtr and info.* fields (aic_name, aiv_name, inner_call,
inner_callee) to implement this priority logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6390931e-374c-43b9-8df7-028806dfef4e

📥 Commits

Reviewing files that changed from the base of the PR and between e4ddc66 and 7e502cb.

📒 Files selected for processing (5)
  • CMakeLists.txt
  • include/pypto/ir/transforms/utils/wrapper_call_utils.h
  • src/codegen/orchestration/orchestration_analysis.cpp
  • src/codegen/orchestration/orchestration_codegen.cpp
  • src/ir/transforms/utils/wrapper_call_utils.cpp

Comment thread src/ir/transforms/utils/wrapper_call_utils.cpp
InferFunctionCoreType used to fall through to a 38-line tile-memory-space
walk when the function arrived as plain InCore. That branch is reached
only when a caller bypasses the IR pipeline (so ExpandMixedKernel never
got to convert InCore → AIC/AIV). The only callers that bypass the
pipeline are tests that hand-build user-style IR and call
codegen.generate_orchestration directly.

Convert those tests to declare their kernels with the appropriate
@pl.function(type=pl.FunctionType.AIV) explicitly — all 32 affected
kernels in tests/ut/codegen/test_orchestration_codegen.py operate on
Vec memory only (pl.load + pl.add + pl.store, no matmul / Mat / Left /
Right), so AIV is the correct concrete type. Tests that already run
the pipeline (pm.run_passes / PassManager.get_strategy / direct calls
to expand_mixed_kernel / outline_incore_scopes) keep InCore because
the pipeline correctly converts them.

InferFunctionCoreType is now an exact-match FunctionType lookup with
INTERNAL_UNREACHABLE_SPAN on anything other than AIC / AIV — codegen
contracts that only AIC / AIV reach this path, with a clear error
pointing maintainers at the two recovery options if it ever fires.

Migration of catalog item hw-native-sys#10 (Phase 2). Pure refactor in the codegen
file (-38 / +6 LoC); test changes are mechanical type swaps.
@lyfne123 lyfne123 changed the title refactor(ir): extract wrapper-call finders into shared IR utility refactor(ir): extract wrapper-call finders into shared utility + drop InferFunctionCoreType body-walking May 9, 2026
- wrapper_call_utils.h / .cpp: clarify FindGroupCallees doc and inline
  comment. The original CalleeFinder used first-match-in-source-order
  for inner_call (no AIC > AIV > InCore priority); my refactor copied
  that behavior verbatim, but the new docstring incorrectly claimed a
  type priority. Update both header and impl to describe the actual
  behavior — first-match wins, with the practical observation that
  Group bodies emitted by ExpandMixedKernel place AIC before AIV in
  source order, so the AIC call wins naturally.

CodeRabbit flagged this as Major / Potential issue. Pure docstring +
comment fix; behavior unchanged from main. If a real type-priority
contract is desired, that's a separate, behavior-changing follow-up.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codegen/orchestration/orchestration_codegen.cpp`:
- Around line 60-66: The doc comment refers to a stale caller name
"GenerateUserFunctionCall"; update the comment to reference the actual caller
"GenerateFunctionCallCode" (and keep "GenerateSpmdCallCode") so the contract
described after ExpandMixedKernel is accurate; locate the comment block near the
top of orchestration_codegen.cpp (surrounding the comment mentioning
ExpandMixedKernel) and replace the stale symbol with GenerateFunctionCallCode
and adjust any surrounding wording if necessary to remain consistent with the
current callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 192cba72-c2b2-4170-ad52-f286a58c04bc

📥 Commits

Reviewing files that changed from the base of the PR and between 7e502cb and c1680ff.

📒 Files selected for processing (4)
  • include/pypto/ir/transforms/utils/wrapper_call_utils.h
  • src/codegen/orchestration/orchestration_codegen.cpp
  • src/ir/transforms/utils/wrapper_call_utils.cpp
  • tests/ut/codegen/test_orchestration_codegen.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • include/pypto/ir/transforms/utils/wrapper_call_utils.h
  • src/ir/transforms/utils/wrapper_call_utils.cpp

Comment thread src/codegen/orchestration/orchestration_codegen.cpp
Doc comment in InferFunctionCoreType referred to GenerateUserFunctionCall;
the actual caller in this file is GenerateFunctionCallCode (line 1262).
Updated to match.
@Hzfengsy Hzfengsy merged commit c3c7589 into hw-native-sys:main May 9, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants