This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to detect constant functions.
- To: gcc-patches at gcc dot gnu dot org
- Subject: Patch to detect constant functions.
- From: John Wehle <john at feith dot com>
- Date: Wed, 18 Aug 1999 00:57:16 -0400 (EDT)
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 | |
-------------------------------------------------------------------------