OSDN Git Service

2010-04-20 Harald Anlauf <anlauf@gmx.de>
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index 41a2f23..a1e12fb 100644 (file)
@@ -1,6 +1,6 @@
 /* Alias analysis for GNU C
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2007, 2008, 2009 Free Software Foundation, Inc.
+   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
 This file is part of GCC.
@@ -265,11 +265,6 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
   if (!expr)
     return false;
 
-  /* If MEM_OFFSET or MEM_SIZE are NULL punt.  */
-  if (!MEM_OFFSET (mem)
-      || !MEM_SIZE (mem))
-    return false;
-
   ao_ref_init (ref, expr);
 
   /* Get the base of the reference and see if we have to reject or
@@ -278,17 +273,17 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
   if (base == NULL_TREE)
     return false;
 
+  /* The tree oracle doesn't like to have these.  */
+  if (TREE_CODE (base) == FUNCTION_DECL
+      || TREE_CODE (base) == LABEL_DECL)
+    return false;
+
   /* If this is a pointer dereference of a non-SSA_NAME punt.
      ???  We could replace it with a pointer to anything.  */
   if (INDIRECT_REF_P (base)
       && TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME)
     return false;
 
-  /* The tree oracle doesn't like to have these.  */
-  if (TREE_CODE (base) == FUNCTION_DECL
-      || TREE_CODE (base) == LABEL_DECL)
-    return false;
-
   /* If this is a reference based on a partitioned decl replace the
      base with an INDIRECT_REF of the pointer representative we
      created during stack slot partitioning.  */
@@ -307,6 +302,18 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
 
   ref->ref_alias_set = MEM_ALIAS_SET (mem);
 
+  /* If MEM_OFFSET or MEM_SIZE are NULL we have to punt.
+     Keep points-to related information though.  */
+  if (!MEM_OFFSET (mem)
+      || !MEM_SIZE (mem))
+    {
+      ref->ref = NULL_TREE;
+      ref->offset = 0;
+      ref->size = -1;
+      ref->max_size = -1;
+      return true;
+    }
+
   /* If the base decl is a parameter we can have negative MEM_OFFSET in
      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
      here.  */
@@ -406,7 +413,7 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2)
   /* Otherwise, check if set1 is a subset of set2.  */
   ase = get_alias_set_entry (set2);
   if (ase != 0
-      && ((ase->has_zero_child && set1 == 0)
+      && (ase->has_zero_child
          || splay_tree_lookup (ase->children,
                                (splay_tree_key) set1)))
     return true;
@@ -1684,14 +1691,7 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode,
       || (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode))
     return 0;
 
-  if (! flag_argument_noalias)
-    return 1;
-
-  if (flag_argument_noalias > 1)
-    return 0;
-
-  /* Weak noalias assertion (arguments are distinct, but may match globals).  */
-  return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
+  return 1;
 }
 
 /* Convert the address X into something we can use.  This is done by returning
@@ -1759,8 +1759,12 @@ addr_side_effect_eval (rtx addr, int size, int n_refs)
   return addr;
 }
 
-/* Return nonzero if X and Y (memory addresses) could reference the
-   same location in memory.  C is an offset accumulator.  When
+/* Return one if X and Y (memory addresses) reference the
+   same location in memory or if the references overlap.
+   Return zero if they do not overlap, else return
+   minus one in which case they still might reference the same location.
+
+   C is an offset accumulator.  When
    C is nonzero, we are testing aliases between X and Y + C.
    XSIZE is the size in bytes of the X reference,
    similarly YSIZE is the size in bytes for Y.
@@ -1775,15 +1779,51 @@ addr_side_effect_eval (rtx addr, int size, int n_refs)
    align memory references, as is done on the Alpha.
 
    Nice to notice that varying addresses cannot conflict with fp if no
-   local variables had their addresses taken, but that's too hard now.  */
+   local variables had their addresses taken, but that's too hard now.
+
+   ???  Contrary to the tree alias oracle this does not return
+   one for X + non-constant and Y + non-constant when X and Y are equal.
+   If that is fixed the TBAA hack for union type-punning can be removed.  */
 
 static int
 memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
 {
   if (GET_CODE (x) == VALUE)
-    x = get_addr (x);
+    {
+      if (REG_P (y))
+       {
+         struct elt_loc_list *l = NULL;
+         if (CSELIB_VAL_PTR (x))
+           for (l = CSELIB_VAL_PTR (x)->locs; l; l = l->next)
+             if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, y))
+               break;
+         if (l)
+           x = y;
+         else
+           x = get_addr (x);
+       }
+      /* Don't call get_addr if y is the same VALUE.  */
+      else if (x != y)
+       x = get_addr (x);
+    }
   if (GET_CODE (y) == VALUE)
-    y = get_addr (y);
+    {
+      if (REG_P (x))
+       {
+         struct elt_loc_list *l = NULL;
+         if (CSELIB_VAL_PTR (y))
+           for (l = CSELIB_VAL_PTR (y)->locs; l; l = l->next)
+             if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, x))
+               break;
+         if (l)
+           y = x;
+         else
+           y = get_addr (y);
+       }
+      /* Don't call get_addr if x is the same VALUE.  */
+      else if (y != x)
+       y = get_addr (y);
+    }
   if (GET_CODE (x) == HIGH)
     x = XEXP (x, 0);
   else if (GET_CODE (x) == LO_SUM)
@@ -1841,7 +1881,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
          else if (CONST_INT_P (y1))
            return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
 
-         return 1;
+         return -1;
        }
       else if (CONST_INT_P (x1))
        return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
@@ -1856,7 +1896,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
       if (CONST_INT_P (y1))
        return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
       else
-       return 1;
+       return -1;
     }
 
   if (GET_CODE (x) == GET_CODE (y))
@@ -1871,7 +1911,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
          rtx x1 = canon_rtx (XEXP (x, 1));
          rtx y1 = canon_rtx (XEXP (y, 1));
          if (! rtx_equal_for_memref_p (x1, y1))
-           return 1;
+           return -1;
          x0 = canon_rtx (XEXP (x, 0));
          y0 = canon_rtx (XEXP (y, 0));
          if (rtx_equal_for_memref_p (x0, y0))
@@ -1880,7 +1920,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
 
          /* Can't properly adjust our sizes.  */
          if (!CONST_INT_P (x1))
-           return 1;
+           return -1;
          xsize /= INTVAL (x1);
          ysize /= INTVAL (x1);
          c /= INTVAL (x1);
@@ -1939,9 +1979,10 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
                || (rtx_equal_for_memref_p (x, y)
                    && ((c >= 0 && xsize > c) || (c < 0 && ysize+c > 0))));
 
-      return 1;
+      return -1;
     }
-  return 1;
+
+  return -1;
 }
 
 /* Functions to compute memory dependencies.
@@ -2138,6 +2179,13 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
   if (exprx == 0 || expry == 0)
     return 0;
 
+  /* For spill-slot accesses make sure we have valid offsets.  */
+  if ((exprx == get_spill_slot_decl (false)
+       && ! MEM_OFFSET (x))
+      || (expry == get_spill_slot_decl (false)
+         && ! MEM_OFFSET (y)))
+    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
@@ -2166,13 +2214,6 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
        exprx = t;
       }
     }
-  else if (INDIRECT_REF_P (exprx))
-    {
-      exprx = TREE_OPERAND (exprx, 0);
-      if (flag_argument_noalias < 2
-         || TREE_CODE (exprx) != PARM_DECL)
-       return 0;
-    }
 
   moffsety = MEM_OFFSET (y);
   if (TREE_CODE (expry) == COMPONENT_REF)
@@ -2194,13 +2235,6 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
        expry = t;
       }
     }
-  else if (INDIRECT_REF_P (expry))
-    {
-      expry = TREE_OPERAND (expry, 0);
-      if (flag_argument_noalias < 2
-         || TREE_CODE (expry) != PARM_DECL)
-       return 0;
-    }
 
   if (! DECL_P (exprx) || ! DECL_P (expry))
     return 0;
@@ -2294,6 +2328,7 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
 {
   rtx x_addr, mem_addr;
   rtx base;
+  int ret;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
@@ -2308,18 +2343,12 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
       || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
     return 1;
 
-  if (DIFFERENT_ALIAS_SETS_P (x, mem))
-    return 0;
-
   /* Read-only memory is by definition never modified, and therefore can't
      conflict with anything.  We don't expect to find read-only set on MEM,
      but stupid user tricks can produce them, so don't die.  */
   if (MEM_READONLY_P (x))
     return 0;
 
-  if (nonoverlapping_memrefs_p (mem, x))
-    return 0;
-
   /* If we have MEMs refering to different address spaces (which can
      potentially overlap), we cannot easily tell from the addresses
      whether the references overlap.  */
@@ -2344,8 +2373,14 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
   x_addr = canon_rtx (x_addr);
   mem_addr = canon_rtx (mem_addr);
 
-  if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
-                           SIZE_FOR_MODE (x), x_addr, 0))
+  if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
+                                SIZE_FOR_MODE (x), x_addr, 0)) != -1)
+    return ret;
+
+  if (DIFFERENT_ALIAS_SETS_P (x, mem))
+    return 0;
+
+  if (nonoverlapping_memrefs_p (mem, x))
     return 0;
 
   if (aliases_everything_p (x))
@@ -2378,6 +2413,8 @@ int
 canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
                       const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
 {
+  int ret;
+
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
 
@@ -2391,18 +2428,12 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
       || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
     return 1;
 
-  if (DIFFERENT_ALIAS_SETS_P (x, mem))
-    return 0;
-
   /* Read-only memory is by definition never modified, and therefore can't
      conflict with anything.  We don't expect to find read-only set on MEM,
      but stupid user tricks can produce them, so don't die.  */
   if (MEM_READONLY_P (x))
     return 0;
 
-  if (nonoverlapping_memrefs_p (x, mem))
-    return 0;
-
   /* If we have MEMs refering to different address spaces (which can
      potentially overlap), we cannot easily tell from the addresses
      whether the references overlap.  */
@@ -2416,8 +2447,14 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
     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))
+  if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
+                                SIZE_FOR_MODE (x), x_addr, 0)) != -1)
+    return ret;
+
+  if (DIFFERENT_ALIAS_SETS_P (x, mem))
+    return 0;
+
+  if (nonoverlapping_memrefs_p (x, mem))
     return 0;
 
   if (aliases_everything_p (x))
@@ -2448,6 +2485,7 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
   rtx x_addr, mem_addr;
   const_rtx fixed_scalar;
   rtx base;
+  int ret;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
@@ -2466,9 +2504,6 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
   if (!writep && MEM_READONLY_P (mem))
     return 0;
 
-  if (nonoverlapping_memrefs_p (x, mem))
-    return 0;
-
   /* If we have MEMs refering to different address spaces (which can
      potentially overlap), we cannot easily tell from the addresses
      whether the references overlap.  */
@@ -2494,8 +2529,11 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
   x_addr = canon_rtx (x_addr);
   mem_addr = canon_rtx (mem_addr);
 
-  if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
-                          SIZE_FOR_MODE (x), x_addr, 0))
+  if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
+                                SIZE_FOR_MODE (x), x_addr, 0)) != -1)
+    return ret;
+
+  if (nonoverlapping_memrefs_p (x, mem))
     return 0;
 
   fixed_scalar