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]

patch for gcse bug


After some discussion with Jeff, I've committed the following.

When a call insn ends a basic block, as will happen with 
exception handling, instructions for that basic block must be
insertted before the call. 

In the interest of not making reload's job too difficult, I
actually insert the instructions before the call's register
arguments are loaded.  This is also required before Bernd's
monster reload patch goes in, as otherwise we'll generate
incorrect code on those small register class machines that
pass parameters in registers.


r~


Wed Oct  7 10:07:29 1998  Richard Henderson  <rth@cygnus.com>

        * gcse.c (pre_insert_insn): When a call ends a bb, insert
        the new insns before the argument regs are loaded.

Index: gcse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/gcse.c,v
retrieving revision 1.13
diff -c -p -d -r1.13 gcse.c
*** gcse.c	1998/09/15 23:43:50	1.13
--- gcse.c	1998/10/07 17:06:10
*************** pre_insert_insn (expr, bb)
*** 4373,4393 ****
        add_label_notes (SET_SRC (pat), new_insn);
        if (BLOCK_HEAD (bb) == insn)
  	BLOCK_HEAD (bb) = new_insn;
!       /* Keep block number table up to date.  */
!       set_block_num (new_insn, bb);
!       /* Keep register set table up to date.  */
!       record_one_set (regno, new_insn);
      }
    else
      {
        new_insn = emit_insn_after (pat, insn);
        add_label_notes (SET_SRC (pat), new_insn);
        BLOCK_END (bb) = new_insn;
-       /* Keep block number table up to date.  */
-       set_block_num (new_insn, bb);
-       /* Keep register set table up to date.  */
-       record_one_set (regno, new_insn);
      }
  
    gcse_create_count++;
  
--- 4373,4443 ----
        add_label_notes (SET_SRC (pat), new_insn);
        if (BLOCK_HEAD (bb) == insn)
  	BLOCK_HEAD (bb) = new_insn;
!     }
!   /* Likewise if the last insn is a call, as will happen in the presence
!      of exception handling.  */
!   else if (GET_CODE (insn) == CALL_INSN)
!     {
!       HARD_REG_SET parm_regs;
!       int nparm_regs;
!       rtx p;
! 
!       /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
! 	 we search backward and place the instructions before the first
! 	 parameter is loaded.  Do this for everyone for consistency and a
! 	 presumtion that we'll get better code elsewhere as well.  */
! 
!       /* It should always be the case that we can put these instructions
! 	 anywhere in the basic block.  Check this.  */
!       if (!TEST_BIT (pre_antloc[bb], expr->bitmap_index)
! 	  && !TEST_BIT (pre_transp[bb], expr->bitmap_index))
! 	abort ();
! 
!       /* Since different machines initialize their parameter registers
! 	 in different orders, assume nothing.  Collect the set of all
! 	 parameter registers.  */
!       CLEAR_HARD_REG_SET (parm_regs);
!       nparm_regs = 0;
!       for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1))
! 	if (GET_CODE (XEXP (p, 0)) == USE
! 	    && GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
! 	  {
! 	    int regno = REGNO (XEXP (XEXP (p, 0), 0));
! 	    if (regno >= FIRST_PSEUDO_REGISTER)
! 	      abort();
! 	    SET_HARD_REG_BIT (parm_regs, regno);
! 	    nparm_regs++;
! 	  }
! 
!       /* 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
! 	      && REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER
! 	      && TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
! 	    {
! 	      CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));
! 	      nparm_regs--;
! 	    }
! 	}
!       
!       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);
        add_label_notes (SET_SRC (pat), new_insn);
        BLOCK_END (bb) = new_insn;
      }
+ 
+   /* Keep block number table up to date.  */
+   set_block_num (new_insn, bb);
+   /* Keep register set table up to date.  */
+   record_one_set (regno, new_insn);
  
    gcse_create_count++;
  


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