<div dir="ltr">(and to be clear, wherever we end up, if the answer is "please support random update insertions, even if expensive", i'll produce a batch updater for you that can do that, so you won't have to mess around trying to make that work)<div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 1, 2016 at 1:16 PM, Daniel Berlin <span dir="ltr"><<a href="mailto:dberlin@dberlin.org" target="_blank">dberlin@dberlin.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Here's an example where upwards motion is necessary for the transformation to<br>
occur:<br>
<br>
  %S = type { i8*, i8, i32 }<br>
<br>
  define void @noaliasaddrproducer(%S* %src, %S* noalias %dst,<br>
                                    %S* noalias %dstidptr) {<br>
  ; MemoryUse(liveOnEntry)<br>
    %1 = load %S, %S* %src              ; combine this into a memcpy...<br>
  ; 1 = MemoryDef(liveOnEntry)<br>
    store %S zeroinitializer, %S* %src<br>
    %y = bitcast %S* %dstidptr to i8*<br>
  ; 2 = MemoryDef(1)<br>
    call void @llvm.memset.p0i8.i64(i8* %y, i8 0, i64 54, i32 0, i1 false)<br>
  ; 3 = MemoryDef(2)<br>
    store %S %1, %S* %dstidptr          ; ...with this.<br>
    ret void<br>
  }<br>
<br>
The store to %src prevents %1 from being moved down to its corresponding store, </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
so instead, the corresponding store is moved up to %1.</blockquote><div><br></div></span><div>I agree this is how it is currently done.</div><div>I disagree this is the only way to achieve this, and that trying to do it this way necessarily makes sense with MemorySSA.</div><div><br></div><div>The final result is:<span class=""><br><div>define void @noaliasaddrproducer(%S* %src, %S* noalias %dst, %S* noalias %dstidptr) {</div></span><div>  %1 = bitcast %S* %src to i8*</div><span class=""><div>  %y = bitcast %S* %dstidptr to i8*</div></span><div>  %2 = getelementptr i8, i8* %y, i64 16</div><div>  call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 38, i32 8, i1 false)</div><div>  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %y, i8* %1, i64 16, i32 8, i1 false)</div><div>  call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 16, i32 8, i1 false)</div><div>  ret void</div><div>}</div><div><br></div><div>In order (and this is not even the only way to do this)<br></div><div><br></div><div>The store of the zero initializer is processed, you walk the use def chain, discover it is all zeroes. It is replaced with a memset. Since you are replacing a single store with a single memset, it works fine.</div><div><br>You go to the next store.</div><div>You walk the use use-def chain from the memorydef at 3, stopping at each piece, and seeing what info it provides, by examining the instruction. For each definingAccess, you can examine the uses to see if they provide loads that similarly fill in part of the range.</div><div>You discover that 0, 16 has value %1 coming from a load, and 16, 54 is coming from zero.</div></div><div><br>You create the memcpy and memset to make this happen, and replace the load and store.</div><div><br></div><div>None of this *requires* inserting and then later worrying about things.</div><div><br></div><div>What am i missing?<br><br></div><div><br></div></div></div></div>
</blockquote></div><br></div>