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.