Skip to content

Remove automatic memory consistency pass#953

Merged
zhangstevenunity merged 2 commits into
hw-native-sys:mainfrom
TaoTao-real:codex/remove-memory-consistency-pass
Jul 17, 2026
Merged

Remove automatic memory consistency pass#953
zhangstevenunity merged 2 commits into
hw-native-sys:mainfrom
TaoTao-real:codex/remove-memory-consistency-pass

Conversation

@TaoTao-real

Copy link
Copy Markdown
Contributor

Summary

  • Remove the automatic pto-memory-consistency analysis pass from registration, build files, and the default ptoas pipeline.
  • Keep the explicit public memory-consistency IR (pto.cmo.cacheinvalid, pto.fence.barrier_all) and EmitC lowering.
  • Update the memory-consistency design note and lit tests to document/check the explicit-IR contract instead of the removed marker-driven analysis.

Motivation

Design

Testing

  • Local build: ninja -C build ptoas OK.
  • perf: ptoas 0.50 >160x compile slowdown on csa_slots_build_valid_qk_plan kernel vs 0.48 #950 repro: build/tools/ptoas/ptoas /tmp/csa_slots_build_valid_qk_plan.pto -o /tmp/csa_out.cpp --enable-insert-sync --pto-level=level3 --pto-arch a3 OK, real 0.87.
  • Focused lit OK:
    • comm_p2p_emitc
    • cmo_cacheinvalid_single_line_invalid
    • issue711_tnotify_mte_drain
    • issue872_tput_tnotify_release
    • tnotify_release_local_ops
    • signal_payload_cache_consistency
    • memory_consistency_cmo_unsupported
    • memory_consistency_fence_unsupported
  • git diff --check OK.
  • Full lit was attempted: 719 passed, 133 failed due local PTODSL daemon / MLIR Python environment (ModuleNotFoundError: No module named 'mlir.dialects'), not from this change path.

Risk / Rollback

  • Risk: automatic signal/payload memory-consistency checking/insertion is removed; upstream must emit explicit CMO/Fence and pipe barriers for those cases.
  • Rollback: revert this PR after a bounded/deduplicated replacement pass is available.

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

Copy link
Copy Markdown
Contributor

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 removes the automatic pto-memory-consistency analysis pass from the PTOAS pipeline to address compile-time performance degradation in complex control flows (issue #950). The memory consistency model transitions back to an explicit IR contract where users or PyPTO must manually insert cache maintenance operations (CMO), visibility fences, and pipe barriers. The design documentation, operator definitions, tests, and compiler pipeline have been updated accordingly to reflect this change. There are no review comments to address, and I have no additional feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@zhangstevenunity zhangstevenunity left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

COMMENT review. This is a clean, well-scoped removal that correctly targets the root cause of #950 (the unbounded state merge in annotateTNotifyRelease that doubled pendingAccesses per single-block scf.if, going ~2^k over the ~80 sequential cursor ifs in the CSA repro).

Verified on my side:

  • Removal is complete and dangling-reference-free. Every createPTOMemoryConsistencyPass reference, the Passes.td/Passes.h decls, the CMake source entry, and the ptoas.cpp pipeline call live only in files this PR deletes/edits. Nothing else calls the factory.
  • The internal attr constants (kCmoCacheInvalidSkipLowering*, kTNotifyDrain*) are defined in MemoryConsistencyAttrs.h, not in the deleted .cpp, so the dormant EmitC hooks that still read them still link.
  • PTOFenceToEmitC<...> is instantiated only for FenceBarrierAllOp (PTOToEmitC.cpp:14304), so the new conservative drain applies only to pto.fence.barrier_all.
  • The conservative fence drain is safe-direction (pipe_barrier is a wait, no deadlock) and correctly ordered (drains before dsb). For the explicit-IR path it preserves #711/#872: an explicit fence.barrier_all before tnotify still drains MTE2/MTE3/FIX + DSB, which is >= the precise drain the old pass used to insert.
  • Untouched fence test comm_p2p_emitc.pto uses loose ordered checks and is not broken; the Python binding test memory_consistency_bindings.py only exercises the kept public CMO/Fence ops and stays green; docs and ODS descriptions are updated to match.

The residual risks below are consequences of dropping a correctness/diagnostic pass rather than bugs in this PR, and are largely covered by the Risk/Rollback section. Two are worth calling out explicitly (inline). Not a blocker.

op.getScope().getScope() != pto::FenceScope::All)
return rewriter.notifyMatchFailure(op, "unsupported fence scope");

emitConservativeGmFencePipeDrains(rewriter, op.getLoc());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correctness of this conservative drain looks right and safe-direction: pipe_barrier is a wait (no deadlock risk) and the drains-before-dsb order is correct, so an explicit fence.barrier_all before tnotify preserves the #711/#872 release ordering the removed pass used to insert.

One asymmetry worth flagging: the release side keeps a compensating mechanism here (the fence auto-drains MTE2/MTE3/FIX), but the acquire side gets nothing. The removed pass used to diagnose a cacheable GM load_scalar after twait/ttest that lacked a cmo.cacheinvalid; there is no lowering-level fallback for that. After this PR a consumer doing twait -> cacheable GM load with no explicit cmo.cacheinvalid silently reads stale cached data, with no error and no auto-insertion. Since the release path is compensated and the acquire path is not, please confirm that asymmetry is intended.

Minor, non-blocking: MTE2 is a GM->local read pipe and FIX is cube-only, so both are over-drained on pure-vector gm fences. Fine as a documented conservative choice.

// TNotify release requires the producer side to drain local producer pipes
// before the GM fence and before pto.comm.tnotify. PTOAS no longer runs the
// historical MemoryConsistency analysis pass, so the explicit GM fence lowering
// conservatively drains MTE2, MTE3, and FIX before dsb(DSB_DDR).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

After the rewrite this test only proves the conditional guarantee: "if the producer writes an explicit fence, the fence lowers to MTE2/MTE3/FIX drains + DSB." The original #711 failure mode -- a bare MTE3 tstore -> tnotify with no fence -- now emits no drain and no diagnostic, and no test covers that negative case. The test is still valuable for pinning the new fence lowering, but it no longer guards against #711 recurring in producer-generated IR. Consider adding a negative/diagnostic test, or renaming, so the weaker contract is explicit.

}

func.func @single_line_twait_load_scalar_acquire(
func.func @scalar_acquire_sequence(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This acquire sequence (twait -> cmo.cacheinvalid -> cacheable load) is now the only thing standing between a correct read and a stale one, and it is entirely producer-authored: if a producer omits the cmo.cacheinvalid, the load silently returns stale cache with no diagnostic (the removed pass used to error here). Unlike the release path, there is no lowering-level safety net.

The whole "producer responsibility" model hinges on in-tree producers (PyPTO / TileLang templates) already emitting these explicit CMO/fence ops around every signal/payload handoff. This PR validates hand-written lit IR and the #950 compile-time repro, but not an end-to-end produced kernel that previously relied on the auto pass. Worth confirming no production template regresses before merge.

@zhangstevenunity
zhangstevenunity merged commit b4d96c2 into hw-native-sys:main Jul 17, 2026
9 of 10 checks passed
@reedhecre

Copy link
Copy Markdown

A5 板测成功

  • 触发方式:merged
  • 源码提交:b4d96c210f42
  • 结果汇总:OK 21 / FAIL 0 / SKIP 0
  • 日志:/root/ptoas-board-monitor-a5/logs/20260717_135807_merged_pr953.log
  • 结果 TSV:/root/ptoas-board-monitor-a5/logs/20260717_135807_merged_pr953.tsv

@reedhecre

Copy link
Copy Markdown

A3 板测失败

  • 触发方式:merged
  • 源码提交:b4d96c210f42
  • 结果汇总:OK 219 / FAIL 2 / SKIP 2
  • 日志:/home/zhongxuan/ptoas-board-monitor/runtime/logs/20260716_231856_merged_pr953.log
  • 失败阶段:board-validation / exit=1

失败用例

  • comm_p2p_binding_variants (run, exit=1)
  • comm_p2p (run, exit=1)

@reedhecre

Copy link
Copy Markdown

A3 板测失败详情:PR #953

comm_p2p_binding_variants

stage=run info=exit=1

[ERROR] aclrtSynchronizeStream(stream) failed: 507035 (/home/zhongxuan/ptoas-board-monitor/runtime/runs/20260716_231856_merged_pr953/npu_validation/CommSync/comm_p2p_binding_variants/main.cpp:122)
[ERROR] RecentErrMsg: EZ9999: Inner Error!
EZ9999[PID: 148234] 2026-07-17-00:00:14.715.275 (EZ9999):  The error from device(chipId:0, dieId:1), serial number is 1528, there is an exception of aivec error, core id is 42, error code = 0x10, dump info: pc start: 0x124200000000, current: 0x124200000164, vec error info: 0x4000000b7, mte error info: 0x1d03021089, ifu error info: 0x212c0bb989dc0, ccu error info: 0x21b59000000004f, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c100000000.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:645]
        TraceBack (most recent call last):
       The extend info: errcode:(0x10, 0, 0) errorStr: Illegal instruction, which is usually caused by unaligned UUB addresses. fixp_error0 info: 0x3021089, fixp_error1 info: 0x1d, fsmId:1, tslot:2, thread:0, ctxid:0, blk:0, sublk:0, subErrType:4.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:658]
       Kernel task happen error, retCode=0x31, [vector core exception].[FUNC:PreCheckTaskErr][FILE:davinci_kernel_task.cc][LINE:1729]
       AIV Kernel happen error, retCode=0x31.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [AIC_INFO] after execute:args print end[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [DFX_INFO]Aicore kernel execute failed, device_id=1, stream_id=46, report_stream_id=46, task_id=0, flip_num=0, fault kernel_name=comm_p2p_binding_variants_kernel, fault kernel info ext=comm_p2p_binding_variants_kernel, program id=0, hash=16541545288638093324.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       rtStreamSynchronize execution failed, reason=vector core exception[FUNC:FuncErrorReason][FILE:error_message_manage.cc][LINE:65]
       synchronize stream failed, runtime result = 507035[FUNC:ReportCallError][FILE:log_inner.cpp][LINE:148]
[2026-07-17 00:00:16] ERROR: testcase failed (exit 1): comm_p2p_binding_variants
comm_p2p

stage=run info=exit=1

[ERROR] aclrtSynchronizeStream(stream) failed: 507035 (/home/zhongxuan/ptoas-board-monitor/runtime/runs/20260716_231856_merged_pr953/npu_validation/CommSync/comm_p2p/main.cpp:122)
[ERROR] RecentErrMsg: EZ9999: Inner Error!
EZ9999[PID: 166657] 2026-07-17-00:00:33.931.980 (EZ9999):  The error from device(chipId:0, dieId:1), serial number is 1529, there is an exception of aivec error, core id is 47, error code = 0x10, dump info: pc start: 0x124200000000, current: 0x124200000168, vec error info: 0x4000000b7, mte error info: 0x3c0300404d, ifu error info: 0x2ffffff080d40, ccu error info: 0x21b59000000004f, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c100000000.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:645]
        TraceBack (most recent call last):
       The extend info: errcode:(0x10, 0, 0) errorStr: Illegal instruction, which is usually caused by unaligned UUB addresses. fixp_error0 info: 0x300404d, fixp_error1 info: 0x3c, fsmId:1, tslot:2, thread:0, ctxid:0, blk:0, sublk:0, subErrType:4.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:658]
       Kernel task happen error, retCode=0x31, [vector core exception].[FUNC:PreCheckTaskErr][FILE:davinci_kernel_task.cc][LINE:1729]
       AIV Kernel happen error, retCode=0x31.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [AIC_INFO] after execute:args print end[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [DFX_INFO]Aicore kernel execute failed, device_id=1, stream_id=46, report_stream_id=46, task_id=0, flip_num=0, fault kernel_name=comm_p2p_kernel, fault kernel info ext=comm_p2p_kernel, program id=0, hash=6260346515940177617.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       rtStreamSynchronize execution failed, reason=vector core exception[FUNC:FuncErrorReason][FILE:error_message_manage.cc][LINE:65]
       synchronize stream failed, runtime result = 507035[FUNC:ReportCallError][FILE:log_inner.cpp][LINE:148]
[2026-07-17 00:00:35] ERROR: testcase failed (exit 1): comm_p2p

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.

perf: ptoas 0.50 >160x compile slowdown on csa_slots_build_valid_qk_plan kernel vs 0.48

3 participants