From 7790df190afbe938f40506f1c75cfe7bef68496a Mon Sep 17 00:00:00 2001 From: John Wehle Date: Thu, 19 Aug 1999 15:53:10 +0000 Subject: [PATCH] alias.c: Include tree.h. * alias.c: Include tree.h. (nonlocal_reference_p, mark_constant_function): New functions. * flow.c (life_analysis): Call mark_constant_function. * rtl.h (mark_constant_function): Declare it. From-SVN: r28762 --- gcc/ChangeLog | 7 +++ gcc/alias.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/flow.c | 5 ++ gcc/rtl.h | 1 + 4 files changed, 157 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3dd68696d3a..046606b1f66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Thu Aug 19 11:51:22 EDT 1999 John Wehle (john@feith.com) + + * alias.c: Include tree.h. + (nonlocal_reference_p, mark_constant_function): New functions. + * flow.c (life_analysis): Call mark_constant_function. + * rtl.h (mark_constant_function): Declare it. + Thu Aug 19 15:02:01 1999 Nick Clifton * config/rs6000/rs6000.c (rs6000_override_options): Fix test for diff --git a/gcc/alias.c b/gcc/alias.c index d24b0b64543..5f4d4277e08 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" #include "rtl.h" +#include "tree.h" #include "function.h" #include "expr.h" #include "regs.h" @@ -1335,6 +1336,149 @@ output_dependence (mem, 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: + if (GET_CODE (SUBREG_REG (x)) == REG) + { + /* Global registers are not local. */ + if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER + && global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]) + return 1; + return 0; + } + break; + + 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: + /* Be overly conservative and consider any volatile memory + reference as not local. */ + if (MEM_VOLATILE_P (x)) + return 1; + 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_PUBLIC (current_function_decl) + || 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; +} + static HARD_REG_SET argument_registers; diff --git a/gcc/flow.c b/gcc/flow.c index c7ffe78aac8..3d13baf2681 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -2087,7 +2087,12 @@ life_analysis (f, nregs, file, remove_dead_code) /* We want alias analysis information for local dead store elimination. */ init_alias_analysis (); + life_analysis_1 (f, nregs, remove_dead_code); + + if (! reload_completed) + mark_constant_function (); + end_alias_analysis (); if (file) diff --git a/gcc/rtl.h b/gcc/rtl.h index 4f01212ff03..8f0ff59904a 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1546,6 +1546,7 @@ extern int true_dependence PROTO ((rtx, enum machine_mode, rtx, 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)); -- 2.30.2