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
This commit is contained in:
John Wehle 2002-03-21 06:59:43 +00:00 committed by John Wehle
parent 380f343b24
commit c14b996014
4 changed files with 330 additions and 57 deletions

View File

@ -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

View File

@ -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 (! x)
return 0;
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);
}
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;
}
{
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;
}
}
}
/* Returns non-zero if X might mention something which is not
local to the function and is not constant. */
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;
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;

View File

@ -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));

View File

@ -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. */