Repository navigation
Conversation
…r dims A dynamic layout's size was an i32 product of i32 extents, so (4, 2**29) wrapped to INT32_MIN. logical_divide used it as a decomposition divisor and every lane wrote to a wrong but in-bounds address (#1176). Sizes now go through intTupleSize (i64), so fx.size of a multi-dim dynamic layout is Int64. intTupleProduct and coordinate div/rem stay i32, so a nested dynamic mode whose extents multiply past INT32_MAX still wraps. A dynamic dim >= 2**31 now fails at launch with a message naming the field instead of a bare struct.error.
Phil-amd
force-pushed
the
fix/issue-1176-i32-shape-overflow
branch
from
October 8, 2026 01:01
80de7eb to
53ac5d7
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes a silent wrong-address bug for layout-dynamic tensors whose total size reaches 2^31, and replaces the bare
struct.errorraised when a single dynamic dimension does not fit in i32. Addresses #1176.A (4, 2^29) tensor has size 2^31. Each extent fits in i32, but the size was also computed in i32 and wrapped to INT32_MIN.
logical_divideuses that size as a divisor when it decomposes a coordinate, so every lane of the kernel below wrote tolane * 16instead of its layout position. The wrong addresses stay in bounds, so buffer OOB checking never fires and nothing reports an error.pytest tests/unit/test_dynamic_extent_overflow.py -m large_shapereproduces it (about 2 GiB of device memory).Why not widen all dynamic multiplication to i64
A new
intTupleSizecomputes sizes in i64, and onlylayoutSize,fly.sizeandfly.int_tuple_productuse it.intTupleProductstays i32 because it also builds the divisors forcrd2idx/idx2crd. Widening it, which was my first attempt, turned per-thread index math over nested dynamic modes into 64-bitdivsi/remsi. A FileCheck case now guards against that.Rejecting launches whose
prod(shape)exceeds INT32_MAX would also block valid multi-dimensional tensors. Accepting dimensions of 2^31 or larger would need ABI and compiler changes, as the issue discussion notes. This PR only reports that case clearly.Key points
Composition stays i32.
min(extent, size)is bounded by the i32 extent.minExtenttruncates it back, so coordinate div/rem are i32. Only arithmetic on the size itself becomes i64: its multiply and, with a non-trivial tiler, one ceil-div by a constant.Visible type change.
fx.sizeof a multi-dimensional dynamic layout is nowInt64. Static layouts, 1-D dynamic layouts andcosizeare unchanged; with the default 64-bit stridescosizeis already i64.test_static_vs_dynamicreturned this size from an i32 function and was updated.Launch diagnostic.
tensor shape[0] = 2147483648 does not fit in a signed 32-bit integer ...names the field and its index. The check runs only afterpack_intohas already failed, so a launch that succeeds pays nothing.Not changed. Static
IntAttrvalues and their divisibility are still int32. Two cases can still wrap silently:((4, 2^30+1), 2)with strides((1, 4), 1), coordinate 63 maps to offset 18 instead of 63.use_32bit_stride, cosize is computed from i32 terms:cosize((50000, 50000):(50000, 1))gives -1794967296 instead of 2500000000.Both reproduce when the ops are lowered directly. I have not checked whether any kernel reaches them.