Testcase: union a { int i; float f; }; void f(float *a, int *b, float e) { union a c; c.f = *a + e; *b = c.i; }
--- CUT --- Currently we get (on x86): subl $28, %esp movl 32(%esp), %eax flds 40(%esp) fadds (%eax) movl 36(%esp), %eax fstps 12(%esp) <--- extra store movl 12(%esp), %edx <--- extra load movl %edx, (%eax) <--- store result to *b addl $28, %esp ret Or with -mfpmath=sse: _f: subl $28, %esp movl 32(%esp), %eax movss 40(%esp), %xmm0 addss (%eax), %xmm0 movl 36(%esp), %eax movss %xmm0, 12(%esp) <--- extra store movl 12(%esp), %edx <--- extra load movl %edx, (%eax) <---store result to *b addl $28, %esp ret Or on PPC: f: lfs 0,0(3) stwu 1,-16(1) fadds 0,1,0 stfs 0,8(1) <--- extra store lwz 0,8(1) <--- extra load addi 1,1,16 stw 0,0(4) <--- store result to *b blr The issue is that SFmode cannot be in integer registers. The rtl looks like: (insn 8 7 9 3 t1.c:10 (set (reg:SF 124) (mem:SF (reg/v/f:SI 120 [ a ]) [2 S4 A32])) -1 (nil)) (insn 9 8 10 3 t1.c:10 (set (reg:SF 123) (plus:SF (reg/v:SF 122 [ e ]) (reg:SF 124))) -1 (nil)) (insn 10 9 11 3 t1.c:10 (set (subreg:SF (reg/v:SI 119 [ c ]) 0) (reg:SF 123)) -1 (nil)) (insn 11 10 16 3 t1.c:11 (set (mem:SI (reg/v/f:SI 121 [ b ]) [3 S4 A32]) (reg/v:SI 119 [ c ])) -1 (nil)) See how we could translate register 119 (SImode) into a register that is in SFmode and get away with it. -- Summary: Extra load/store for float with union Product: gcc Version: 4.3.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: enhancement Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: pinskia at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33989