gcse bugfix [ Fixes libg++ PA test failures ]

Jeffrey A Law law@cygnus.com
Thu Jun 3 00:17:00 GMT 1999

This fixes the tFile testsuite failures for libg++ on PA platforms.

One of the interesting problems in the existing gcse code is the need to be
able to add instructions at the end of a basic block.  Consider the case where
a block ends with a function call that might throw an exception.

It is incorrect to place instruction(s) after the call (since if the call 
an exception the instruction(s) after the call will not be executed).

It is incorrect to place the instruction(s) immediately before a call as
the instruction may clobber a parameter register.

The gcse combats this situation by trying to place instrutions immediately
before any argument setup if a function ends with a call that might throw.

Of course it has to search backwards from the call to find the argument setup.

Here's the existing code:
      /* Search backward for the first set of a register in this set.  */
      while (nparm_regs && BLOCK_HEAD (bb) != insn)
          insn = PREV_INSN (insn);
          p = single_set (insn);
          if (p && GET_CODE (SET_DEST (p)) == REG
              && TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
              CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));

      new_insn = emit_insn_before (pat, insn);
      if (BLOCK_HEAD (bb) == insn)
        BLOCK_HEAD (bb) = new_insn;

Consider what happens if we have a basic block that starts with a CODE_LABEL
(as many do) and we are unable to find all the argument register setup insns.

We will exit the while loop with insn == BLOCK_HEAD(bb) == CODE_LABEL.  And
we will place the new instructions *BEFORE* the code label -- effectively
putting them into the wrong basic block.  Opps.  This causes bad things
to happen.

This patch solves the problem by never placing insns before a CODE_LABEL that
begins a basic block.

	* gcse.c (insert_insn_end_bb): Correct placement of insns when the
	current block starts with a CODE_LABEL and ends with a CALL and
	we can not find all the argument setup instructions for the CALL.

Index: gcse.c
RCS file: /egcs/carton/cvsfiles/egcs/gcc/gcse.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 gcse.c
*** gcse.c	1999/05/09 12:25:03	1.38
--- gcse.c	1999/06/03 07:05:00
*************** insert_insn_end_bb (expr, bb, pre)
*** 4189,4197 ****
!       new_insn = emit_insn_before (pat, insn);
!       if (BLOCK_HEAD (bb) == insn)
! 	BLOCK_HEAD (bb) = new_insn;
--- 4189,4214 ----
!       /* If we found all the parameter loads, then we want to insert
! 	 before the first parameter load.
! 	 If we did not find all the parameter loads, then we might have
! 	 stopped on the head of the block, which could be a CODE_LABEL.
! 	 If we inserted before the CODE_LABEL, then we would be putting
! 	 the insn in the wrong basic block.  In that case, put the insn
! 	 after the CODE_LABEL.
! 	 ?!? Do we need to account for NOTE_INSN_BASIC_BLOCK here?  */
!       if (GET_CODE (insn) != CODE_LABEL)
! 	{
! 	  new_insn = emit_insn_before (pat, insn);
! 	  if (BLOCK_HEAD (bb) == insn)
! 	    BLOCK_HEAD (bb) = new_insn;
! 	}
!       else
! 	{
! 	  new_insn = emit_insn_after (pat, insn);
! 	}

More information about the Gcc-patches mailing list