<div dir="ltr">Hi,<div><br></div><div>Arnold Schwaighofer <<a href="mailto:aschwaighofer@apple.com" target="_blank">aschwaighofer@apple.com</a>> wrote:</div>> I have taken a high-level look at the implementation of the Dependence Analysis pass. <div>

<br></div><div>Thanks.  It's a sizable chunk of code and I appreciate your effort.</div><div><br></div><div><br></div><div><br></div><div>> - Using GetElementPtr during the analysis.<br>><br>>   Part of the current analysis depends on two geps with matching pointer types.</div>

<div><br></div><div>That's not exactly correct.</div><div><ul><li>If I find a pair of references that have GEPs that look the same, then I take advantage of them to find the separate indices (I recognize that you complain about this idea later on).<br>

</li><li>If one of the references lacks a GEP or the GEPs have different types, then I use the underlying SCEVs for all the analysis.</li></ul></div><div>If we immediately jump to using SCEVs, we are essentially linearizing all array accesses. While it won't matter for the 1-D cases, we're throwing away information that could help in multidimensional cases. Sometimes we can delinearize automagically, but I have, in the past, convinced myself that this is inadequate to handle the general case.</div>

<div><br></div><div>> I don’t think this is the right approach. Two differently typed GetElementPtr’s can compute the same access function.</div><div><br></div><div>Right. When faced with differently typed GEPs, I'd always use the SCEVs.</div>

<div><br></div><div><br></div><div><br><br><br>> - A GetElementPtr used to describe array accesses does not impose array dimension restrictions.<br><br>Right. I don't look at the type of the GEP at all, so I'm not trying to get dimension info there (or anywhere else, for that matter).</div>

<div><br>>   The code currently assumes that two different indices of a GetElementPointer can be independently analyzed.</div><div><br></div><div>Yes, this this is exactly how I'm using GEPs and its the only thing I try to glean from GEPs.</div>
<div><br></div>
<div>> This is not correct.</div><div><br></div><div>OK, so let's focus on this.</div><div><br></div><div>> The address part computation of a higher index may “overflow" into the lower index. An array type in a gep does not restrict the index range. (<a href="http://llvm.org/docs/GetElementPtr.html#what-happens-if-an-array-index-is-out-of-bounds" target="_blank">http://llvm.org/docs/GetElementPtr.html#what-happens-if-an-array-index-is-out-of-bounds</a>, Only the type of the array elements is relevant for the address computation)<br>

>   If we want to use a “multi-dimensional” array property (indices can be independently analyzed) we have to first show that this holds for the LLVM-IR in question. In my example below we have to make sure that N < 256, otherwise, we have to analyze the indices together.<br>

><br>>   Let me give an example:<br>>     void f(int A[256][256], long N) {<br>>     for (long y = 0; y < 128; ++y)<br>>       for (long i = 0; i < N; ++i)<br>>         A[y][i+N] = 2 * A[y][i];<br>

>     }<br>><br>> [...]<br>><br>>   If N is big enough (>=256) there is a dependence between the accesses (it might not be valid C to have N > 255, but it is certainly valid in LLVM IR semantics). The current implementation treats different getelementptr indices as independent and will return “none” as dependence answer for the two accesses. This is not correct.<br>
<br>So it sounds like we'll need to disable the little bit of code that makes this assumption and take our lumps with linearizing everything. We might try writing a delinearizer following Maslov (Hal Finkel also had ideas worth visiting).</div>
<div><br></div><div>Alternatively, we might revisit the definition of GEPs, looking for an alternative that lets a C or Fortran front end express multidimensional array references without linearizing everything.<br><br><br>
<br>> - Overflow<br>> It seems the current implementation does not handle overflow correctly.</div><div><br>
</div><div>I can believe it. I think this whole question needs to be carefully discussed and reviewed.</div><div style>I certainly don't understand all the constraints.</div><div><br></div><div>> We must be very careful with cases where part of the access function might overflow.<br>

><br>> ;;  for (long unsigned i = 0; i < N; i++) {<br>> ;;    A[3*i+7] = i;<br>> ;;    *B++ = A[3*i];<br>><br>> There is a dependence between the two access possible due to integer wrapping</div><div>

> but the current implementation returns there is none. I have not investigated why.</div><div><br></div><div>At a glance, I would think there's no possible dependence,</div><div>since GCD(3, 3) => 3 which doesn't divide 7.</div>
<div style>That's as far as the current analysis will go.</div><div><br></div><div style>But of course your point is correct.</div><div style>If I work through what happens with 4-bit words,</div><div style>we see things like (3*i + 7) % 16 == (3*j)  % 16</div>
<div style>when i == 0 and j == 13.</div><div><br></div><div style>Seems a fatally hard problem to me.</div><div style>Any ideas before I give up in despair?</div><div><br></div><div><br>> Thanks for pushing LLVM on this front!<br>
<br></div><div style>Thanks again for the feedback,</div><div style>Preston</div></div>