-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Simplify bounds checks for multi-dimensional array accesses #18064
RFC: Simplify bounds checks for multi-dimensional array accesses #18064
Conversation
The existing code is kind of strange. What do we get by checking the total linearized index instead of just checking the last dimension? |
|
@blakejohnson, that's probably "partial linear indexing" (see #14770). |
Thinking about this partial indexing, we should be able to handle this case without special-casing Polly by generating the last check as:
In case dimensions and indexes match, we get the simple checks Matthias is looking for. In case of partial linear indexing, we still get checks that ensure we do not access outside of allocated memory. This would make Polly work in the common case without partial indexing, but partial indexing would continue to work. |
Since there seems to be a consensus about getting rid of partial indexing (just needs someone to actually implement the change), another option would be to say you can't use it in But if it's easy to keep, that would be fine, too. |
Thank you for your comments! @TobiG With this approach we would have one |
On Wed, Aug 17, 2016, at 09:36 PM, Matthias J. Reisinger wrote:
Right. I personally would be OK with this, but I am not part of the Best, |
Yes, |
32d9e28
to
1fc813d
Compare
Thank you for your thoughts again! I now updated the PR in the following way: As soon as we have an array access that uses (1D or partial) linear indexing we still use the existing bounds checking, but in the case of regular indexing the simpler check is used (to be on the safe side here: is the check Do you think this is the direction we could choose? |
builder.CreateCondBr(builder.CreateICmpULT(i, alen), endBB, failBB); | ||
} else { | ||
// We have already emitted a bounds check for each index except for | ||
// the last one which we therefore emit here, i.e. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence matches both branches and should be moved before the if (bc). Please also add a comment discussing the difference of the two checks and why each is used. Something like:
For the last dimension there are two options of how to emit bounds checks. In case only a single dimension remains (the number of subscript expressions in the array matches the number of array dimensions), we check if the outermost subscript is smaller than the size of the outermost dimension. In case more than one array dimension is left when we reach the last subscript (partial indexing), we verify if the computed element address is within the bounds of the allocated memory range.
Hi Matthias, thanks for the update. I like this change a lot. Two remarks:
|
1fc813d
to
39e1dc5
Compare
39e1dc5
to
ecd4a37
Compare
Thank you for the feedback! I addressed it in the updated PR. Best, |
This looks great from my side. What do Julia people think? |
This simplifies the array bounds check code that is emitted for multi-dimensional array accesses that use "regular" indexing, i.e. accesses of the form `A[i1,i2,...,iN]` to some `N`-dimensional array `A`. For example, with this change, the access `A[i,j,k]` to an array with the three dimensions `m`, `n` and `o` now leads to bounds checks that correspond to the following pseudo code: ``` if (i >= m) out_of_bounds_error(); else if (j >= n) out_of_bounds_error(); else if (k >= o) out_of_bounds_error(); ``` So far, the following more complicated bounds checks would have been emitted: ``` if (i >= m) out_of_bounds_error(); else if (j >= n) out_of_bounds_error(); else if (((k * n + j) * m + i) >= m * n * o) out_of_bounds_error(); ``` Julia also allows one-dimensional and "partial" linear indexing (see JuliaLang#14770), i.e. the number of indices used to access an array does not have to match the actual number of dimensions of the accessed array. For this case we still have use this old scheme. One motivation for this change was the following: expressions like `((k * n + j) * m + i)` are non-affine and Polly would not be able to analyze them. This change therefore also facilitates Polly's bounds check elimination logic, which would hoist such checks out of loops or may remove them entirely where possible.
ecd4a37
to
9f531d9
Compare
lgtm. this seems like a good find and a good fix. I'll merge if nanosoldier agrees (which I expect it will). @nanosoldier |
Something went wrong when running your job: |
LGTM, too. |
Looks like doing a clean build from |
the nightly build hit a different failure, which may or may not happen again... @nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels |
This simplifies the array bounds check code that is emitted for
multi-dimensional array accesses that use "regular" indexing, i.e.
accesses of the form
A[i1,i2,...,iN]
to someN
-dimensional arrayA
.For example, with this change, the access
A[i,j,k]
to an arraywith the three dimensions
m
,n
ando
now leads to bounds checksthat correspond to the following pseudo code:
So far, the following more complicated bounds checks would have been
emitted:
Julia also allows one-dimensional and "partial" linear indexing
(see #14770), i.e. the number of indices used to access an array does
not have to match the actual number of dimensions of the accessed array.
For this case we still have use this old scheme.
One motivation for this change was the following: expressions like
((k * n + j) * m + i)
are non-affine and Polly would not be ableto analyze them. This change therefore also facilitates Polly's bounds
check elimination logic, which would hoist such checks out of loops
or may remove them entirely where possible.