OSDN Git Service

2001-10-10 Stan Shebs <shebs@apple.com>
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index 79c0c33..53de65f 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -59,7 +59,7 @@ Boston, MA 02111-1307, USA.  */
 
    To see whether two alias sets can point to the same memory, we must
    see if either alias set is a subset of the other. We need not trace
-   past immediate decendents, however, since we propagate all
+   past immediate descendents, however, since we propagate all
    grandchildren up one level.
 
    Alias set zero is implicitly a superset of all other alias sets.
@@ -72,7 +72,7 @@ typedef struct alias_set_entry
   HOST_WIDE_INT alias_set;
 
   /* The children of the alias set.  These are not just the immediate
-     children, but, in fact, all decendents.  So, if we have:
+     children, but, in fact, all descendents.  So, if we have:
 
        struct T { struct S s; float f; } 
 
@@ -107,8 +107,6 @@ static int aliases_everything_p         PARAMS ((rtx));
 static int write_dependence_p           PARAMS ((rtx, rtx, int));
 static int nonlocal_mentioned_p         PARAMS ((rtx));
 
-static int loop_p                       PARAMS ((void));
-
 /* Set up all info needed to perform alias analysis on memory references.  */
 
 /* Returns the size in bytes of the mode of X.  */
@@ -336,7 +334,7 @@ objects_must_conflict_p (t1, t2)
       != (t2 != 0 && AGGREGATE_TYPE_P (t2)))
     return 0;
 
-  /* Otherwise they conflict only if the alias sets conflict. */
+  /* Otherwise they conflict only if the alias sets conflict.  */
   return alias_sets_conflict_p (t1 ? get_alias_set (t1) : 0,
                                t2 ? get_alias_set (t2) : 0);
 }
@@ -383,7 +381,6 @@ find_base_decl (t)
     case '3':
       d0 = find_base_decl (TREE_OPERAND (t, 0));
       d1 = find_base_decl (TREE_OPERAND (t, 1));
-      d0 = find_base_decl (TREE_OPERAND (t, 0));
       d2 = find_base_decl (TREE_OPERAND (t, 2));
 
       /* Set any nonzero values from the last, then from the first.  */
@@ -473,16 +470,32 @@ get_alias_set (t)
     return 0;
 
   /* We can be passed either an expression or a type.  This and the
-     language-specific routine may make mutually-recursive calls to
-     each other to figure out what to do.  At each juncture, we see if
-     this is a tree that the language may need to handle specially.
-     First handle things that aren't types and start by removing nops
-     since we care only about the actual object.  */
+     language-specific routine may make mutually-recursive calls to each other
+     to figure out what to do.  At each juncture, we see if this is a tree
+     that the language may need to handle specially.  First handle things that
+     aren't types and start by removing nops since we care only about the
+     actual object.  Also replace PLACEHOLDER_EXPRs and pick up the outermost
+     object that we could have a pointer to.  */
   if (! TYPE_P (t))
     {
-      while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
-            || TREE_CODE (t) == NON_LVALUE_EXPR)
-       t = TREE_OPERAND (t, 0);
+      /* Remove any NOPs and see what any PLACEHOLD_EXPRs will expand to.  */
+      while (((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
+             && (TYPE_MODE (TREE_TYPE (t))
+                 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))))
+            || TREE_CODE (t) == NON_LVALUE_EXPR
+            || TREE_CODE (t) == PLACEHOLDER_EXPR
+            || (handled_component_p (t) && ! can_address_p (t)))
+       {
+         /* Give the language a chance to do something with this tree
+            before we go inside it.  */
+         if ((set = lang_get_alias_set (t)) != -1)
+           return set;
+
+         if (TREE_CODE (t) == PLACEHOLDER_EXPR)
+           t = find_placeholder (t, 0);
+         else
+           t = TREE_OPERAND (t, 0);
+       }
 
       /* Now give the language a chance to do something but record what we
         gave it this time.  */
@@ -490,15 +503,9 @@ get_alias_set (t)
       if ((set = lang_get_alias_set (t)) != -1)
        return set;
 
-      /* Now loop the same way as get_inner_reference and get the alias
-        set to use.  Pick up the outermost object that we could have
-        a pointer to.  */
-      while (handled_component_p (t) && ! can_address_p (t))
-       t = TREE_OPERAND (t, 0);
-
+      /* Check for accesses through restrict-qualified pointers.  */
       if (TREE_CODE (t) == INDIRECT_REF)
        {
-         /* Check for accesses through restrict-qualified pointers.  */
          tree decl = find_base_decl (TREE_OPERAND (t, 0));
 
          if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
@@ -511,6 +518,13 @@ get_alias_set (t)
            return 0;
        }
 
+      /* If we've already determined the alias set for this decl, just
+        return it.  This is necessary for C++ anonymous unions, whose
+        component variables don't look like union members (boo!).  */
+      if (TREE_CODE (t) == VAR_DECL
+         && DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)
+       return MEM_ALIAS_SET (DECL_RTL (t));
+
       /* Give the language another chance to do something special.  */
       if (orig_t != t
          && (set = lang_get_alias_set (t)) != -1)
@@ -583,6 +597,11 @@ record_alias_subset (superset, subset)
   alias_set_entry superset_entry;
   alias_set_entry subset_entry;
 
+  /* It is possible in complex type situations for both sets to be the same,
+     in which case we can ignore this operation.  */
+  if (superset == subset)
+    return;
+
   if (superset == 0)
     abort ();
 
@@ -695,7 +714,7 @@ get_frame_alias_set ()
 
 static rtx
 find_base_value (src)
-     register rtx src;
+     rtx src;
 {
   unsigned int regno;
   switch (GET_CODE (src))
@@ -742,7 +761,7 @@ find_base_value (src)
       if (GET_CODE (src) != PLUS && GET_CODE (src) != MINUS)
        break;
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case PLUS:
     case MINUS:
@@ -791,7 +810,7 @@ find_base_value (src)
 
     case AND:
       /* If the second operand is constant set the base
-        address to the first operand. */
+        address to the first operand.  */
       if (GET_CODE (XEXP (src, 1)) == CONST_INT && INTVAL (XEXP (src, 1)) != 0)
        return find_base_value (XEXP (src, 0));
       return 0;
@@ -827,7 +846,7 @@ record_set (dest, set, data)
      rtx dest, set;
      void *data ATTRIBUTE_UNUSED;
 {
-  register unsigned regno;
+  unsigned regno;
   rtx src;
 
   if (GET_CODE (dest) != REG)
@@ -938,6 +957,21 @@ record_base_value (regno, val, invariant)
   reg_base_value[regno] = find_base_value (val);
 }
 
+/* Clear alias info for a register.  This is used if an RTL transformation
+   changes the value of a register.  This is used in flow by AUTO_INC_DEC
+   optimizations.  We don't need to clear reg_base_value, since flow only
+   changes the offset.  */
+
+void
+clear_reg_alias_info (reg)
+     rtx reg;
+{
+  unsigned int regno = REGNO (reg);
+
+  if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
+    reg_known_value[regno] = reg;
+}
+
 /* Returns a canonical version of X, from the point of view alias
    analysis.  (For example, if X is a MEM whose address is a register,
    and the register has a known value (say a SYMBOL_REF), then a MEM
@@ -959,12 +993,10 @@ canon_rtx (x)
 
       if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1))
        {
-         /* We can tolerate LO_SUMs being offset here; these
-            rtl are used for nothing other than comparisons.  */
          if (GET_CODE (x0) == CONST_INT)
-           return plus_constant_for_output (x1, INTVAL (x0));
+           return plus_constant (x1, INTVAL (x0));
          else if (GET_CODE (x1) == CONST_INT)
-           return plus_constant_for_output (x0, INTVAL (x1));
+           return plus_constant (x0, INTVAL (x1));
          return gen_rtx_PLUS (GET_MODE (x), x0, x1);
        }
     }
@@ -974,17 +1006,8 @@ canon_rtx (x)
      MEM alone, but need to return the canonicalized MEM with
      all the flags with their original values.  */
   else if (GET_CODE (x) == MEM)
-    {
-      rtx addr = canon_rtx (XEXP (x, 0));
-
-      if (addr != XEXP (x, 0))
-       {
-         rtx new = gen_rtx_MEM (GET_MODE (x), addr);
+    x = replace_equiv_address_nv (x, canon_rtx (XEXP (x, 0)));
 
-         MEM_COPY_ATTRIBUTES (new, x);
-         x = new;
-       }
-    }
   return x;
 }
 
@@ -997,10 +1020,10 @@ static int
 rtx_equal_for_memref_p (x, y)
      rtx x, y;
 {
-  register int i;
-  register int j;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  int j;
+  enum rtx_code code;
+  const char *fmt;
 
   if (x == 0 && y == 0)
     return 1;
@@ -1027,6 +1050,9 @@ rtx_equal_for_memref_p (x, y)
   /* Some RTL can be compared without a recursive examination.  */
   switch (code)
     {
+    case VALUE:
+      return CSELIB_VAL_PTR (x) == CSELIB_VAL_PTR (y);
+
     case REG:
       return REGNO (x) == REGNO (y);
 
@@ -1096,6 +1122,12 @@ rtx_equal_for_memref_p (x, y)
            return 0;
          break;
 
+         /* This can happen for asm operands.  */
+       case 's':
+         if (strcmp (XSTR (x, i), XSTR (y, i)))
+           return 0;
+         break;
+
        /* This can happen for an asm which clobbers memory.  */
        case '0':
          break;
@@ -1117,9 +1149,9 @@ static rtx
 find_symbolic_term (x)
      rtx x;
 {
-  register int i;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  enum rtx_code code;
+  const char *fmt;
 
   code = GET_CODE (x);
   if (code == SYMBOL_REF || code == LABEL_REF)
@@ -1146,7 +1178,7 @@ find_symbolic_term (x)
 
 static rtx
 find_base_term (x)
-     register rtx x;
+     rtx x;
 {
   cselib_val *val;
   struct elt_loc_list *l;
@@ -1309,11 +1341,11 @@ base_alias_check (x, y, x_mode, y_mode)
        return 1;
       if (GET_CODE (x) == AND
          && (GET_CODE (XEXP (x, 1)) != CONST_INT
-             || GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
+             || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
        return 1;
       if (GET_CODE (y) == AND
          && (GET_CODE (XEXP (y, 1)) != CONST_INT
-             || GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
+             || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
        return 1;
       /* Differing symbols never alias.  */
       return 0;
@@ -1333,7 +1365,7 @@ base_alias_check (x, y, x_mode, y_mode)
   if (flag_argument_noalias > 1)
     return 0;
 
-  /* Weak noalias assertion (arguments are distinct, but may match globals). */
+  /* Weak noalias assertion (arguments are distinct, but may match globals).  */
   return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
 }
 
@@ -1420,7 +1452,7 @@ addr_side_effect_eval (addr, size, n_refs)
 
 static int
 memrefs_conflict_p (xsize, x, ysize, y, c)
-     register rtx x, y;
+     rtx x, y;
      int xsize, ysize;
      HOST_WIDE_INT c;
 {
@@ -1705,7 +1737,7 @@ true_dependence (mem, mem_mode, x, varies)
      rtx x;
      int (*varies) PARAMS ((rtx, int));
 {
-  register rtx x_addr, mem_addr;
+  rtx x_addr, mem_addr;
   rtx base;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
@@ -1778,7 +1810,7 @@ canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
      enum machine_mode mem_mode;
      int (*varies) PARAMS ((rtx, int));
 {
-  register rtx x_addr;
+  rtx x_addr;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
@@ -1897,8 +1929,8 @@ anti_dependence (mem, x)
 
 int
 output_dependence (mem, x)
-     register rtx mem;
-     register rtx x;
+     rtx mem;
+     rtx x;
 {
   return write_dependence_p (mem, x, /*writep=*/1);
 }
@@ -1911,7 +1943,7 @@ nonlocal_mentioned_p (x)
      rtx x;
 {
   rtx base;
-  register RTX_CODE code;
+  RTX_CODE code;
   int regno;
 
   code = GET_CODE (x);
@@ -1920,7 +1952,7 @@ nonlocal_mentioned_p (x)
     {
       /* 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_CALL_P (x))
+      if (code == CALL_INSN && CONST_OR_PURE_CALL_P (x))
         {
          x = CALL_INSN_FUNCTION_USAGE (x);
          if (x == 0)
@@ -2015,8 +2047,8 @@ nonlocal_mentioned_p (x)
   /* Recursively scan the operands of this expression.  */
 
   {
-    register const char *fmt = GET_RTX_FORMAT (code);
-    register int i;
+    const char *fmt = GET_RTX_FORMAT (code);
+    int i;
     
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
@@ -2027,7 +2059,7 @@ nonlocal_mentioned_p (x)
          }
        else if (fmt[i] == 'E')
          {
-           register int j;
+           int j;
            for (j = 0; j < XVECLEN (x, i); j++)
              if (nonlocal_mentioned_p (XVECEXP (x, i, j)))
                return 1;
@@ -2038,96 +2070,6 @@ nonlocal_mentioned_p (x)
   return 0;
 }
 
-/* Return non-zero if a loop (natural or otherwise) is present.
-   Inspired by Depth_First_Search_PP described in:
-
-     Advanced Compiler Design and Implementation
-     Steven Muchnick
-     Morgan Kaufmann, 1997
-
-   and heavily borrowed from flow_depth_first_order_compute.  */
-
-static int
-loop_p ()
-{
-  edge *stack;
-  int *pre;
-  int *post;
-  int sp;
-  int prenum = 1;
-  int postnum = 1;
-  sbitmap visited;
-
-  /* Allocate the preorder and postorder number arrays.  */
-  pre = (int *) xcalloc (n_basic_blocks, sizeof (int));
-  post = (int *) xcalloc (n_basic_blocks, sizeof (int));
-
-  /* Allocate stack for back-tracking up CFG.  */
-  stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
-  sp = 0;
-
-  /* Allocate bitmap to track nodes that have been visited.  */
-  visited = sbitmap_alloc (n_basic_blocks);
-
-  /* None of the nodes in the CFG have been visited yet.  */
-  sbitmap_zero (visited);
-
-  /* Push the first edge on to the stack.  */
-  stack[sp++] = ENTRY_BLOCK_PTR->succ;
-
-  while (sp)
-    {
-      edge e;
-      basic_block src;
-      basic_block dest;
-
-      /* Look at the edge on the top of the stack.  */
-      e = stack[sp - 1];
-      src = e->src;
-      dest = e->dest;
-
-      /* Check if the edge destination has been visited yet.  */
-      if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
-       {
-         /* Mark that we have visited the destination.  */
-         SET_BIT (visited, dest->index);
-
-         pre[dest->index] = prenum++;
-
-         if (dest->succ)
-           {
-             /* Since the DEST node has been visited for the first
-                time, check its successors.  */
-             stack[sp++] = dest->succ;
-           }
-         else
-           post[dest->index] = postnum++;
-       }
-      else
-       {
-         if (dest != EXIT_BLOCK_PTR
-             && pre[src->index] >= pre[dest->index]
-             && post[dest->index] == 0)
-           break;
-
-         if (! e->succ_next && src != ENTRY_BLOCK_PTR)
-           post[src->index] = postnum++;
-
-         if (e->succ_next)
-           stack[sp - 1] = e->succ_next;
-         else
-           sp--;
-       }
-    }
-
-  free (pre);
-  free (post);
-  free (stack);
-  sbitmap_free (visited);
-
-  return sp;
-}
-
 /* Mark the function if it is constant.  */
 
 void
@@ -2144,7 +2086,7 @@ mark_constant_function ()
     return;
 
   /* A loop might not return which counts as a side effect.  */
-  if (loop_p ())
+  if (mark_dfs_back_edges ())
     return;
 
   nonlocal_mentioned = 0;
@@ -2174,7 +2116,7 @@ static HARD_REG_SET argument_registers;
 void
 init_alias_once ()
 {
-  register int i;
+  int i;
 
 #ifndef OUTGOING_REGNO
 #define OUTGOING_REGNO(N) N
@@ -2182,7 +2124,7 @@ init_alias_once ()
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     /* Check whether this register can hold an incoming pointer
        argument.  FUNCTION_ARG_REGNO_P tests outgoing register
-       numbers, so translate if necessary due to register windows. */
+       numbers, so translate if necessary due to register windows.  */
     if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
        && HARD_REGNO_MODE_OK (i, Pmode))
       SET_HARD_REG_BIT (argument_registers, i);
@@ -2198,9 +2140,9 @@ init_alias_analysis ()
 {
   int maxreg = max_reg_num ();
   int changed, pass;
-  register int i;
-  register unsigned int ui;
-  register rtx insn;
+  int i;
+  unsigned int ui;
+  rtx insn;
 
   reg_known_value_size = maxreg;
 
@@ -2310,7 +2252,7 @@ init_alias_analysis ()
 
              /* If this insn has a noalias note, process it,  Otherwise,
                 scan for sets.  A simple set will have no side effects
-                which could change the base value of any other register. */
+                which could change the base value of any other register.  */
 
              if (GET_CODE (PATTERN (insn)) == SET
                  && REG_NOTES (insn) != 0
@@ -2349,8 +2291,7 @@ init_alias_analysis ()
                      rtx op0 = XEXP (src, 0);
                      op0 = reg_known_value[REGNO (op0)];
                      reg_known_value[regno]
-                       = plus_constant_for_output (op0,
-                                                   INTVAL (XEXP (src, 1)));
+                       = plus_constant (op0, INTVAL (XEXP (src, 1)));
                      reg_known_equiv_p[regno] = 0;
                    }
                  else if (REG_N_SETS (regno) == 1