<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><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><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:<br><div>define void @noaliasaddrproducer(%S* %src, %S* noalias %dst, %S* noalias %dstidptr) {</div><div>  %1 = bitcast %S* %src to i8*</div><div>  %y = bitcast %S* %dstidptr to i8*</div><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>