OSDN Git Service

* optabs.h (OTI_flodiv, flodiv_optab): Kill.
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index 6e92533..a79589f 100644 (file)
@@ -1,5 +1,5 @@
 /* Alias analysis for GNU C
-   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   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.
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "tm_p.h"
 #include "function.h"
-#include "insn-flags.h"
 #include "expr.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -88,13 +87,15 @@ typedef struct alias_set_entry
 
 static int rtx_equal_for_memref_p      PARAMS ((rtx, rtx));
 static rtx find_symbolic_term          PARAMS ((rtx));
-static rtx get_addr                    PARAMS ((rtx));
+rtx get_addr                           PARAMS ((rtx));
 static int memrefs_conflict_p          PARAMS ((int, rtx, int, rtx,
                                                 HOST_WIDE_INT));
 static void record_set                 PARAMS ((rtx, rtx, void *));
 static rtx find_base_term              PARAMS ((rtx));
 static int base_alias_check            PARAMS ((rtx, rtx, enum machine_mode,
                                                 enum machine_mode));
+static int handled_component_p         PARAMS ((tree));
+static int can_address_p               PARAMS ((tree));
 static rtx find_base_value             PARAMS ((rtx));
 static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
 static int insert_subset_children       PARAMS ((splay_tree_node, void*));
@@ -106,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.  */
@@ -277,6 +276,24 @@ alias_sets_conflict_p (set1, set2)
   return 0;
 }
 \f
+/* Set the alias set of MEM to SET.  */
+
+void
+set_mem_alias_set (mem, set)
+     rtx mem;
+     HOST_WIDE_INT set;
+{
+  /* We would like to do this test but can't yet since when converting a
+     REG to a MEM, the alias set field is undefined.  */
+#if 0
+  /* If the new and old alias sets don't conflict, something is wrong.  */
+  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
+    abort ();
+#endif
+
+  MEM_ALIAS_SET (mem) = set;
+}
+\f
 /* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
    has any readonly fields.  If any of the fields have types that
    contain readonly fields, return true as well.  */
@@ -309,24 +326,33 @@ int
 objects_must_conflict_p (t1, t2)
      tree t1, t2;
 {
+  /* If neither has a type specified, we don't know if they'll conflict
+     because we may be using them to store objects of various types, for
+     example the argument and local variables areas of inlined functions.  */
+  if (t1 == 0 && t2 == 0)
+    return 0;
+
+  /* If one or the other has readonly fields or is readonly,
+     then they may not conflict.  */
+  if ((t1 != 0 && readonly_fields_p (t1))
+      || (t2 != 0 && readonly_fields_p (t2))
+      || (t1 != 0 && TYPE_READONLY (t1))
+      || (t2 != 0 && TYPE_READONLY (t2)))
+    return 0;
+
   /* If they are the same type, they must conflict.  */
   if (t1 == t2
       /* Likewise if both are volatile.  */
       || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
     return 1;
 
-  /* We now know they are different types.  If one or both has readonly fields
-     or if one is readonly and the other not, they may not conflict.
-     Likewise if one is aggregate and the other is scalar.  */
-  if ((t1 != 0 && readonly_fields_p (t1))
-      || (t2 != 0 && readonly_fields_p (t2))
-      || ((t1 != 0 && TYPE_READONLY (t1))
-         != (t2 != 0 && TYPE_READONLY (t2)))
-      || ((t1 != 0 && AGGREGATE_TYPE_P (t1))
-         != (t2 != 0 && AGGREGATE_TYPE_P (t2))))
+  /* If one is aggregate and the other is scalar then they may not
+     conflict.  */
+  if ((t1 != 0 && AGGREGATE_TYPE_P (t1))
+      != (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);
 }
@@ -373,7 +399,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.  */
@@ -391,6 +416,59 @@ find_base_decl (t)
     }
 }
 
+/* Return 1 if T is an expression that get_inner_reference handles.  */
+
+static int
+handled_component_p (t)
+     tree t;
+{
+  switch (TREE_CODE (t))
+    {
+    case BIT_FIELD_REF:
+    case COMPONENT_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case NON_LVALUE_EXPR:
+      return 1;
+
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+      return (TYPE_MODE (TREE_TYPE (t))
+             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
+
+    default:
+      return 0;
+    }
+}
+
+/* Return 1 if all the nested component references handled by
+   get_inner_reference in T are such that we can address the object in T.  */
+
+static int
+can_address_p (t)
+     tree t;
+{
+  /* If we're at the end, it is vacuously addressable.  */
+  if (! handled_component_p (t))
+    return 1;
+
+  /* Bitfields are never addressable.  */
+  else if (TREE_CODE (t) == BIT_FIELD_REF)
+    return 0;
+
+  else if (TREE_CODE (t) == COMPONENT_REF
+          && ! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))
+          && can_address_p (TREE_OPERAND (t, 0)))
+    return 1;
+
+  else if ((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
+          && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
+          && can_address_p (TREE_OPERAND (t, 0)))
+    return 1;
+
+  return 0;
+}
+
 /* Return the alias set for T, which may be either a type or an
    expression.  Call language-specific routine for help, if needed.  */
 
@@ -430,35 +508,9 @@ get_alias_set (t)
       /* 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 (1)
-       {
-         /* Unnamed bitfields are not an addressable object.  */
-         if (TREE_CODE (t) == BIT_FIELD_REF)
-           ;
-         else if (TREE_CODE (t) == COMPONENT_REF)
-           {
-             if (! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
-               /* Stop at an adressable decl.  */
-               break;
-           }
-         else if (TREE_CODE (t) == ARRAY_REF)
-           {
-             if (! TYPE_NONALIASED_COMPONENT
-                 (TREE_TYPE (TREE_OPERAND (t, 0))))
-               /* Stop at an addresssable array element.  */
-               break;
-           }
-         else if (TREE_CODE (t) != NON_LVALUE_EXPR
-                  && ! ((TREE_CODE (t) == NOP_EXPR
-                     || TREE_CODE (t) == CONVERT_EXPR)
-                    && (TYPE_MODE (TREE_TYPE (t))
-                        == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))))))
-           /* Stop if not one of above and not mode-preserving conversion. */
-           break;
-
-         t = TREE_OPERAND (t, 0);
-       }
-                  
+      while (handled_component_p (t) && ! can_address_p (t))
+       t = TREE_OPERAND (t, 0);
+
       if (TREE_CODE (t) == INDIRECT_REF)
        {
          /* Check for accesses through restrict-qualified pointers.  */
@@ -474,6 +526,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)
@@ -705,7 +764,7 @@ find_base_value (src)
       if (GET_CODE (src) != PLUS && GET_CODE (src) != MINUS)
        break;
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case PLUS:
     case MINUS:
@@ -754,7 +813,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;
@@ -922,12 +981,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);
        }
     }
@@ -937,17 +994,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;
 }
 
@@ -990,6 +1038,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);
 
@@ -1059,6 +1110,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;
@@ -1272,11 +1329,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;
@@ -1296,7 +1353,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);
 }
 
@@ -1304,7 +1361,7 @@ base_alias_check (x, y, x_mode, y_mode)
    it unchanged unless it is a value; in the latter case we call cselib to get
    a more useful rtx.  */
 
-static rtx
+rtx
 get_addr (x)
      rtx x;
 {
@@ -1729,6 +1786,63 @@ true_dependence (mem, mem_mode, x, varies)
                                              varies);
 }
 
+/* Canonical true dependence: X is read after store in MEM takes place.
+   Variant of true_dependece which assumes MEM has already been 
+   canonicalized (hence we no longer do that here).  
+   The mem_addr argument has been added, since true_dependence computed 
+   this value prior to canonicalizing.  */
+
+int
+canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
+     rtx mem, mem_addr, x;
+     enum machine_mode mem_mode;
+     int (*varies) PARAMS ((rtx, int));
+{
+  register rtx x_addr;
+
+  if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
+    return 1;
+
+  if (DIFFERENT_ALIAS_SETS_P (x, mem))
+    return 0;
+
+  /* If X is an unchanging read, then it can't possibly conflict with any
+     non-unchanging store.  It may conflict with an unchanging write though,
+     because there may be a single store to this address to initialize it.
+     Just fall through to the code below to resolve the case where we have
+     both an unchanging read and an unchanging write.  This won't handle all
+     cases optimally, but the possible performance loss should be
+     negligible.  */
+  if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
+    return 0;
+
+  x_addr = get_addr (XEXP (x, 0));
+
+  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
+    return 0;
+
+  x_addr = canon_rtx (x_addr);
+  if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
+                           SIZE_FOR_MODE (x), x_addr, 0))
+    return 0;
+
+  if (aliases_everything_p (x))
+    return 1;
+
+  /* We cannot use aliases_everyting_p to test MEM, since we must look
+     at MEM_MODE, rather than GET_MODE (MEM).  */
+  if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
+    return 1;
+
+  /* In true_dependence we also allow BLKmode to alias anything.  Why
+     don't we do this in anti_dependence and output_dependence?  */
+  if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
+    return 1;
+
+  return ! fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
+                                             varies);
+}
+
 /* Returns non-zero if a write to X might alias a previous read from
    (or, if WRITEP is non-zero, a write to) MEM.  */
 
@@ -1826,7 +1940,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)
@@ -1844,7 +1958,7 @@ nonlocal_mentioned_p (x)
        {
          /* Global registers are not local.  */
          if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
-             && global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)])
+             && global_regs[subreg_regno (x)])
            return 1;
          return 0;
        }
@@ -1944,96 +2058,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
@@ -2050,7 +2074,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;
@@ -2088,7 +2112,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);
@@ -2216,7 +2240,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
@@ -2239,6 +2263,7 @@ init_alias_analysis ()
                           && REG_N_SETS (regno) == 1)
                          || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
                      && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+                     && ! rtx_varies_p (XEXP (note, 0), 1)
                      && ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
                    {
                      reg_known_value[regno] = XEXP (note, 0);
@@ -2252,11 +2277,9 @@ init_alias_analysis ()
                           && GET_CODE (XEXP (src, 1)) == CONST_INT)
                    {
                      rtx op0 = XEXP (src, 0);
-                     if (reg_known_value[REGNO (op0)])
-                       op0 = reg_known_value[REGNO (op0)];
+                     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