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]

Tiny speedups..



Hi
This patch attempts to avoid two of the most commonly called functions in gcc -
single_set and recog_memoized.  The profiler claims them to eat together about
5% of compilation time.  The patch replaces them with macros that takes care
for the fast path (in the single_set case the fast path if non-PARALLEL insn
and even on i386 this saved about 75% of calls) and shots them off the top
places in profile.

Also single_set is futher optimized to expect parallel with single set followed
by clobber and uses and to avoid call of find_reg_note on that, so also
the amount of call of that functions decreases to about one half.

After first clobber is found, insn is not proceeded farer expecting that
uses and clobbers are grouped on the end - I think we have similar expectations
elsewhere and it is not dificult to maitain.

No make this patch proper, one should rename all single_sets to SINGLE_SET
and recog_memoized to RECOG_MEMOIZEd, so this is just an try whether such
idea is applicable or not.

Wed Sep 20 21:36:42 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* recog.c (recog_memoized): Rename to recog_memoized_1.
	* recog.h (recog_memoized): Rename to recog_memoized_1.
	(recog_memoized): New macro.
	* rtl.h (single_set): Rename to single_set_1
	(single_set): New macro.
	* rtl.c (single_set): Rename to single_set_1;  expect clobbers
	to be last.

*** ../../egcs-20000918.orig/gcc/./recog.c	Wed Sep 20 11:18:04 2000
--- ./recog.c	Wed Sep 20 17:30:32 2000
*************** init_recog ()
*** 112,118 ****
     through this one.  (The only exception is in combine.c.)  */
  
  int
! recog_memoized (insn)
       rtx insn;
  {
    if (INSN_CODE (insn) < 0)
--- 112,118 ----
     through this one.  (The only exception is in combine.c.)  */
  
  int
! recog_memoized_1 (insn)
       rtx insn;
  {
    if (INSN_CODE (insn) < 0)
*** ../../egcs-20000918.orig/gcc/./recog.h	Wed Sep 20 11:18:04 2000
--- ./recog.h	Wed Sep 20 10:45:00 2000
*************** struct operand_alternative
*** 69,75 ****
  
  extern void init_recog			PARAMS ((void));
  extern void init_recog_no_volatile	PARAMS ((void));
! extern int recog_memoized		PARAMS ((rtx));
  extern int check_asm_operands		PARAMS ((rtx));
  extern int asm_operand_ok		PARAMS ((rtx, const char *));
  extern int validate_change		PARAMS ((rtx, rtx *, rtx, int));
--- 69,76 ----
  
  extern void init_recog			PARAMS ((void));
  extern void init_recog_no_volatile	PARAMS ((void));
! #define recog_memoized(I) (INSN_CODE(I)>=0?INSN_CODE(I):recog_memoized_1(I))
! extern int recog_memoized_1		PARAMS ((rtx));
  extern int check_asm_operands		PARAMS ((rtx));
  extern int asm_operand_ok		PARAMS ((rtx, const char *));
  extern int validate_change		PARAMS ((rtx, rtx *, rtx, int));
*** ../../egcs-20000918.orig/gcc/./rtl.h	Wed Sep 20 11:18:04 2000
--- ./rtl.h	Wed Sep 20 12:23:23 2000
*************** extern int no_jumps_between_p		PARAMS ((
*** 1347,1353 ****
  extern int modified_in_p		PARAMS ((rtx, rtx));
  extern int insn_dependent_p		PARAMS ((rtx, rtx));
  extern int reg_set_p			PARAMS ((rtx, rtx));
! extern rtx single_set			PARAMS ((rtx));
  extern int multiple_sets		PARAMS ((rtx));
  extern rtx find_last_value		PARAMS ((rtx, rtx *, rtx, int));
  extern int refers_to_regno_p		PARAMS ((unsigned int, unsigned int,
--- 1484,1491 ----
  extern int modified_in_p		PARAMS ((rtx, rtx));
  extern int insn_dependent_p		PARAMS ((rtx, rtx));
  extern int reg_set_p			PARAMS ((rtx, rtx));
! extern rtx single_set_1			PARAMS ((rtx)) __attribute__ ((pure));
! #define single_set(I)  (INSN_P (I) ? GET_CODE (PATTERN (I)) == SET ? PATTERN (I) : single_set_1 (I) : NULL_RTX)
  extern int multiple_sets		PARAMS ((rtx));
  extern rtx find_last_value		PARAMS ((rtx, rtx *, rtx, int));
  extern int refers_to_regno_p		PARAMS ((unsigned int, unsigned int,
*** ../../egcs-20000918.orig/gcc/rtlanal.c	Wed Sep 20 11:18:04 2000
--- rtlanal.c	Wed Sep 20 21:30:52 2000
*************** insn_dependent_p_1 (x, pat, data)
*** 842,887 ****
     will not be used, which we ignore.  */
  
  rtx
! single_set (insn)
       rtx insn;
  {
    rtx set;
    int i;
    
!   if (! INSN_P (insn))
!     return 0;
! 
!   if (GET_CODE (PATTERN (insn)) == SET)
!     return PATTERN (insn);
!   
!   else if (GET_CODE (PATTERN (insn)) == PARALLEL)
      {
!       for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++)
  	{
! 	  rtx sub = XVECEXP (PATTERN (insn), 0, i);
! 
! 	  switch (GET_CODE (sub))
  	    {
! 	    case USE:
! 	    case CLOBBER:
! 	      break;
! 
! 	    case SET:
! 	      if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
! 		  || side_effects_p (sub))
  		{
! 		  if (set)
! 		    return 0;
! 		  else
  		    set = sub;
! 		}
! 	      break;
  
! 	    default:
! 	      return 0;
  	    }
  	}
-       return set;
      }
    
    return 0;
--- 842,928 ----
     will not be used, which we ignore.  */
  
  rtx
! single_set_1 (insn)
       rtx insn;
  {
    rtx set;
+   rtx pat = PATTERN (insn);
    int i;
    
!   if (GET_CODE (pat) == PARALLEL)
      {
!       rtx x, sub;
!       /* This part is is performance critical for targets that use a lot of
! 	 parallels, such as i386.  We want to accept as single set
! 	 instructions even an instructions with multiple sets where only
! 	 one has live result, but we attempt to delay this tests only for
! 	 multiple set instructions to reduce amount of calls to
! 	 find_reg_note and side_effects_p.
!        
! 	 We expect the "common" instruction to be parallel with first SET
! 	 followed by the clobbers.  So first we get the set, then look
! 	 if it is followed by USE or CLOBBER. If so, we just return expect
! 	 no SETs after these.  When SET is followed by another SET, we
! 	 continue by the clomplex loop trought all members of PARALLEL.
!        */
!       set = XVECEXP (pat, 0, 0);
!       switch (GET_CODE (set))
  	{
! #ifdef ENABLE_CHECKING
! 	  case USE:
! 	  case CLOBBER:
! 	    /* Instruction should not consist only from USEs and CLOBBERS,
! 	       since then gcc is allowed to remove it entirely.  In case
! 	       something else is present, it should be first in the pattern.  */
! 	    abort();
! #endif
! 	  case SET:
! 	    break;
! 	  default:
! 	    return 0;
! 	}
!       x = XVECEXP (pat, 0, 1);
!       switch (GET_CODE (x))
! 	{
! 	case USE:
! 	case CLOBBER:
! #ifdef ENABLE_CHECKING
! 	  /* The USEs and CLOBBERs should always come last in the pattern.  */
! 	  for (i = XVECLEN (pat, 0) - 1; i > 1; i--)
! 	    if (GET_CODE (XVECEXP (pat, 0, i)) != USE
! 		&& GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER)
! 	      abort();
! #endif
! 	    return set;
! 	case SET:
! 	  /* Multiple set insns - we are off the critical path now.  */
! 	  for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
  	    {
! 	      sub = XVECEXP (pat, 0, i);
! 	      switch GET_CODE (sub)
  		{
! 		case USE:
! 		case CLOBBER:
! 		  break;
! 
! 		case SET:
! 		  if (!set
! 		      || (find_reg_note (insn, REG_UNUSED, SET_DEST (set))
! 			  && side_effects_p (set)))
  		    set = sub;
! 		  else if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
! 			   || side_effects_p (sub))
! 		    return 0;
! 		  break;
  
! 		default:
! 		  return 0;
! 		}
  	    }
+ 	  return set;
+ 	default:
+ 	  return 0;
  	}
      }
    
    return 0;

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