Commit c14b9960 by John Wehle Committed by John Wehle

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
parent 380f343b
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> 2002-03-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
* fixinc/inclhack.def (alpha_assert): Fix assert macro in Tru64 * fixinc/inclhack.def (alpha_assert): Fix assert macro in Tru64
......
...@@ -108,7 +108,13 @@ static tree decl_for_component_ref PARAMS ((tree)); ...@@ -108,7 +108,13 @@ static tree decl_for_component_ref PARAMS ((tree));
static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx)); static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx));
static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx)); static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx));
static int write_dependence_p PARAMS ((rtx, rtx, int)); 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_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. */ /* Set up all info needed to perform alias analysis on memory references. */
...@@ -2234,35 +2240,22 @@ output_dependence (mem, x) ...@@ -2234,35 +2240,22 @@ output_dependence (mem, x)
return write_dependence_p (mem, x, /*writep=*/1); return write_dependence_p (mem, x, /*writep=*/1);
} }
/* Returns non-zero if X mentions something which is not /* A subroutine of nonlocal_mentioned_p, returns 1 if *LOC mentions
local to the function and is not constant. */ something which is not local to the function and is not constant. */
static int static int
nonlocal_mentioned_p (x) nonlocal_mentioned_p_1 (loc, data)
rtx x; rtx *loc;
void *data ATTRIBUTE_UNUSED;
{ {
rtx x = *loc;
rtx base; rtx base;
RTX_CODE code;
int regno; int regno;
code = GET_CODE (x); if (! 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; return 0;
}
else
x = PATTERN (x);
code = GET_CODE (x);
}
switch (code) switch (GET_CODE (x))
{ {
case SUBREG: case SUBREG:
if (GET_CODE (SUBREG_REG (x)) == REG) if (GET_CODE (SUBREG_REG (x)) == REG)
...@@ -2344,69 +2337,260 @@ nonlocal_mentioned_p (x) ...@@ -2344,69 +2337,260 @@ nonlocal_mentioned_p (x)
break; 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. */
{ static int
const char *fmt = GET_RTX_FORMAT (code); nonlocal_mentioned_p (x)
int i; rtx x;
{
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (INSN_P (x))
{ {
if (fmt[i] == 'e' && XEXP (x, i)) if (GET_CODE (x) == CALL_INSN)
{ {
if (nonlocal_mentioned_p (XEXP (x, i))) if (! CONST_OR_PURE_CALL_P (x))
return 1; return 1;
x = CALL_INSN_FUNCTION_USAGE (x);
if (x == 0)
return 0;
} }
else if (fmt[i] == 'E') 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))
{ {
int j; case MEM:
for (j = 0; j < XVECLEN (x, i); j++) case REG:
if (nonlocal_mentioned_p (XVECEXP (x, i, j))) 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; 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; 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. */ /* Mark the function if it is constant. */
void void
mark_constant_function () mark_constant_function ()
{ {
rtx insn; rtx insn;
int nonlocal_mentioned; int nonlocal_memory_referenced;
if (TREE_PUBLIC (current_function_decl) if (TREE_PUBLIC (current_function_decl)
|| TREE_READONLY (current_function_decl) || TREE_READONLY (current_function_decl)
|| DECL_IS_PURE (current_function_decl) || DECL_IS_PURE (current_function_decl)
|| TREE_THIS_VOLATILE (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; return;
/* A loop might not return which counts as a side effect. */ /* A loop might not return which counts as a side effect. */
if (mark_dfs_back_edges ()) if (mark_dfs_back_edges ())
return; return;
nonlocal_mentioned = 0; nonlocal_memory_referenced = 0;
init_alias_analysis (); 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)) for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (INSN_P (insn) && nonlocal_mentioned_p (insn))
{ {
nonlocal_mentioned = 1; if (! INSN_P (insn))
continue;
if (nonlocal_set_p (insn) || global_reg_mentioned_p (insn)
|| volatile_refs_p (PATTERN (insn)))
break; break;
if (! nonlocal_memory_referenced)
nonlocal_memory_referenced = nonlocal_referenced_p (insn);
} }
end_alias_analysis (); end_alias_analysis ();
/* Mark the function. */ /* 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; TREE_READONLY (current_function_decl) = 1;
} }
......
...@@ -1461,6 +1461,7 @@ extern int rtx_addr_varies_p PARAMS ((rtx, int)); ...@@ -1461,6 +1461,7 @@ extern int rtx_addr_varies_p PARAMS ((rtx, int));
extern HOST_WIDE_INT get_integer_term PARAMS ((rtx)); extern HOST_WIDE_INT get_integer_term PARAMS ((rtx));
extern rtx get_related_value PARAMS ((rtx)); extern rtx get_related_value PARAMS ((rtx));
extern rtx get_jump_table_offset PARAMS ((rtx, 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 reg_mentioned_p PARAMS ((rtx, rtx));
extern int count_occurrences PARAMS ((rtx, rtx, int)); extern int count_occurrences PARAMS ((rtx, rtx, int));
extern int reg_referenced_p PARAMS ((rtx, rtx)); extern int reg_referenced_p PARAMS ((rtx, rtx));
......
...@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h" #include "tm_p.h"
/* Forward declarations */ /* Forward declarations */
static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
static void set_of_1 PARAMS ((rtx, rtx, void *)); static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *)); static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int computed_jump_p_1 PARAMS ((rtx)); static int computed_jump_p_1 PARAMS ((rtx));
...@@ -483,6 +484,82 @@ get_jump_table_offset (insn, earliest) ...@@ -483,6 +484,82 @@ get_jump_table_offset (insn, earliest)
return x; 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 /* 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. */ zero, we do not count occurrences inside the destination of a SET. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment