OSDN Git Service

* alias.c: Include tree.h.
authorwehle <wehle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Aug 1999 15:53:10 +0000 (15:53 +0000)
committerwehle <wehle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Aug 1999 15:53:10 +0000 (15:53 +0000)
(nonlocal_reference_p, mark_constant_function): New functions.
* flow.c (life_analysis): Call mark_constant_function.
* rtl.h (mark_constant_function): Declare it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28762 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/alias.c
gcc/flow.c
gcc/rtl.h

index 3dd6869..046606b 100644 (file)
@@ -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
index d24b0b6..5f4d427 100644 (file)
@@ -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;
 
index c7ffe78..3d13baf 100644 (file)
@@ -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)
index 4f01212..8f0ff59 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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));