https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100694

            Bug ID: 100694
           Summary: PPC: initialization of __int128 is very inefficient
           Product: gcc
           Version: 8.3.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jens.seifert at de dot ibm.com
  Target Milestone: ---

Initializing a __int128 from 2 64-bit integers is implemented very inefficient.

The most natural code which works good on all other platforms generate
additional 2 li 0 + 2 or instructions.

void test2(unsigned __int128* res, unsigned long long hi, unsigned long long
lo)
{
   unsigned __int128 i = hi;
   i <<= 64;
   i |= lo;
   *res = i;
}

_Z5test2Poyy:
.LFB15:
        .cfi_startproc
        li 8,0
        li 11,0
        or 10,5,8
        or 11,11,4
        std 10,0(3)
        std 11,8(3)
        blr
        .long 0
        .byte 0,9,0,0,0,0,0,0
        .cfi_endproc


While for the above sample, "+" instead "|" solves the issues, it generates
addc+addz in other more complicated scenarsion.

The most ugly workaround I can think of I now use as workaround.

void test4(unsigned __int128* res, unsigned long long hi, unsigned long long
lo)
{
   union
   { unsigned __int128 i;
        struct
   {
     unsigned long long lo;
     unsigned long long hi;
   } s;
   } u;
   u.s.lo = lo;
   u.s.hi = hi;
   *res = u.i;
}

This generates the expected code sequence in all cases I have looked at.

_Z5test4Poyy:
.LFB17:
        .cfi_startproc
        std 5,0(3)
        std 4,8(3)
        blr
        .long 0
        .byte 0,9,0,0,0,0,0,0
        .cfi_endproc

Please merge li 0 + or to nop.
  • [Bug target/100694] New: PPC: ... jens.seifert at de dot ibm.com via Gcc-bugs

Reply via email to