[Bugfix] Resolve reg offset on dynamic add_offset chains - #926
Conversation
|
From a performance perspective, I do not think dynamic offsets on register pointers/tensors should be supported. A runtime offset often prevents promotion to vector-SSA/register and may force a private-memory or spill fallback. Since this storage is intended to remain register-backed, it would be better to reject the case with a clear diagnostic instead of silently compile it. |
Thanks comment — I agree with the underlying concern: silently spilling register-backed storage to scratch would be a bad outcome, and an invisible performance cliff is worse than a compile-time error. I checked the generated code before responding, however, and the situation is narrower than “a runtime offset forces a private-memory fallback.” The fallback is real, but only beyond LLVM’s promotion threshold. An unpromoted
For up to 32 elements, the On scope: this PR fixes a silent miscompile. Previously, My proposal is to land this PR as the correctness fix, then follow up with the dynamic |
sjfeng1999
left a comment
There was a problem hiding this comment.
The rest looks good.
294c01b to
7063933
Compare
resolveRegOffset summed offsets with IntAttr::getValue() without checking isStatic(). A dynamic IntAttr carries value == 0, so an access through a dynamic offset was promoted to vector.extract of slot 0 -- silently the wrong element. Return the root plus an optional offset, and exclude allocas reached by a dynamic chain from promotion. Refs #898.
7063933 to
dfa31d6
Compare
Summary
resolveRegOffsetaccumulatedadd_offsetdisplacements without checking whether each link was static, so a register access through a dynamic offset was promoted to a hardcoded read of slot 0.Motivation
A dynamic
IntAttrcarriesvalue == 0(FlyAttrDefs.cpp), soIntAttr::getValue()on a dynamic offset silently returns 0 instead of failing. Before this change,add_offset(reg_ptr, dynamic)lowered to:The dynamic index is dropped entirely and the access is hardcoded to slot 0 — a deterministic read of the wrong element, not merely an undefined value.
Changes
resolveRegOffsetnow returns the root alloca plus an optional offset. The root is always reported, so the recast-exclusion walk andcollectTouchedRegAllocaInRegionkeep their conservative behaviour; onlygetRegAccessInfo, which needs a concrete slot index, bails out.register operand/result remain after rmem SSA promotion).No kernel in the tree currently hits this path — a scan of 15 compiled kernels found no register-space
add_offsetwith a dynamic offset — so this is a latent-correctness fix rather than a behaviour change for existing code.Performance (if applicable)
Not applicable. Per-kernel ISA resource comparison against the base commit shows no change: gfx942 33 kernels and gfx950 31 kernels, all identical in VGPR/SGPR/spill/scratch/ds_read.
Testing
tests/mlir/Transforms/promote_regmem_to_ssa_invalid.mlirgains@skip_register_dynamic_offset, verified to fail without the source change and pass with itclang-formatcleanDependencies
Breaking Changes
None.