<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 28, 2018, at 6:18 PM, Philip Reames <<a href="mailto:listmail@philipreames.com" class="">listmail@philipreames.com</a>> wrote:</div><div class=""><div text="#000000" bgcolor="#FFFFFF" class=""><p class="">On 02/27/2018 10:21 AM, Alex Wang via
      llvm-dev wrote:</p>
    <blockquote type="cite" cite="mid:75E6CCB8-0A96-4577-A0A2-30C04B81D64F@gmail.com" class="">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252" class="">
      Hello all!<br class="">
      <br class="">
      I was looking through the results of disassembling a heavily-used
      short function<br class="">
      in the program I'm working on, and ended up wondering why LLVM was
      generating<br class="">
      that assembly and what changes would be necessary to improve the
      code. I asked<br class="">
      on #llvm, but it seems that the people with the necessary
      expertise weren't<br class="">
      around.<br class="">
      <br class="">
      Here is a condensed version of the code: <a href="https://godbolt.org/g/ec5cP7" class="" moz-do-not-send="true">https://godbolt.org/g/ec5cP7</a><br class="">
      <br class="">
      My main question concerns assembly lines 37/38 and 59/60, where
      xmm0 is spilled<br class="">
      to the stack, only to be immediately reloaded into xmm1. Google
      tells me that<br class="">
      there is a register-to-register mov instruction for the xmmn
      registers, so I<br class="">
      found it odd that LLVM missed what looks like an easy
      optimization. tstellar on<br class="">
      #llvm pointed me towards using -debug-only=regalloc with llc to
      see what LLVM is<br class="">
      thinking (regalloc log here, since I'm not sure what's considered
      "too large"<br class="">
      for mailing lists: [0]), and it seemed to me like the load/store
      were<br class="">
      introduced separately, and llc never looked at them at the same
      time, and so<br class="">
      never realized that they could be folded. Is that what is
      happening? I know<br class="">
      little about compilers, so I wouldn't be surprised if I were
      wrong.<br class="">
    </blockquote>
    I don't have time to dig into this in detail, but you're heading in
    the right direction if you're looking at regalloc tracing.  This
    vaguely looks like something related to phi lowering, so you might
    want to check what the MIR looks like immediately before regalloc as
    well.<br class=""></div></div></blockquote><br class=""><div>Apparently it's the greedy register allocation pass that results in the</div><div>spill/reload? If I'm reading the MIR files right, before the pass the MIR is</div><div><br class=""></div><div>    ; ...</div><div>    %36:fr64 = MULSDrr %36, %32</div><div>    %41:fr64 = ADDSDrr %41, %36</div><div>    %40:gr64_nosp = INC64r %40, implicit-def dead $eflats</div><div>    ; ...</div><div><br class=""></div><div>And after:</div><div><br class=""></div><div>    ; ...</div><div>    %36:fr64 = MULSDrm %36, %stack.2, 1, $noreg, 0, $noreg :: (load 8 from %stack.2)</div><div>    %47:fr64 = MOVSDrm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)</div><div>    %47:fr64 = ADDSDrr %47, %36</div><div>    MOVSDmr %stack.0, 1, $noreg, 0, $noreg, %47 :: (store 8 into %stack.0)</div><div>    %45:fr64 = MOVSDrm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)</div><div>    %40:gr64_nosp = INC64r %40, implicit-def dead $eflags</div><div>    ; ...</div><div><br class=""></div><div>So I guess that's a good place to start. Unfortunately, I have no clue whether</div><div>the fix should be in RegAllocGreedy.cpp or if it should be taken care of</div><div>elsewhere.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class="">
    <blockquote type="cite" cite="mid:75E6CCB8-0A96-4577-A0A2-30C04B81D64F@gmail.com" class=""><br class="">
      The other two questions are tangential, so please let me know if I
      should ask<br class="">
      them somewhere else.<br class="">
      <br class="">
      On assembly lines 24 and 46, I think the vtable pointer for the
      Quad object is<br class="">
      being reloaded every iteration of the loop. nbjoerg on #llvm said
      that's due to<br class="">
      the possibility of placement new being used somewhere inside the
      called<br class="">
      function, which makes sense to me. Is there a way to indicate to
      LLVM that this<br class="">
      will not happen? I tried [[gnu::pure]], since the function doesn't
      write to<br class="">
      externally-visible memory, but the vtable pointer reload remained.<br class="">
    </blockquote>
    I don't know that we have anything like this, but we totally should
    if we don't.  You're more likely to get a useful answer if you send
    this separately to cfe-dev though.  The clang frontend devs don't
    tend to read emails apparently about register allocation.  :)<br class="">
    <br class=""></div></div></blockquote><div><br class=""></div><div><div>Alright, I'll head on over to cfe-dev to see if that functionality is</div><div>available/implemented.</div></div><br class=""><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class="">
    If you want to assist with the devirt directly, you could capture
    the member pointer on the first iteration, then reuse.  This does
    require that all Nodes in your array are the exact same type though!<br class=""></div></div></blockquote><div><br class=""></div><div>Just to ensure I'm reading you right, are you talking about something like:</div><div><br class=""></div><div>    auto f = &Rect::GetLocalValue;</div><div>    for (...) {</div><div>        // ...</div><div>        const double localVal = (this->*f)(i, local, gauss);</div><div>    }</div><div><br class=""></div><div>?</div><div><br class=""></div><div><div>If so, I've tried something along those lines already, and the vtable pointer</div><div>reload remained inside the loop. I've also tried capturing this into a local</div><div>pointer, and capturing into a lambda. None of those got Clang to hoist the</div><div>vtable pointer load out of the loop. I wouldn't be surprised if I were barking</div><div>up the wrong tree, though.</div></div><br class=""><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class="">
    <blockquote type="cite" cite="mid:75E6CCB8-0A96-4577-A0A2-30C04B81D64F@gmail.com" class=""><br class="">
      Finally, I'm inclined to say that this routine should be
      vectorizable, since<br class="">
      it's essentially just an accumulate, but Clang can't prove that
      GetLocalValue<br class="">
      doesn't have side effects that will affect later iterations. Is
      this correct,<br class="">
      and if so, are there any hints I can give Clang besides just
      manually<br class="">
      parallelizing it with #pragma omp or something?<br class="">
    </blockquote>
    To clarify, is the the GetLocalValue in your example?  Or some more
    complicated version?  It depends a lot on what IPO can conclude
    about the function.  You can also manually annotate the initial IR,
    but I don't know how to do that from clang.  </div></div></blockquote><div><br class=""></div><div>I was wondering if GetValue() was vectorizable. The version on godbolt is</div><div>basically the same as the original, and the generated assembly is more or less</div><div>the same, modulo member offsets. GetLocalValue is a "true" pure function, in</div><div>that it does some math based only on its arguments, but it seems that's not</div><div>getting picked up, even with -flto. Maybe it's the virtual-ness preventing</div><div>deeper analysis?</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class=""><blockquote type="cite" cite="mid:75E6CCB8-0A96-4577-A0A2-30C04B81D64F@gmail.com" class="">
      I do intend on changing this loop to something a bit less messy,
      but it'll be<br class="">
      part of a larger refactoring, so it's still a ways off.<br class="">
      <br class="">
      Thanks!
      <div class=""><br class="">
      </div>
      <div class="">Alex<br class="">
        <br class="">
           [0]: <a href="https://hastebin.com/raw/oqamesahos" class="" moz-do-not-send="true">https://hastebin.com/raw/oqamesahos</a></div>
      <br class="">
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br class="">
      <pre wrap="" class="">_______________________________________________
LLVM Developers mailing list
<a class="moz-txt-link-abbreviated" href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>
<a class="moz-txt-link-freetext" href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a>
</pre>
    </blockquote>
    <br class="">
  </div>

</div></blockquote></div><br class=""></body></html>