<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - std::pair<int, float> are combined as an int64 first before being stored to memory"
   href="https://llvm.org/bugs/show_bug.cgi?id=28726">28726</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>std::pair<int, float> are combined as an int64 first before being stored to memory
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Scalar Optimizations
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>wmi@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>testcase 1.cc
------------------------------------------------------
#include <utility>

void goo(const std::pair<int, float> &pr);

void foo(int index_offset, int i, float dsqs[]) {
  float tmp = dsqs[0] + 3.0;
  goo(std::make_pair(index_offset + i + 0, tmp));
  asm volatile ("":::"memory");  
}
------------------------------------------------------
The last asm stmt is to prevent llvm from doing tail call opt (gcc doesn't do
tail call opt), so as to make instructions comparison between llvm and gcc a
little easier. 

~/workarea/gcc-r233722/build/install/bin/g++ -O2 -S 1.cc
gcc code:
        .cfi_startproc
        subq    $24, %rsp
        .cfi_def_cfa_offset 32
        addl    %esi, %edi
        movss   .LC0(%rip), %xmm0
        movl    %edi, (%rsp)
        movq    %rsp, %rdi
        addss   (%rdx), %xmm0
        movss   %xmm0, 4(%rsp)
        call    _Z3gooRKSt4pairIifE
        addq    $24, %rsp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc

~/workarea/llvm-r275818/dbuild/bin/clang++ -O2 -S 1.cc
llvm code:
        .cfi_startproc
# BB#0:                                 # %entry
        pushq   %rax
.Ltmp0:
        .cfi_def_cfa_offset 16
        movss   (%rdx), %xmm0           # xmm0 = mem[0],zero,zero,zero
        addss   .LCPI0_0(%rip), %xmm0
        movd    %xmm0, %eax
        addl    %esi, %edi
        shlq    $32, %rax
        orq     %rax, %rdi
        movq    %rdi, (%rsp)
        leaq    (%rsp), %rdi
        callq   _Z3gooRKSt4pairIifE
        popq    %rax
        retq

gcc generates two instructions less than llvm.

>From asm code, we can see that llvm tries to bundle an int and a float into a
int64 and store the int64 into memory. It is better to save int and float into
memory using separate stores so the bitwise instructions to generate the int64
can be removed.

The bitwise instructions to generate the int64 bundle are generated by SROA for
std::make_pair, but I think SROA generates correct code there because frontend
already uses i64 as the return type of std::make_pair. Since SROA for
std::make_pair is done before std::make_pair is inlined into foo, it is
impossible for SROA to know the i64 returned by std::make_pair has only been
used in a store.

The return value of std::make_pair has already been i64 from the very beginning
of llvm pipeline: 
*** IR Dump After Module Verifier ***
define linkonce_odr i64 @_ZSt9make_pairIifESt4pairIT_T0_ES1_S2_(i32 %__x, float
%__y) local_unnamed_addr #3 comdat {
  ...
}

I guess it is instcombine to be enhanced to split the int64 store because it
can see the combined int64 value has not been used elsewhere other than in the
store after std::make_pair is inlined.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>