[llvm-bugs] [Bug 28726] New: std::pair<int, float> are combined as an int64 first before being stored to memory

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Jul 26 18:06:07 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=28726

            Bug ID: 28726
           Summary: std::pair<int, float> are combined as an int64 first
                    before being stored to memory
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: wmi at google.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160727/7c063f3b/attachment.html>


More information about the llvm-bugs mailing list