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

Reply via email to