thomasrolinger / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
0 stars 0 forks source link

Task: Check for writing to A[B[i]] #10

Closed thomasrolinger closed 2 years ago

thomasrolinger commented 2 years ago

I believe if the irregular access is on the LHS of a statement, we will have a compiler error. This is because we'd attempt to replace A[B[i]] with a call to inspectAccess and executeAccess. So we'd have a function call on the LHS of the statement.

Further down the road we can consider supporting writes to A like this, but for now, we should attempt to identify this and abort the optimization. Ideally, we'd do this during normalization. It'll require some tests to see what the AST looks like for various operators, but hopefully they'll be reduced down to something like a move that we can see where A[B[i]] is on the LHS.

But we could have something like this, which wouldn't produce a compiler error:

forall i in B.domain {
   ref x = A[B[i]];
   x = ...;
}

The issue here is that x may be a replicated value, and we don't have the mechanisms in place right now to support writes to replicated values. However, this would be OK is x was a var and not a ref. Either way, we'll need to add some checks for this scenario. Detecting it will be similar to what we will do for the above case: find out what it looks like for different operators and try to reduce it down to something easy to find. In this case, if x is a ref and we find the symbol for x, we'll want to track modifications to it. Since we will be doing that, we'll need to be in normalization. A concern is whether our existing approaches to detect modifications will work since x is not necessarily an array.

thomasrolinger commented 2 years ago

Addressed: https://github.com/thomasrolinger/chapel/commit/c1a7920f200adb25b30ec0e8ee6eb9e38cfa51cc

First, during normalization we checked whether A[B[i]]'s parent is an assignment (=, +=, etc), and if A[B[i]] is the first argument to this assignment. If so, the optimization is aborted.

We also check whether we have something like ref t = A[B[i]]. If we do, we ensure that t is a const ref or var. Otherwise, we abort. That is much easier than pulling out t in post-resolution and looking for modifications. So we are a bit aggressive, as a ref t is OK if it is never written to. But it's easier on us to do it this way.