extern void abort (void); _Complex v = 3.0 + 1.0iF;
void foo (_Complex z, int *x) { if (z != v) abort (); } _Complex bar (_Complex z) __attribute__ ((pure)); _Complex bar (_Complex z) { return v; } int baz (void) { int a, i; for (i = 0; i < 6; i++) foo (bar (1.0iF * i), &a); return 0; } int main () { baz (); return 0; } is miscompiled at -O1 -m32 or -O2 -m32. This was fixed in 4.2 and on the trunk with PR25505 changes (the tree-nrv.c change most importantly), NRV in this case is really a wrong thing to do, as target is _Complex at virtual-outgoing-regs, but those are also used for the call. Furthermore GCC then incorrectly computes where the region actually was: (insn 26 25 27 2 (set (mem/i:DF (plus:SI (reg/f:SI 56 virtual-outgoing-args) (const_int 4 [0x4])) [0 S8 A32]) (float_extend:DF (reg:SF 69))) -1 (nil) (nil)) (insn 27 26 28 2 (set (mem/i:DF (plus:SI (reg/f:SI 56 virtual-outgoing-args) (const_int 12 [0xc])) [0 S8 A32]) (reg:DF 68)) -1 (nil) (nil)) (insn 28 27 29 2 (set (mem:SI (reg/f:SI 56 virtual-outgoing-args) [0 S4 A32]) (reg/f:SI 56 virtual-outgoing-args)) -1 (nil) (nil)) (call_insn 29 28 30 2 (parallel [ (call (mem:QI (symbol_ref:SI ("bar") [flags 0x3] <function_decl 0x2aaaaea20400 bar>) [0 S1 A8]) (const_int 20 [0x14])) (set (reg/f:SI 7 sp) (plus:SI (reg/f:SI 7 sp) (const_int 4 [0x4]))) ]) -1 (nil) (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)) (nil)) (insn 30 29 31 2 (parallel [ (set (reg/f:SI 7 sp) (plus:SI (reg/f:SI 7 sp) (const_int -4 [0xfffffffffffffffc]))) (clobber (reg:CC 17 flags)) ]) -1 (nil) (nil)) (insn 31 30 32 2 (set (reg:DF 70) (mem/c/i:DF (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -32 [0xffffffffffffffe0])) [2 S8 A64])) -1 (nil) (nil)) (insn 32 31 33 2 (set (mem:DF (plus:SI (reg/f:SI 56 virtual-outgoing-args) (const_int 4 [0x4])) [0 S8 A8]) (reg:DF 70)) -1 (nil) (nil)) (insn 33 32 34 2 (set (reg:DF 71) (mem/c/i:DF (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -24 [0xffffffffffffffe8])) [2 S8 A64])) -1 (nil) (nil)) (insn 34 33 35 2 (set (mem:DF (plus:SI (reg/f:SI 56 virtual-outgoing-args) (const_int 12 [0xc])) [0 S8 A8]) (reg:DF 71)) -1 (nil) (nil)) So, it stores the return value to %esp (== %ebp - 68 at that point) and loads from %ebp - 40. -- Summary: [4.1 Regression] Miscompilation with pure _Complex returning call inside another fn's argument list Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jakub at gcc dot gnu dot org GCC target triplet: i686-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32285