<div dir="ltr"><div><div>Hi Jay -<br><br></div>I'm surprised by the codegen for your examples too, but LLVM has an expectation that a front-end and IR optimizer will use llvm.memcpy liberally:<br><a href="http://llvm.org/docs/doxygen/html/SelectionDAGBuilder_8cpp_source.html#l00094" target="_blank">http://llvm.org/docs/doxygen/html/SelectionDAGBuilder_8cpp_source.html#l00094</a><br><a href="http://llvm.org/docs/doxygen/html/SelectionDAGBuilder_8cpp_source.html#l03156" target="_blank">http://llvm.org/docs/doxygen/html/SelectionDAGBuilder_8cpp_source.html#l03156</a><br><pre class=""><span class="">"Any ld-ld-st-st sequence over this should have been converted to llvm.memcpy by the frontend."</span><span class=""></span><br>"The optimizer should really avoid this case by converting large object/array copies to llvm.memcpy"<br></pre><br>So for example with clang:<br><br>$ cat copy.c <br>struct bagobytes {<br>    int i0;<br>    int i1;<br>};<br><br>void foo(struct bagobytes* a, struct bagobytes* b) {<br>    *b = *a;<br>}<br><br>$ clang -O2 copy.c -S -emit-llvm -Xclang -disable-llvm-optzns -o -<br>define void @foo(%struct.bagobytes* %a, %struct.bagobytes* %b) #0 {<br>...<br>  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %3, i64 8, i32 4, i1 false), !tbaa.struct !6<br>  ret void<br>}<br><br></div>It may still be worth filing a bug (or seeing if one is already open) for one of your simple examples.<br><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 29, 2015 at 6:08 PM, Jay McCarthy via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I am a first time poster, so I apologize if this is an obvious<br>
question or out of scope for LLVM. I am an LLVM user. I don't really<br>
know anything about hacking on LLVM, but I do know a bit about<br>
compilation generally.<br>
<br>
I am on x86-64 and I am interested in structure reads, writes, and<br>
constants being optimized to use vector registers when the alignment<br>
and sizes are right. I have created a gist of a small example:<br>
<br>
<a href="https://gist.github.com/jeapostrophe/d54d3a6a871e5127a6ed" rel="noreferrer" target="_blank">https://gist.github.com/jeapostrophe/d54d3a6a871e5127a6ed</a><br>
<br>
The assembly is produced with<br>
<br>
llc -O3 -march=x86-64 -mcpu=corei7-avx<br>
<br>
The key idea is that we have a structure like this:<br>
<br>
%athing = type { float, float, float, float, float, float, i16, i16,<br>
i8, i8, i8, i8 }<br>
<br>
That works out to be 32 bytes, so it can fit in YMM registers.<br>
<br>
If I have two pointers to arrays of these things:<br>
<br>
@one = external global %athing<br>
@two = external global %athing<br>
<br>
and then I do a copy from one to the other<br>
<br>
  %a = load %athing* @two<br>
  store %athing %a, %athing* @one<br>
<br>
Then the code that is generated uses the XMM registers for the floats,<br>
but does 12 loads and then 12 stores.<br>
<br>
In contrast, if I manually cast to a properly sized float vector I get<br>
the desired single load and single store:<br>
<br>
  %two_vector = bitcast %athing* @two to <8 x float>*<br>
  %b = load <8 x float>* %two_vector<br>
  %one_vector = bitcast %athing* @one to <8 x float>*<br>
  store <8 x float> %b, <8 x float>* %one_vector<br>
<br>
The rest of the file demonstrates that the code for modifying these<br>
vectors is pretty good, but has examples of bad ways to initialize the<br>
structure and a good way to initialize it. If I try to store a<br>
constant struct, I get 13 stores. If I try to assemble a vector by<br>
casting <2 x i16> to float then <4 x i8> to float and installing them<br>
into a single <8 x float>, I do get the desired single store, but I<br>
get very complicated constants that are loaded from memory. In<br>
contrast, if I bitcast the <8 x float> to <16 x i16> and <32 x i8> as<br>
I go, then I get the desired initialization with no loads and just<br>
modifications of the single YMM register. (Even this last one,<br>
however, doesn't have the best assembly because the words and bytes<br>
are not inserted into the vector simultaneously, but instead<br>
individually.)<br>
<br>
I am kind of surprised that the obvious code didn't get optimized the<br>
way I expected and even the tedious version of the initialization<br>
isn't optimal either. I would like to know if a transformation of one<br>
to the other is feasible in LLVM (I know anything is possible, but<br>
what is feasible in this situation?) or if I should implement a<br>
transformation like this in my front-end and settle for the<br>
initialization that comes out.<br>
<br>
Thank you for your time,<br>
<br>
Jay<br>
<br>
--<br>
Jay McCarthy<br>
Associate Professor<br>
PLT @ CS @ UMass Lowell<br>
<a href="http://jeapostrophe.github.io" rel="noreferrer" target="_blank">http://jeapostrophe.github.io</a><br>
<br>
           "Wherefore, be not weary in well-doing,<br>
      for ye are laying the foundation of a great work.<br>
And out of small things proceedeth that which is great."<br>
                          - D&C 64:33<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div><br></div>