-
-/* Returns non-zero if X mentions something which is not
- local to the function and is not constant. */
-
-static int
-nonlocal_mentioned_p (x)
- rtx x;
-{
- 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);
- }
-
- 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[subreg_regno (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:
- /* Non-constant calls and recursion are not local. */
- 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)
- {
- /* A Pmode ADDRESS could be a reference via the structure value
- address or static chain. Such memory references are nonlocal.
-
- Thus, we have to examine the contents of the ADDRESS to find
- out if this is a local reference or not. */
- if (GET_CODE (base) == ADDRESS
- && GET_MODE (base) == Pmode
- && (XEXP (base, 0) == stack_pointer_rtx
- || XEXP (base, 0) == arg_pointer_rtx
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- || XEXP (base, 0) == hard_frame_pointer_rtx
-#endif
- || XEXP (base, 0) == frame_pointer_rtx))
- 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 UNSPEC_VOLATILE:
- case ASM_INPUT:
- return 1;
-
- case ASM_OPERANDS:
- if (MEM_VOLATILE_P (x))
- return 1;
-
- /* FALLTHROUGH */
-
- default:
- break;
- }
-
- /* Recursively scan the operands of this expression. */
-
- {
- 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;
- }
- }
- }
-
- return 0;
-}
-
-/* Mark the function if it is constant. */
-
-void
-mark_constant_function ()
-{
- rtx insn;
- int nonlocal_mentioned;
-
- 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)
- return;
-
- /* A loop might not return which counts as a side effect. */
- if (mark_dfs_back_edges ())
- return;
-
- nonlocal_mentioned = 0;
-
- init_alias_analysis ();
-
- /* Determine if this is a constant function. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && nonlocal_mentioned_p (insn))
- {
- nonlocal_mentioned = 1;
- break;
- }
-
- end_alias_analysis ();
-
- /* Mark the function. */
-
- if (! nonlocal_mentioned)
- TREE_READONLY (current_function_decl) = 1;
-}
-
-
-static HARD_REG_SET argument_registers;