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
This commit is contained in:
parent
4406229e16
commit
7790df190a
|
@ -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 <nickc@cygnus.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_override_options): Fix test for
|
||||
|
|
144
gcc/alias.c
144
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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue