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 to detect constant functions.


This patch allows gcc to detect and mark functions as constant by using
the information from the alias analysis to determine if the function
references memory which isn't local.  Knowing that a function is constant
can help cse and loop.  For example using -O2 on a x86 platform to compile:

  int
  subr(int a, int b, int c)
    {

    if (! c )
      return subr(a, b, 1);

    return a + b / c;
    }

  int
  func(int a, int b, int c)
    {

    return subr(a, b, c) + subr(a, b, c);
    }

without the patch produces:

func:
	pushl %ebp
	movl %esp,%ebp
	subl $12,%esp
	pushl %edi
	pushl %esi
	pushl %ebx
	movl 12(%ebp),%esi
	movl 16(%ebp),%ebx
	addl $-4,%esp
	pushl %ebx
	pushl %esi
	movl 8(%ebp),%eax
	pushl %eax
	call subr
	movl %eax,%edi
	addl $-4,%esp
	pushl %ebx
	pushl %esi
	movl 8(%ebp),%eax
	pushl %eax
	call subr
	addl %edi,%eax
	leal -24(%ebp),%esp
	popl %ebx
	popl %esi
	popl %edi
	leave
	ret

for func and with the patch:

func:
	pushl %ebp
	movl %esp,%ebp
	subl $8,%esp
	addl $-4,%esp
	pushl 16(%ebp)
	pushl 12(%ebp)
	pushl 8(%ebp)
	call subr
	addl %eax,%eax
	leave
	ret

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

ChangeLog:

Tue Aug 17 22:42:20 EDT 1999  John Wehle  (john@feith.com)

	* alias.c: Include tree.h.
	(nonlocal_reference_p, mark_constant_function): New functions.
	* cse.c (cse_main): Call mark_constant_function.
	* rtl.h (mark_constant_function): Declare it.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/alias.c.ORIGINAL	Sun Aug  8 01:10:21 1999
--- gcc/alias.c	Tue Aug 17 22:56:55 1999
*************** Boston, MA 02111-1307, USA.  */
*** 22,27 ****
--- 22,28 ----
  #include "config.h"
  #include "system.h"
  #include "rtl.h"
+ #include "tree.h"
  #include "expr.h"
  #include "regs.h"
  #include "hard-reg-set.h"
*************** output_dependence (mem, x)
*** 1332,1337 ****
--- 1333,1473 ----
       register rtx x;
  {
    return write_dependence_p (mem, x, /*writep=*/1);
+ }
+ 
+ /* Returns non-zero if X might refer to something which is not
+    local to the function and is not constant.  */
+ 
+ static int
+ nonlocal_reference_p (x)
+      rtx x;
+ {
+   rtx base;
+   register RTX_CODE code;
+   int regno;
+ 
+   code = GET_CODE (x);
+ 
+   if (GET_RTX_CLASS (code) == 'i')
+     {
+       /* Constant functions are constant.  */
+       if (code == CALL_INSN && CONST_CALL_P (x))
+ 	return 0;
+       x = PATTERN (x);
+       code = GET_CODE (x);
+     }
+ 
+   switch (code)
+     {
+     case SUBREG:
+       regno = REGNO (SUBREG_REG (x));
+       /* Global registers are not local.  */
+       if (regno < FIRST_PSEUDO_REGISTER
+ 	  && global_regs[regno + SUBREG_WORD (x)])
+ 	return 1;
+       return 0;
+ 
+     case REG:
+       regno = REGNO (x);
+       /* Global registers are not local.  */
+       if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+ 	return 1;
+       return 0;
+ 
+     case SCRATCH:
+     case PC:
+     case CC0:
+     case CONST_INT:
+     case CONST_DOUBLE:
+     case CONST:
+     case LABEL_REF:
+       return 0;
+ 
+     case SYMBOL_REF:
+       /* Constants in the function's constants pool are constant.  */
+       if (CONSTANT_POOL_ADDRESS_P (x))
+ 	return 0;
+       return 1;
+ 
+     case CALL:
+       /* Recursion introduces no additional considerations.  */
+       if (GET_CODE (XEXP (x, 0)) == MEM
+ 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ 	  && strcmp(XSTR (XEXP (XEXP (x, 0), 0), 0),
+ 		    IDENTIFIER_POINTER (
+ 			  DECL_ASSEMBLER_NAME (current_function_decl))) == 0)
+ 	return 0;
+       return 1;
+ 
+     case MEM:
+       base = find_base_term (XEXP (x, 0));
+       if (base)
+ 	{
+ 	  /* Stack references are local.  */
+ 	  if (GET_CODE (base) == ADDRESS && GET_MODE (base) == Pmode)
+ 	    return 0;
+ 	  /* Constants in the function's constant pool are constant.  */
+ 	  if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base))
+ 	    return 0;
+ 	}
+       return 1;
+ 
+     case ASM_INPUT:
+     case ASM_OPERANDS:
+       return 1;
+ 
+     default:
+       break;
+     }
+ 
+   /* Recursively scan the operands of this expression.  */
+ 
+   {
+     register char *fmt = GET_RTX_FORMAT (code);
+     register int i;
+     
+     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+       {
+ 	if (fmt[i] == 'e')
+ 	  {
+ 	    if (nonlocal_reference_p (XEXP (x, i)))
+ 	      return 1;
+ 	  }
+ 	if (fmt[i] == 'E')
+ 	  {
+ 	    register int j;
+ 	    for (j = 0; j < XVECLEN (x, i); j++)
+ 	      if (nonlocal_reference_p (XVECEXP (x, i, j)))
+ 		return 1;
+ 	  }
+       }
+   }
+ 
+   return 0;
+ }
+ 
+ /* Mark the function if it is constant.  */
+ 
+ void
+ mark_constant_function ()
+ {
+   rtx insn;
+ 
+   if (TREE_READONLY (current_function_decl)
+       || TREE_THIS_VOLATILE (current_function_decl)
+       || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode)
+     return;
+ 
+   /* Determine if this is a constant function.  */
+ 
+   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+ 	&& nonlocal_reference_p (insn))
+       return;
+ 
+   /* Mark the function.  */
+ 
+   TREE_READONLY (current_function_decl) = 1;
  }
  
  
*** gcc/cse.c.ORIGINAL	Fri Aug  6 16:53:37 1999
--- gcc/cse.c	Thu Aug 12 01:12:24 1999
*************** cse_main (f, nregs, after_loop, file)
*** 8643,8648 ****
--- 8643,8650 ----
    init_recog ();
    init_alias_analysis ();
  
+   mark_constant_function ();
+ 
    max_reg = nregs;
  
    max_insn_uid = get_max_uid ();
*** gcc/rtl.h.ORIGINAL	Sun Aug  8 01:11:08 1999
--- gcc/rtl.h	Thu Aug 12 01:12:25 1999
*************** extern int true_dependence		PROTO ((rtx,
*** 1623,1628 ****
--- 1623,1629 ----
  extern int read_dependence		PROTO ((rtx, rtx));
  extern int anti_dependence		PROTO ((rtx, rtx));
  extern int output_dependence		PROTO ((rtx, rtx));
+ extern void mark_constant_function	PROTO ((void));
  extern void init_alias_once		PROTO ((void));
  extern void init_alias_analysis		PROTO ((void));
  extern void end_alias_analysis		PROTO ((void));
-------------------------------------------------------------------------
|   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]