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]

Additional patch to further improve delete_computation.


This patch allows delete_computation to remove calls to constant
functions.  For example using -O2 -fno-schedule-insns2 on a x86
platform to compile:

  long
  func(long long a, long long b)
    {
    long long c;

    c = a / b;

    if (c)
      return 0;

    c -= c;

    return c;
    }

without the patch produces:

	pushl %ebp
	movl %esp,%ebp
	subl $8,%esp
	movl 16(%ebp),%eax
	movl 20(%ebp),%edx
	pushl %edx
	pushl %eax
	movl 8(%ebp),%eax
	movl 12(%ebp),%edx
	pushl %edx
	pushl %eax
	call __divdi3
	xorl %eax,%eax
	leave
	ret

with the patch:

	pushl %ebp
	movl %esp,%ebp
	subl $8,%esp
	movl 16(%ebp),%eax
	movl 20(%ebp),%edx
	pushl %edx
	pushl %eax
	movl 8(%ebp),%eax
	movl 12(%ebp),%edx
	pushl %edx
	pushl %eax
	xorl %eax,%eax
	leave
	ret

This patch passes make bootstrap and make check on FreeBSD-3.2 x86.

Notes:

  1) Unfortunately at the moment I don't see a straight forward way
     to avoid pushing the arguements on the stack (helpful little
     things such as REG_LIBCALL and REG_RETVAL notes are not around),
     however with enough analysis it's probably doable.

ChangeLog:

Sun Aug  8 00:03:55 EDT 1999  John Wehle  (john@feith.com)

	* jump.c (delete_prior_computation): Also check calls
	to constant functions.  Don't bother checking for a
	REG_UNUSED note before adding it.
	(delete_computation): Handle multi-word hard registers
	when synthesizing missing REG_DEAD notes for a register
	which is both set and used by an insn.

Enjoy!

-- John Wehle
-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/jump.c.ORIGINAL	Fri Aug  6 16:58:16 1999
--- gcc/jump.c	Sat Aug  7 23:56:40 1999
*************** delete_prior_computation (note, insn)
*** 3824,3834 ****
    rtx reg = XEXP (note, 0);
  
    for (our_prev = prev_nonnote_insn (insn);
!        our_prev && GET_CODE (our_prev) == INSN;
         our_prev = prev_nonnote_insn (our_prev))
      {
        rtx pat = PATTERN (our_prev);
  
        /* If we reach a SEQUENCE, it is too complex to try to
  	 do anything with it, so give up.  */
        if (GET_CODE (pat) == SEQUENCE)
--- 3824,3842 ----
    rtx reg = XEXP (note, 0);
  
    for (our_prev = prev_nonnote_insn (insn);
!        our_prev && (GET_CODE (our_prev) == INSN
! 		    || GET_CODE (our_prev) == CALL_INSN);
         our_prev = prev_nonnote_insn (our_prev))
      {
        rtx pat = PATTERN (our_prev);
  
+       /* If we reach a CALL which is not calling a const function
+ 	 or the callee pops the arguments, then give up.  */
+       if (GET_CODE (our_prev) == CALL_INSN
+ 	  && (! CONST_CALL_P (our_prev)
+ 	      || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
+ 	break;
+ 
        /* If we reach a SEQUENCE, it is too complex to try to
  	 do anything with it, so give up.  */
        if (GET_CODE (pat) == SEQUENCE)
*************** delete_prior_computation (note, insn)
*** 3842,3848 ****
  
        if (reg_set_p (reg, pat))
  	{
! 	  if (side_effects_p (pat))
  	    break;
  
  	  if (GET_CODE (pat) == PARALLEL)
--- 3850,3856 ----
  
        if (reg_set_p (reg, pat))
  	{
! 	  if (side_effects_p (pat) && GET_CODE (our_prev) != CALL_INSN)
  	    break;
  
  	  if (GET_CODE (pat) == PARALLEL)
*************** delete_prior_computation (note, insn)
*** 3885,3892 ****
  		 insns.  Write REG_UNUSED notes for those parts that were not
  		 needed.  */
  	      else if (dest_regno <= regno
! 		       && dest_endregno >= endregno
! 		       && ! find_regno_note (our_prev, REG_UNUSED, REGNO(reg)))
  		{
  		  int i;
  
--- 3893,3899 ----
  		 insns.  Write REG_UNUSED notes for those parts that were not
  		 needed.  */
  	      else if (dest_regno <= regno
! 		       && dest_endregno >= endregno)
  		{
  		  int i;
  
*************** delete_computation (insn)
*** 3972,3978 ****
--- 3979,4008 ----
      }
  #endif
  
+   /* The REG_DEAD note may have been omitted for a register
+      which is both set and used by the insn.  */
    set = single_set (insn);
+   if (set && GET_CODE (SET_DEST (set)) == REG)
+     {
+     int dest_regno = REGNO (SET_DEST (set));
+     int dest_endregno
+ 	  = dest_regno + (dest_regno < FIRST_PSEUDO_REGISTER 
+ 	    ? HARD_REGNO_NREGS (dest_regno,
+ 				GET_MODE (SET_DEST (set))) : 1);
+     int i;
+ 
+     for (i = dest_regno; i < dest_endregno; i++)
+       {
+ 	if (! refers_to_regno_p (i, i + 1, SET_SRC (set), NULL_PTR)
+ 	    || find_regno_note (insn, REG_DEAD, i))
+ 	  continue;
+ 
+ 	note = gen_rtx_EXPR_LIST (REG_DEAD, (i < FIRST_PSEUDO_REGISTER
+ 					     ? gen_rtx_REG (reg_raw_mode[i], i)
+ 					     : SET_DEST (set)), NULL_RTX);
+ 	delete_prior_computation (note, insn);
+       }
+     }
  
    for (note = REG_NOTES (insn); note; note = next)
      {
*************** delete_computation (insn)
*** 3983,4001 ****
  	  || GET_CODE (XEXP (note, 0)) != REG)
  	continue;
  
-       if (set && reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
- 	set = NULL_RTX;
- 
-       delete_prior_computation (note, insn);
-     }
- 
-   /* The REG_DEAD note may have been omitted for a register
-      which is both set and used by the insn.  */
-   if (set
-       && GET_CODE (SET_DEST (set)) == REG
-       && reg_mentioned_p (SET_DEST (set), SET_SRC (set)))
-     {
-       note = gen_rtx_EXPR_LIST (REG_DEAD, SET_DEST (set), NULL_RTX);
        delete_prior_computation (note, insn);
      }
  
--- 4013,4018 ----
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------


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