On Fri, Apr 27, 2007 at 08:24:11AM -0700, Richard Henderson wrote: > This doesn't look like frame pointer elimination at all, > just different stack slots allocated. But that said, if > there's a bug in elimination, it should be fixed, not > hacked around in one backend.
$ ./xgcc -B./ ~/cvssrc/gcc/gcc/testsuite/gcc.dg/20020210-1.c \ -O2 -sim=linuxvm86 -o /tmp/20020210-1-fp -fno-omit-frame-pointer $ /tmp/20020210-1-fp; echo $? 0 $ ./xgcc -B./ ~/cvssrc/gcc/gcc/testsuite/gcc.dg/20020210-1.c \ -O2 -sim=linuxvm86 -o /tmp/20020210-1-nofp -fomit-frame-pointer $ /tmp/20020210-1-nofp; echo $? 1 Looking at the assembly, the failure with -fomit-frame-pointer (the default) is no surprice: --- 20020210-1-fp.s 2007-05-01 19:16:29.000000000 +0200 +++ 20020210-1-nofp.s 2007-05-01 19:16:23.000000000 +0200 @@ -21,16 +21,15 @@ .type foo, @function foo: pushw %bp - movw %sp, %bp subw $10, %sp - pushw 12(%bp) - pushw 10(%bp) - pushw 8(%bp) - pushw 6(%bp) - pushw 4(%bp) + movw %sp, %bp + pushw 22(%bp) + pushw 22(%bp) + pushw 22(%bp) + pushw 22(%bp) + pushw 22(%bp) call bar - addw $10, %sp - movw %bp, %sp + addw $20, %sp popw %bp ret .size foo, .-foo void foo (int a, int b, int c, int d, int e) { bar (a, b, c, d, e); } .lreg dump shows: (insn:HI 12 8 13 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg/f:HI 14 argp) (const_int 10 [0xa])) [2 e+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) (insn:HI 13 12 14 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg/f:HI 14 argp) (const_int 8 [0x8])) [2 d+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) (insn:HI 14 13 15 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg/f:HI 14 argp) (const_int 6 [0x6])) [2 c+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) (insn:HI 15 14 16 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg/f:HI 14 argp) (const_int 4 [0x4])) [2 b+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) (insn:HI 16 15 17 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg/f:HI 14 argp) (const_int 2 [0x2])) [2 a+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) Register elimination is nothing out of the ordinary, but note that the stack pointer is not a valid base register. #define ELIMINABLE_REGS \ { { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } } .greg dump shows: ;; Function foo (foo) Spilling for insn 12. Using reg 10 for reload 0 Spilling for insn 13. Using reg 10 for reload 0 Spilling for insn 14. Using reg 10 for reload 0 Spilling for insn 15. Using reg 10 for reload 0 Spilling for insn 16. Using reg 10 for reload 0 Spilling for insn 17. Spilling for insn 12. Using reg 10 for reload 0 Spilling for insn 13. Using reg 10 for reload 0 Spilling for insn 14. Using reg 10 for reload 0 Spilling for insn 15. Using reg 10 for reload 0 Spilling for insn 16. Using reg 10 for reload 0 Spilling for insn 17. Reloads for insn # 12 Reload order: 0 1 Reload 0: reload_in (HI) = (reg/f:HI 12 sp) BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) reload_in_reg: (reg/f:HI 12 sp) reload_reg_rtx: (reg:HI 10 bp) Reload 1: reload_in (HI) = (mem/c/i:HI (plus:HI (reg/f:HI 12 sp) (const_int 22 [0x16])) [2 e+0 S2 A16]) SEG_GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 0), optional reload_in_reg: (mem/c/i:HI (plus:HI (reg/f:HI 12 sp) (const_int 22 [0x16])) [2 e+0 S2 A16]) Reloads for insn # 13 Reload order: 0 1 Reload 0: reload_in (HI) = (reg/f:HI 12 sp) BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) reload_in_reg: (reg/f:HI 12 sp) reload_reg_rtx: (reg:HI 10 bp) Reload 1: reload_in (HI) = (mem/c/i:HI (plus:HI (reg/f:HI 12 sp) (const_int 22 [0x16])) [2 d+0 S2 A16]) SEG_GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 0), optional reload_in_reg: (mem/c/i:HI (plus:HI (reg/f:HI 12 sp) (const_int 22 [0x16])) [2 d+0 S2 A16]) [...] (note:HI 8 7 30 2 NOTE_INSN_FUNCTION_BEG) (insn 30 8 12 2 (set (reg:HI 10 bp) (reg/f:HI 12 sp)) 23 {*movhi} (nil) (nil)) (insn:HI 12 30 13 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg:HI 10 bp) (const_int 22 [0x16])) [2 e+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) (insn:HI 13 12 14 2 (set (mem:HI (pre_dec:HI (reg/f:HI 12 sp)) [0 S2 A8]) (mem/c/i:HI (plus:HI (reg:HI 10 bp) (const_int 22 [0x16])) [2 d+0 S2 A16])) 30 {*pushhi1_086} (nil) (nil)) The reload insn 30 for insn 12 is being inherited by insn 13, but reload fails to notice that the stack pointer has changed. This happens in "real" code. I'll try to find a fix. -- Rask Ingemann Lambertsen