title: clang (LLVM) inline assembly - multiple constraints with useless spills / reloads
body: <p><strong>clang / gcc</strong> : Some inline assembly operands can be satisfied with multiple constraints, e.g., <code>"rm"</code>, when an operand can be satisfied with a register or memory location. As an example, the 64 x 64 = 128 bit multiply:</p>
  
  <pre><code>__asm__ ("mulq %q3" : "=a" (rl), "=d" (rh) : "%0" (x), "rm" (y) : "cc")
  </code></pre>
  
  <p>The generated code appears to choose a memory constraint for argument <code>3</code>, which would be fine if we were register starved, to avoid a spill. Obviously there's less register pressure on x86-64 than on IA32. However, the assembly snippet generated (by <strong>clang</strong>) is:</p>
  
  <pre><code>    movq    %rcx, -8(%rbp)
      ## InlineAsm Start
      mulq -8(%rbp)
      ## InlineAsm End
  </code></pre>
  
  <p>Choosing a memory constraint is clearly pointless! Changing the constraint to: <code>"r" (y)</code>, however (forcing a register) we get:</p>
  
  <pre><code>    ## InlineAsm Start
      mulq %rcx
      ## InlineAsm End
  </code></pre>
  
  <p>as expected. These results are for clang / LLVM 3.2 (current Xcode release). The first question: <strong>Why would clang select the less efficient constraint in this case?</strong></p>
  
  <p>Secondly, there is the less widely used, comma-separated, <a href="http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Multi_002dAlternative.html#Multi_002dAlternative" rel="nofollow noreferrer">multiple alternative constraint</a> syntax:<br>
  <code>"r,m" (y)</code>, which <em>should</em> evaluate the costs of each alternative, and choose the one that results in less copying. This appears to work, <em>but clang simply chooses the first</em> - as evidenced by: <code>"m,r" (y)</code></p>
  
  <hr>
  
  <p>I could simply drop the <code>"m"</code> alternative constraints, but this doesn't express the range of possible legal operands. This brings me to the second question: <strong>Have these issues been resolved or at least acknowledged in 3.3?</strong> I've tried looking through LLVM dev archives, but I'd rather solicit some answers before unnecessarily restricting constraints further, or joining project discussions, etc.</p>