title: Why does GAS inline assembly wrapped in a function generate different instructions for the caller than a pure assembly function
body: <p>I've been writing some basic functions using GCC's <code>asm</code> to practice for an actual application.</p>
  
  <p>My functions <code>pretty</code>, <code>wrap</code>, and <code>pure</code> generate the same instructions to unpack a 64 bit integer into a 128 bit vector. <code>add1</code> and <code>add2</code> which call <code>pretty</code> and <code>wrap</code> respectively also generate the same instructions. But <code>add3</code> differs by saving its <code>xmm0</code> register by pushing it to the stack rather than by copying it to another <code>xmm</code> register. This I don't understand because the compiler can see the details of <code>pure</code> to know none of the other <code>xmm</code> registers will be clobbered.</p>
  
  <p>Here is the C++</p>
  
  <pre><code>#include &lt;immintrin.h&gt;
  
  __m128i pretty(long long b) { return (__m128i){b,b}; }
  
  __m128i wrap(long long b) {
      asm ("mov qword ptr [rsp-0x10], rdi\n"
           "vmovddup xmm0, qword ptr [rsp-0x10]\n"
           :
           : "r"(b)
           );
  }
  
  extern "C" __m128i pure(long long b);
  asm (".text\n.global pure\n\t.type pure, @function\n"
       "pure:\n\t"
       "mov qword ptr [rsp-0x10], rdi\n\t"
       "vmovddup xmm0, qword ptr [rsp-0x10]\n\t"
       "ret\n\t"
       );
  
  __m128i add1(__m128i in, long long in2) { return in + pretty(in2);}
  __m128i add2(__m128i in, long long in2) { return in + wrap(in2);}
  __m128i add3(__m128i in, long long in2) { return in + pure(in2);}
  </code></pre>
  
  <p>Compiled with <code>g++ -c  so.cpp -march=native   -masm=intel -O3 -fno-inline</code> and disassembled with <code>objdump -d -M intel so.o | c++filt</code>.</p>
  
  <pre><code>so.o:     file format elf64-x86-64
  
  
  Disassembly of section .text:
  
  0000000000000000 &lt;pure&gt;:
     0:   48 89 7c 24 f0          mov    QWORD PTR [rsp-0x10],rdi
     5:   c5 fb 12 44 24 f0       vmovddup xmm0,QWORD PTR [rsp-0x10]
     b:   c3                      ret
     c:   0f 1f 40 00             nop    DWORD PTR [rax+0x0]
  
  0000000000000010 &lt;pretty(long long)&gt;:
    10:   48 89 7c 24 f0          mov    QWORD PTR [rsp-0x10],rdi
    15:   c5 fb 12 44 24 f0       vmovddup xmm0,QWORD PTR [rsp-0x10]
    1b:   c3                      ret
    1c:   0f 1f 40 00             nop    DWORD PTR [rax+0x0]
  
  0000000000000020 &lt;wrap(long long)&gt;:
    20:   48 89 7c 24 f0          mov    QWORD PTR [rsp-0x10],rdi
    25:   c5 fb 12 44 24 f0       vmovddup xmm0,QWORD PTR [rsp-0x10]
    2b:   c3                      ret
    2c:   0f 1f 40 00             nop    DWORD PTR [rax+0x0]
  
  0000000000000030 &lt;add1(long long __vector(2), long long)&gt;:
    30:   c5 f8 28 c8             vmovaps xmm1,xmm0
    34:   48 83 ec 08             sub    rsp,0x8
    38:   e8 00 00 00 00          call   3d &lt;add1(long long __vector(2), long long)+0xd&gt;
    3d:   48 83 c4 08             add    rsp,0x8
    41:   c5 f9 d4 c1             vpaddq xmm0,xmm0,xmm1
    45:   c3                      ret
    46:   66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
    4d:   00 00 00
  
  0000000000000050 &lt;add2(long long __vector(2), long long)&gt;:
    50:   c5 f8 28 c8             vmovaps xmm1,xmm0
    54:   48 83 ec 08             sub    rsp,0x8
    58:   e8 00 00 00 00          call   5d &lt;add2(long long __vector(2), long long)+0xd&gt;
    5d:   48 83 c4 08             add    rsp,0x8
    61:   c5 f9 d4 c1             vpaddq xmm0,xmm0,xmm1
    65:   c3                      ret
    66:   66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
    6d:   00 00 00
  
  0000000000000070 &lt;add3(long long __vector(2), long long)&gt;:
    70:   48 83 ec 18             sub    rsp,0x18
    74:   c5 f8 29 04 24          vmovaps XMMWORD PTR [rsp],xmm0
    79:   e8 00 00 00 00          call   7e &lt;add3(long long __vector(2), long long)+0xe&gt;
    7e:   c5 f9 d4 04 24          vpaddq xmm0,xmm0,XMMWORD PTR [rsp]
    83:   48 83 c4 18             add    rsp,0x18
    87:   c3                      ret
  </code></pre>