from http://embed.cs.utah.edu/embarrassing/dec_09/harvest/gcc-head_llvm-gcc-head/ union __anonunion___u_19 { double __d; int __i[2]; }; extern __attribute__ ((__nothrow__)) int __signbit (double __x) __attribute__ ((__const__)); extern __attribute__ ((__nothrow__)) int __signbit (double __x) __attribute__ ((__const__)); extern int __signbit (double __x) { union __anonunion___u_19 __u; { __u.__d = __x; return (__u.__i[1] < 0); } } /* Checksum = AEFB9790 */ generates with -O2 -m32 -fomit-frame-pointer subl $12, %esp fldl 16(%esp) fstpl (%esp) movl 4(%esp), %eax addl $12, %esp shrl $31, %eax ret the move through the x87 stack and the local frame is totally unnecessary; the shr could be just done on the input stack value in comparison llvm generates the much neater: 0: 0f b7 44 24 0c movzwl 0xc(%esp),%eax 5: c1 e8 0f shr $0xf,%eax 8: c3 ret
;; __u.__d = __x_1(D); (insn 6 5 0 t.c:15 (set (subreg:DF (reg/v:DI 60 [ __u ]) 0) (reg/v:DF 62 [ __x ])) -1 (nil)) That causes a reload to happen: Reload 0: reload_out (DF) = (subreg:DF (reg/v:DI 60 [ __u ]) 0) FLOAT_REGS, RELOAD_FOR_OUTPUT (opnum = 0) reload_out_reg: (subreg:DF (reg/v:DI 60 [ __u ]) 0) reload_reg_rtx: (reg:DF 8 st) I think I might have another bug about this issue before ...
Here is an example which shows the issue on PPC also: union __anonunion___u_19 { double __d; int __i[2]; }; extern int __signbit (double *__x) { union __anonunion___u_19 __u; { __u.__d = *__x; return (__u.__i[1] < 0); } }
This is related to PR 33989.
Fixed in 4.9.0+ Before: (insn 6 3 7 2 (set (subreg:DF (reg/v:DI 62 [ __u ]) 0) (reg/v:DF 64 [ __x ])) /app/example.c:15 -1 (nil)) After: (insn 6 3 7 2 (set (reg/v:DI 86 [ __u ]) (subreg:DI (reg/v:DF 88 [ __x ]) 0)) /app/example.c:15 -1 (nil)) Which means it was fixed by r0-126192.