Compile the following with -m64 -mlong-double-128 -O2 -S long double pack (double a, double aa) { union { long double ld; double d[2]; } u; u.d[0] = a; u.d[1] = aa; return u.ld; }
void unpack (long double x, double *a, double *aa) { union { long double ld; double d[2]; } u; u.ld = x; *a = u.d[0]; *aa = u.d[1]; } Results in [snip] .L.pack: stfd 1,-176(1) stfd 14,-144(1) nop nop ld 9,-176(1) stfd 2,-176(1) std 9,-160(1) nop ld 10,-176(1) std 10,-152(1) lfd 13,-160(1) fmr 1,13 lfd 14,-152(1) fmr 2,14 lfd 14,-144(1) blr [snip] .L.unpack: stfd 1,-16(1) stfd 2,-8(1) nop nop ld 11,-16(1) ld 12,-8(1) std 11,0(5) std 12,0(6) blr This ought to be .L.pack: blr .L.unpack: stfd 1,0(5) stfd 2,0(6) blr ie. packing and unpacking long doubles ought to be nops. Instead we see needless moving between fprs and gprs via memory. This problem affects functions like __gcc_qadd from rs6000/darwin-ldouble.c -- Summary: pack and unpack of long doubles via union generates poor code Product: gcc Version: 4.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: amodra at bigpond dot net dot au GCC target triplet: powerpc64-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25972