This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Old loop optimizer clobbers frame pointer


Hello,

since a couple of weeks the 
  gcc.c-torture/execute/built-in-setjmp.c execution,  -O1
test case fails on s390-ibm-linux.

It turns out that this is due to a bug in the old loop optimizer
that got exposed somehow.  Before loop, we have the following
piece of RTL:

(note 132 27 28 0 NOTE_INSN_LOOP_BEG)

(jump_insn 28 132 29 0 (set (pc)
        (label_ref 36)) 318 {*jump31} (nil)
    (nil))
;; End of basic block 0, registers live:
 (nil)

(barrier 29 28 30)

;; Start of basic block 1, registers live: (nil)
(code_label/s 30 29 119 1 6 "" [1 uses])

(note 119 30 31 1 [bb 1] NOTE_INSN_BASIC_BLOCK)

(insn 31 119 32 1 (use (reg/f:SI 11 %r11)) -1 (nil)
    (nil))

(insn 32 31 126 1 (clobber (reg:SI 0 %r0)) -1 (nil)
    (nil))

(insn 126 32 34 1 (parallel [
            (set (reg/f:SI 34 %fp)
                (plus:SI (reg/f:SI 11 %r11)
                    (const_int -96 [0xffffffffffffffa0])))
            (clobber (reg:CC 33 %cc))
        ]) 143 {addsi3} (nil)
    (nil))

(insn 34 126 35 1 (asm_input ("")) -1 (nil)
    (nil))

(insn 35 34 36 1 (set (reg:SI 50 [ D.1232 ])
        (const_int 1 [0x1])) 47 {*movsi_esa} (nil)
    (nil))
;; End of basic block 1, registers live:
 (nil)

;; Start of basic block 2, registers live: (nil)
(code_label 36 35 120 2 7 "" [1 uses])

(note 120 36 37 2 [bb 2] NOTE_INSN_BASIC_BLOCK)


Note that insn 31-35 correspond to the non-local jump 'receiver' pad. 
On entry to that piece of code, register 11 (the hard frame pointer)
will hold the saved 'virtual-stack-rtx' value from the jump buffer.
Due to our stack bias, this value is in fact 96 bytes off from the
actual frame pointer value; insn 126 performs this correction
(register 34 is the frame pointer, which will be eliminated using
the hard frame pointer by reload).

Now, the bug is caused by move_movables in reload.c hoisting this
insn 126 to before note 132.  At the place of insn 126 the value
will be copied from a pseudo.  However, since accessing pseudos
doesn't work properly before the frame pointer is set up correctly,
this breaks.

It is clear that this instruction certainly should not be hoisted.
The question is, what is the correct way to resolve the problem.

One weird thing is the placement of the loop begin/end notes.
Apparently the jump over the setjmp receiver pad was interpreted
as jump over the initial condition test of a loop, which it
really isn't.

Also, register 11 is, strictly speaking, not loop-invariant,
because it has a different value between label 30 and insn 126
than in all the rest of the function.  However, the hard frame
pointer is always considered invariant.

Finally, an instruction *setting* the frame pointer should
really always be treated with care since there are so many
implicit dependencies on the frame pointer.

I've implemented a patch for the latter option, which seemed
to be least invasive.  This fixes my problem.  What do you think?

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
OK for mainline?

ChangeLog:

	* loop.c (scan_loop): Do not consider insns setting the frame
	pointer to be candidates for hoisting.

Index: gcc/loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.531
diff -c -p -r1.531 loop.c
*** gcc/loop.c	31 May 2005 21:29:05 -0000	1.531
--- gcc/loop.c	1 Jun 2005 23:33:08 -0000
*************** scan_loop (struct loop *loop, int flags)
*** 1135,1140 ****
--- 1135,1141 ----
  	  if (! in_libcall
  	      && (set = single_set (p))
  	      && REG_P (SET_DEST (set))
+ 	      && SET_DEST (set) != frame_pointer_rtx
  #ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
  	      && SET_DEST (set) != pic_offset_table_rtx
  #endif
-- 
  Dr. Ulrich Weigand
  Linux on zSeries Development
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]