OSDN Git Service

2007-02-12 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index db8555f..3ac6848 100644 (file)
@@ -1,6 +1,6 @@
 /* Alias analysis for GNU C
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
 This file is part of GCC.
@@ -49,7 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 
 /* The aliasing API provided here solves related but different problems:
 
-   Say there exists (in c) 
+   Say there exists (in c)
 
    struct X {
      struct Y y1;
@@ -87,7 +87,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    this may be too conservative for some C++ types.
 
    The pass ipa-type-escape does this analysis for the types whose
-   instances do not escape across the compilation boundary.  
+   instances do not escape across the compilation boundary.
 
    Historically in GCC, these two problems were combined and a single
    data structure was used to represent the solution to these
@@ -109,11 +109,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    `double'.  (However, a store to an `int' cannot alias a `double'
    and vice versa.)  We indicate this via a tree structure that looks
    like:
-           struct S
-            /   \
+          struct S
+           /   \
           /     \
-         |/_     _\|
-         int    double
+        |/_     _\|
+        int    double
 
    (The arrows are directed and point downwards.)
     In this situation we say the alias set for `struct S' is the
@@ -149,7 +149,6 @@ struct alias_set_entry GTY(())
 typedef struct alias_set_entry *alias_set_entry;
 
 static int rtx_equal_for_memref_p (rtx, rtx);
-static rtx find_symbolic_term (rtx);
 static int memrefs_conflict_p (int, rtx, int, rtx, HOST_WIDE_INT);
 static void record_set (rtx, rtx, void *);
 static int base_alias_check (rtx, rtx, enum machine_mode,
@@ -293,6 +292,26 @@ insert_subset_children (splay_tree_node node, void *data)
   return 0;
 }
 
+/* Return true if the first alias set is a subset of the second.  */
+
+bool
+alias_set_subset_of (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
+{
+  alias_set_entry ase;
+
+  /* Everything is a subset of the "aliases everything" set.  */
+  if (set2 == 0)
+    return true;
+
+  /* Otherwise, check if set1 is a subset of set2.  */
+  ase = get_alias_set_entry (set2);
+  if (ase != 0
+      && (splay_tree_lookup (ase->children,
+                            (splay_tree_key) set1)))
+    return true;
+  return false;
+}
+
 /* Return 1 if the two specified alias sets may conflict.  */
 
 int
@@ -730,7 +749,7 @@ record_component_aliases (tree type)
        {
          int i;
          tree binfo, base_binfo;
-         
+
          for (binfo = TYPE_BINFO (type), i = 0;
               BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
            record_alias_subset (superset,
@@ -1023,7 +1042,7 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
      If neither case holds, reject the original base value as invalid.
      Note that the following situation is not detected:
 
-         extern int x, y;  int *p = &x; p += (&y-&x);
+        extern int x, y;  int *p = &x; p += (&y-&x);
 
      ANSI C does not allow computing the difference of addresses
      of distinct top level objects.  */
@@ -1091,7 +1110,7 @@ clear_reg_alias_info (rtx reg)
 
 /* If a value is known for REGNO, return it.  */
 
-rtx 
+rtx
 get_reg_known_value (unsigned int regno)
 {
   if (regno >= FIRST_PSEUDO_REGISTER)
@@ -1325,39 +1344,6 @@ rtx_equal_for_memref_p (rtx x, rtx y)
   return 1;
 }
 
-/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
-   X and return it, or return 0 if none found.  */
-
-static rtx
-find_symbolic_term (rtx x)
-{
-  int i;
-  enum rtx_code code;
-  const char *fmt;
-
-  code = GET_CODE (x);
-  if (code == SYMBOL_REF || code == LABEL_REF)
-    return x;
-  if (OBJECT_P (x))
-    return 0;
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      rtx t;
-
-      if (fmt[i] == 'e')
-       {
-         t = find_symbolic_term (XEXP (x, i));
-         if (t != 0)
-           return t;
-       }
-      else if (fmt[i] == 'E')
-       break;
-    }
-  return 0;
-}
-
 rtx
 find_base_term (rtx x)
 {
@@ -1620,7 +1606,7 @@ addr_side_effect_eval (rtx addr, int size, int n_refs)
 
   if (offset)
     addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0),
-                        GEN_INT (offset));
+                        GEN_INT (offset));
   else
     addr = XEXP (addr, 0);
   addr = canon_rtx (addr);
@@ -1857,13 +1843,15 @@ fixed_scalar_and_varying_struct_p (rtx mem1, rtx mem2, rtx mem1_addr,
   if (! flag_strict_aliasing)
     return NULL_RTX;
 
-  if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+  if (MEM_ALIAS_SET (mem2)
+      && MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
       && !varies_p (mem1_addr, 1) && varies_p (mem2_addr, 1))
     /* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
        varying address.  */
     return mem1;
 
-  if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+  if (MEM_ALIAS_SET (mem1)
+      && MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
       && varies_p (mem1_addr, 1) && !varies_p (mem2_addr, 1))
     /* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
        varying address.  */
@@ -2001,14 +1989,14 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
   /* Unless both have exprs, we can't tell anything.  */
   if (exprx == 0 || expry == 0)
     return 0;
-  
+
   /* If both are field references, we may be able to determine something.  */
   if (TREE_CODE (exprx) == COMPONENT_REF
       && TREE_CODE (expry) == COMPONENT_REF
       && nonoverlapping_component_refs_p (exprx, expry))
     return 1;
 
-  
+
   /* If the field reference test failed, look at the DECLs involved.  */
   moffsetx = MEM_OFFSET (x);
   if (TREE_CODE (exprx) == COMPONENT_REF)
@@ -2020,7 +2008,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
         tree fieldcontext = DECL_FIELD_CONTEXT (field);
         if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
                                                       TREE_TYPE (field)))
-          return 1;     
+          return 1;
        }
       {
        tree t = decl_for_component_ref (exprx);
@@ -2048,7 +2036,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
         tree fieldcontext = DECL_FIELD_CONTEXT (field);
         if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
                                                       TREE_TYPE (field)))
-          return 1;     
+          return 1;
        }
       {
        tree t = decl_for_component_ref (expry);
@@ -2149,7 +2137,7 @@ true_dependence (rtx mem, enum machine_mode mem_mode, rtx x,
     return 1;
 
   /* (mem:BLK (scratch)) is a special mechanism to conflict with everything.
-     This is used in epilogue deallocation functions.  */
+     This is used in epilogue deallocation functions, and in cselib.  */
   if (GET_MODE (x) == BLKmode && GET_CODE (XEXP (x, 0)) == SCRATCH)
     return 1;
   if (GET_MODE (mem) == BLKmode && GET_CODE (XEXP (mem, 0)) == SCRATCH)
@@ -2431,9 +2419,7 @@ init_alias_analysis (void)
   if (reg_base_value)
     VEC_truncate (rtx, reg_base_value, 0);
 
-  VEC_safe_grow (rtx, gc, reg_base_value, maxreg);
-  memset (VEC_address (rtx, reg_base_value), 0,
-         sizeof (rtx) * VEC_length (rtx, reg_base_value));
+  VEC_safe_grow_cleared (rtx, gc, reg_base_value, maxreg);
 
   new_reg_base_value = XNEWVEC (rtx, maxreg);
   reg_seen = XNEWVEC (char, maxreg);
@@ -2506,8 +2492,8 @@ init_alias_analysis (void)
 #endif
 
              /* 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.  */
+                scan for sets.  A simple set will have no side effects
+                which could change the base value of any other register.  */
 
              if (GET_CODE (PATTERN (insn)) == SET
                  && REG_NOTES (insn) != 0
@@ -2526,10 +2512,12 @@ init_alias_analysis (void)
                  rtx src = SET_SRC (set);
                  rtx t;
 
-                 if (REG_NOTES (insn) != 0
-                     && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
-                          && REG_N_SETS (regno) == 1)
-                         || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
+                 note = find_reg_equal_equiv_note (insn);
+                 if (note && REG_NOTE_KIND (note) == REG_EQUAL
+                     && REG_N_SETS (regno) != 1)
+                   note = NULL_RTX;
+
+                 if (note != NULL_RTX
                      && GET_CODE (XEXP (note, 0)) != EXPR_LIST
                      && ! rtx_varies_p (XEXP (note, 0), 1)
                      && ! reg_overlap_mentioned_p (SET_DEST (set),
@@ -2563,8 +2551,8 @@ init_alias_analysis (void)
        }
 
       /* Now propagate values from new_reg_base_value to reg_base_value.  */
-      gcc_assert (maxreg == (unsigned int) max_reg_num());
-      
+      gcc_assert (maxreg == (unsigned int) max_reg_num ());
+
       for (ui = 0; ui < maxreg; ui++)
        {
          if (new_reg_base_value[ui]
@@ -2584,38 +2572,6 @@ init_alias_analysis (void)
     if (reg_known_value[i] == 0)
       reg_known_value[i] = regno_reg_rtx[i + FIRST_PSEUDO_REGISTER];
 
-  /* Simplify the reg_base_value array so that no register refers to
-     another register, except to special registers indirectly through
-     ADDRESS expressions.
-
-     In theory this loop can take as long as O(registers^2), but unless
-     there are very long dependency chains it will run in close to linear
-     time.
-
-     This loop may not be needed any longer now that the main loop does
-     a better job at propagating alias information.  */
-  pass = 0;
-  do
-    {
-      changed = 0;
-      pass++;
-      for (ui = 0; ui < maxreg; ui++)
-       {
-         rtx base = VEC_index (rtx, reg_base_value, ui);
-         if (base && REG_P (base))
-           {
-             unsigned int base_regno = REGNO (base);
-             if (base_regno == ui)             /* register set from itself */
-               VEC_replace (rtx, reg_base_value, ui, 0);
-             else
-               VEC_replace (rtx, reg_base_value, ui,
-                            VEC_index (rtx, reg_base_value, base_regno));
-             changed = 1;
-           }
-       }
-    }
-  while (changed && pass < MAX_ALIAS_LOOP_PASSES);
-
   /* Clean up.  */
   free (new_reg_base_value);
   new_reg_base_value = 0;