aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wehle <john@feith.com>2002-03-21 06:59:43 +0000
committerJohn Wehle <wehle@gcc.gnu.org>2002-03-21 06:59:43 +0000
commitc14b9960142c1daeff4f6098819beaed1edae50e (patch)
tree6b14d4c2f9960628888847cc9e4f77a205cf4a8c
parent380f343b245bdc410e2f5bd0fcddaa294511d834 (diff)
downloadgcc-c14b9960142c1daeff4f6098819beaed1edae50e.zip
gcc-c14b9960142c1daeff4f6098819beaed1edae50e.tar.gz
gcc-c14b9960142c1daeff4f6098819beaed1edae50e.tar.bz2
alias.c: (nonlocal_mentioned_p): Use for_each_rtx.
* alias.c: (nonlocal_mentioned_p): Use for_each_rtx. (nonlocal_mentioned_p_1): New function. (nonlocal_referenced_p, nonlocal_referenced_p_1): Likewise. (nonlocal_set_p, nonlocal_set_p_1): Likewise. (mark_constant_function): Recognize pure functions. * rtl.h (global_reg_mentioned_p): New prototype. * rtlanal.c (global_reg_mentioned_p, global_reg_mentioned_p_1): New function. From-SVN: r51113
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/alias.c298
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c77
4 files changed, 330 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 688fbbf..ddc2726 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+Thu Mar 21 01:55:06 EST 2002 John Wehle (john@feith.com)
+
+ * alias.c: (nonlocal_mentioned_p): Use for_each_rtx.
+ (nonlocal_mentioned_p_1): New function.
+ (nonlocal_referenced_p, nonlocal_referenced_p_1): Likewise.
+ (nonlocal_set_p, nonlocal_set_p_1): Likewise.
+ (mark_constant_function): Recognize pure functions.
+ * rtl.h (global_reg_mentioned_p): New prototype.
+ * rtlanal.c (global_reg_mentioned_p,
+ global_reg_mentioned_p_1): New function.
+
2002-03-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
* fixinc/inclhack.def (alpha_assert): Fix assert macro in Tru64
diff --git a/gcc/alias.c b/gcc/alias.c
index 9b46fe1..42d8e18 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -108,7 +108,13 @@ static tree decl_for_component_ref PARAMS ((tree));
static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx));
static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx));
static int write_dependence_p PARAMS ((rtx, rtx, int));
+
+static int nonlocal_mentioned_p_1 PARAMS ((rtx *, void *));
static int nonlocal_mentioned_p PARAMS ((rtx));
+static int nonlocal_referenced_p_1 PARAMS ((rtx *, void *));
+static int nonlocal_referenced_p PARAMS ((rtx));
+static int nonlocal_set_p_1 PARAMS ((rtx *, void *));
+static int nonlocal_set_p PARAMS ((rtx));
/* Set up all info needed to perform alias analysis on memory references. */
@@ -2233,36 +2239,23 @@ output_dependence (mem, x)
{
return write_dependence_p (mem, x, /*writep=*/1);
}
-
-/* Returns non-zero if X mentions something which is not
- local to the function and is not constant. */
+
+/* A subroutine of nonlocal_mentioned_p, returns 1 if *LOC mentions
+ something which is not local to the function and is not constant. */
static int
-nonlocal_mentioned_p (x)
- rtx x;
+nonlocal_mentioned_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
{
+ rtx x = *loc;
rtx base;
- RTX_CODE code;
int regno;
- code = GET_CODE (x);
-
- if (GET_RTX_CLASS (code) == 'i')
- {
- /* Constant functions can be constant if they don't use
- scratch memory used to mark function w/o side effects. */
- if (code == CALL_INSN && CONST_OR_PURE_CALL_P (x))
- {
- x = CALL_INSN_FUNCTION_USAGE (x);
- if (x == 0)
- return 0;
- }
- else
- x = PATTERN (x);
- code = GET_CODE (x);
- }
+ if (! x)
+ return 0;
- switch (code)
+ switch (GET_CODE (x))
{
case SUBREG:
if (GET_CODE (SUBREG_REG (x)) == REG)
@@ -2344,72 +2337,263 @@ nonlocal_mentioned_p (x)
break;
}
- /* Recursively scan the operands of this expression. */
+ return 0;
+}
+
+/* Returns non-zero if X might mention something which is not
+ local to the function and is not constant. */
- {
- const char *fmt = GET_RTX_FORMAT (code);
- int i;
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e' && XEXP (x, i))
- {
- if (nonlocal_mentioned_p (XEXP (x, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = 0; j < XVECLEN (x, i); j++)
- if (nonlocal_mentioned_p (XVECEXP (x, i, j)))
- return 1;
- }
- }
- }
+static int
+nonlocal_mentioned_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_mentioned_p_1, NULL);
+}
+
+/* A subroutine of nonlocal_referenced_p, returns 1 if *LOC references
+ something which is not local to the function and is not constant. */
+
+static int
+nonlocal_referenced_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case MEM:
+ case REG:
+ case SYMBOL_REF:
+ case SUBREG:
+ return nonlocal_mentioned_p (x);
+
+ case CALL:
+ /* Non-constant calls and recursion are not local. */
+ return 1;
+
+ case SET:
+ if (nonlocal_mentioned_p (SET_SRC (x)))
+ return 1;
+
+ if (GET_CODE (SET_DEST (x)) == MEM)
+ return nonlocal_mentioned_p (XEXP (SET_DEST (x), 0));
+
+ /* If the destination is anything other than a CC0, PC,
+ MEM, REG, or a SUBREG of a REG that occupies all of
+ the REG, then X references nonlocal memory if it is
+ mentioned in the destination. */
+ if (GET_CODE (SET_DEST (x)) != CC0
+ && GET_CODE (SET_DEST (x)) != PC
+ && GET_CODE (SET_DEST (x)) != REG
+ && ! (GET_CODE (SET_DEST (x)) == SUBREG
+ && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+ && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+ == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
+ return nonlocal_mentioned_p (SET_DEST (x));
+ return 0;
+
+ case CLOBBER:
+ if (GET_CODE (XEXP (x, 0)) == MEM)
+ return nonlocal_mentioned_p (XEXP (XEXP (x, 0), 0));
+ return 0;
+
+ case USE:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case ASM_INPUT:
+ case UNSPEC_VOLATILE:
+ return 1;
+
+ case ASM_OPERANDS:
+ if (MEM_VOLATILE_P (x))
+ return 1;
+
+ /* FALLTHROUGH */
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns non-zero if X might reference something which is not
+ local to the function and is not constant. */
+
+static int
+nonlocal_referenced_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_referenced_p_1, NULL);
+}
+
+/* A subroutine of nonlocal_set_p, returns 1 if *LOC sets
+ something which is not local to the function and is not constant. */
+
+static int
+nonlocal_set_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case CALL:
+ /* Non-constant calls and recursion are not local. */
+ return 1;
+
+ case PRE_INC:
+ case PRE_DEC:
+ case POST_INC:
+ case POST_DEC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case SET:
+ if (nonlocal_mentioned_p (SET_DEST (x)))
+ return 1;
+ return nonlocal_set_p (SET_SRC (x));
+
+ case CLOBBER:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case USE:
+ return 0;
+
+ case ASM_INPUT:
+ case UNSPEC_VOLATILE:
+ return 1;
+
+ case ASM_OPERANDS:
+ if (MEM_VOLATILE_P (x))
+ return 1;
+
+ /* FALLTHROUGH */
+
+ default:
+ break;
+ }
return 0;
}
+/* Returns non-zero if X might set something which is not
+ local to the function and is not constant. */
+
+static int
+nonlocal_set_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_set_p_1, NULL);
+}
+
/* Mark the function if it is constant. */
void
mark_constant_function ()
{
rtx insn;
- int nonlocal_mentioned;
+ int nonlocal_memory_referenced;
if (TREE_PUBLIC (current_function_decl)
|| TREE_READONLY (current_function_decl)
|| DECL_IS_PURE (current_function_decl)
|| TREE_THIS_VOLATILE (current_function_decl)
- || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode)
+ || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode
+ || current_function_has_nonlocal_goto)
return;
/* A loop might not return which counts as a side effect. */
if (mark_dfs_back_edges ())
return;
- nonlocal_mentioned = 0;
+ nonlocal_memory_referenced = 0;
init_alias_analysis ();
- /* Determine if this is a constant function. */
+ /* Determine if this is a constant or pure function. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && nonlocal_mentioned_p (insn))
- {
- nonlocal_mentioned = 1;
- break;
- }
+ {
+ if (! INSN_P (insn))
+ continue;
- end_alias_analysis ();
+ if (nonlocal_set_p (insn) || global_reg_mentioned_p (insn)
+ || volatile_refs_p (PATTERN (insn)))
+ break;
+ if (! nonlocal_memory_referenced)
+ nonlocal_memory_referenced = nonlocal_referenced_p (insn);
+ }
+
+ end_alias_analysis ();
+
/* Mark the function. */
-
- if (! nonlocal_mentioned)
+
+ if (insn)
+ ;
+ else if (nonlocal_memory_referenced)
+ DECL_IS_PURE (current_function_decl) = 1;
+ else
TREE_READONLY (current_function_decl) = 1;
}
-
+
static HARD_REG_SET argument_registers;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 711f53b..3c51155 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1461,6 +1461,7 @@ extern int rtx_addr_varies_p PARAMS ((rtx, int));
extern HOST_WIDE_INT get_integer_term PARAMS ((rtx));
extern rtx get_related_value PARAMS ((rtx));
extern rtx get_jump_table_offset PARAMS ((rtx, rtx *));
+extern int global_reg_mentioned_p PARAMS ((rtx));
extern int reg_mentioned_p PARAMS ((rtx, rtx));
extern int count_occurrences PARAMS ((rtx, rtx, int));
extern int reg_referenced_p PARAMS ((rtx, rtx));
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 70cbbf8..79ccf9d 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
/* Forward declarations */
+static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int computed_jump_p_1 PARAMS ((rtx));
@@ -483,6 +484,82 @@ get_jump_table_offset (insn, earliest)
return x;
}
+/* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
+ a global register. */
+
+static int
+global_reg_mentioned_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int regno;
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case SUBREG:
+ if (GET_CODE (SUBREG_REG (x)) == REG)
+ {
+ if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
+ && global_regs[subreg_regno (x)])
+ return 1;
+ return 0;
+ }
+ break;
+
+ case REG:
+ regno = REGNO (x);
+ 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 CALL:
+ /* A non-constant call might use a global register. */
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns non-zero if X mentions a global register. */
+
+int
+global_reg_mentioned_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
+}
+
/* Return the number of places FIND appears within X. If COUNT_DEST is
zero, we do not count occurrences inside the destination of a SET. */