OSDN Git Service

PR c++/44059
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-alias.c
index 4c052be..2db3058 100644 (file)
@@ -1,5 +1,5 @@
 /* Alias analysis for trees.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -24,9 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "timevar.h"
 #include "expr.h"
@@ -35,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "function.h"
 #include "diagnostic.h"
+#include "tree-pretty-print.h"
 #include "tree-dump.h"
 #include "gimple.h"
 #include "tree-flow.h"
@@ -189,7 +188,7 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
        ptr = TREE_OPERAND (base, 0);
       else if (base
               && SSA_VAR_P (base))
-       return operand_equal_p (base, decl, 0);
+       return base == decl;
       else if (base
               && CONSTANT_CLASS_P (base))
        return false;
@@ -214,7 +213,7 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
   if (DECL_RESTRICTED_P (decl)
       && TYPE_RESTRICT (TREE_TYPE (ptr))
       && pi->pt.vars_contains_restrict)
-    return bitmap_bit_p (pi->pt.vars, DECL_UID (decl));
+    return bitmap_bit_p (pi->pt.vars, DECL_PT_UID (decl));
 
   return pt_solution_includes (&pi->pt, decl);
 }
@@ -325,7 +324,7 @@ dump_alias_info (FILE *file)
   fprintf (file, "\n\nAlias information for %s\n\n", funcname);
 
   fprintf (file, "Aliased symbols\n\n");
-  
+
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
       if (may_be_aliased (var))
@@ -336,8 +335,6 @@ dump_alias_info (FILE *file)
 
   fprintf (file, "\nESCAPED");
   dump_points_to_solution (file, &cfun->gimple_df->escaped);
-  fprintf (file, "\nCALLUSED");
-  dump_points_to_solution (file, &cfun->gimple_df->callused);
 
   fprintf (file, "\n\nFlow-insensitive points-to information\n\n");
 
@@ -345,7 +342,7 @@ dump_alias_info (FILE *file)
     {
       tree ptr = ssa_name (i);
       struct ptr_info_def *pi;
-      
+
       if (ptr == NULL_TREE
          || SSA_NAME_IN_FREE_LIST (ptr))
        continue;
@@ -403,6 +400,9 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
   if (pt->escaped)
     fprintf (file, ", points-to escaped");
 
+  if (pt->ipa_escaped)
+    fprintf (file, ", points-to unit escaped");
+
   if (pt->null)
     fprintf (file, ", points-to NULL");
 
@@ -412,6 +412,8 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
       dump_decl_set (file, pt->vars);
       if (pt->vars_contains_global)
        fprintf (file, " (includes global vars)");
+      if (pt->vars_contains_restrict)
+       fprintf (file, " (includes restrict tags)");
     }
 }
 
@@ -537,13 +539,24 @@ same_type_for_tbaa (tree type1, tree type2)
   if (TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
     return 1;
 
-  /* ???  Array types are not properly unified in all cases as we have
+  /* ??? Array types are not properly unified in all cases as we have
      spurious changes in the index types for example.  Removing this
      causes all sorts of problems with the Fortran frontend.  */
   if (TREE_CODE (type1) == ARRAY_TYPE
       && TREE_CODE (type2) == ARRAY_TYPE)
     return -1;
 
+  /* ??? In Ada, an lvalue of an unconstrained type can be used to access an
+     object of one of its constrained subtypes, e.g. when a function with an
+     unconstrained parameter passed by reference is called on an object and
+     inlined.  But, even in the case of a fixed size, type and subtypes are
+     not equivalent enough as to share the same TYPE_CANONICAL, since this
+     would mean that conversions between them are useless, whereas they are
+     not (e.g. type and subtypes can have different modes).  So, in the end,
+     they are only guaranteed to have the same alias set.  */
+  if (get_alias_set (type1) == get_alias_set (type2))
+    return -1;
+
   /* The types are known to be not equal.  */
   return 0;
 }
@@ -600,19 +613,9 @@ aliasing_component_refs_p (tree ref1, tree type1,
       offset1 -= offadj;
       return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
     }
-
-  /* We haven't found any common base to apply offset-based disambiguation.
-     There are two cases:
-       1. The base access types have the same alias set.  This can happen
-         in Ada when a function with an unconstrained parameter passed by
-         reference is called on a constrained object and inlined: the types
-         have the same alias set but aren't equivalent.  The references may
-         alias in this case.
-       2. The base access types don't have the same alias set, i.e. one set
-         is a subset of the other.  We have proved that B1 is not in the
-         access path B2.path and that B2 is not in the access path B1.path
-         so the references may not alias.  */
-  return get_alias_set (type1) == get_alias_set (type2);
+  /* If we have two type access paths B1.path1 and B2.path2 they may
+     only alias if either B1 is in B2.path2 or B2 is in B1.path1.  */
+  return false;
 }
 
 /* Return true if two memory references based on the variables BASE1
@@ -628,7 +631,7 @@ decl_refs_may_alias_p (tree base1,
   gcc_assert (SSA_VAR_P (base1) && SSA_VAR_P (base2));
 
   /* If both references are based on different variables, they cannot alias.  */
-  if (!operand_equal_p (base1, base2, 0))
+  if (base1 != base2)
     return false;
 
   /* If both references are based on the same variable, they cannot alias if
@@ -767,7 +770,6 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
 {
   tree base1, base2;
   HOST_WIDE_INT offset1 = 0, offset2 = 0;
-  HOST_WIDE_INT size1 = -1, size2 = -1;
   HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
   bool var1_p, var2_p, ind1_p, ind2_p;
   alias_set_type set;
@@ -788,11 +790,9 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
   /* Decompose the references into their base objects and the access.  */
   base1 = ao_ref_base (ref1);
   offset1 = ref1->offset;
-  size1 = ref1->size;
   max_size1 = ref1->max_size;
   base2 = ao_ref_base (ref2);
   offset2 = ref2->offset;
-  size2 = ref2->size;
   max_size2 = ref2->max_size;
 
   /* We can end up with registers or constants as bases for example from
@@ -822,6 +822,77 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
     return decl_refs_may_alias_p (base1, offset1, max_size1,
                                  base2, offset2, max_size2);
 
+  ind1_p = INDIRECT_REF_P (base1);
+  ind2_p = INDIRECT_REF_P (base2);
+  /* Canonicalize the pointer-vs-decl case.  */
+  if (ind1_p && var2_p)
+    {
+      HOST_WIDE_INT tmp1;
+      tree tmp2;
+      ao_ref *tmp3;
+      tmp1 = offset1; offset1 = offset2; offset2 = tmp1;
+      tmp1 = max_size1; max_size1 = max_size2; max_size2 = tmp1;
+      tmp2 = base1; base1 = base2; base2 = tmp2;
+      tmp3 = ref1; ref1 = ref2; ref2 = tmp3;
+      var1_p = true;
+      ind1_p = false;
+      var2_p = false;
+      ind2_p = true;
+    }
+
+  /* If we are about to disambiguate pointer-vs-decl try harder to
+     see must-aliases and give leeway to some invalid cases.
+     This covers a pretty minimal set of cases only and does not
+     when called from the RTL oracle.  It handles cases like
+
+       int i = 1;
+       return *(float *)&i;
+
+     and also fixes gfortran.dg/lto/pr40725.  */
+  if (var1_p && ind2_p
+      && cfun
+      && gimple_in_ssa_p (cfun)
+      && TREE_CODE (TREE_OPERAND (base2, 0)) == SSA_NAME)
+    {
+      gimple def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (base2, 0));
+      while (is_gimple_assign (def_stmt)
+            && (gimple_assign_rhs_code (def_stmt) == SSA_NAME
+                || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))))
+       {
+         tree rhs = gimple_assign_rhs1 (def_stmt);
+         HOST_WIDE_INT offset, size, max_size;
+
+         /* Look through SSA name copies and pointer conversions.  */
+         if (TREE_CODE (rhs) == SSA_NAME
+             && POINTER_TYPE_P (TREE_TYPE (rhs)))
+           {
+             def_stmt = SSA_NAME_DEF_STMT (rhs);
+             continue;
+           }
+         if (TREE_CODE (rhs) != ADDR_EXPR)
+           break;
+
+         /* If the pointer is defined as an address based on a decl
+            use plain offset disambiguation and ignore TBAA.  */
+         rhs = TREE_OPERAND (rhs, 0);
+         rhs = get_ref_base_and_extent (rhs, &offset, &size, &max_size);
+         if (SSA_VAR_P (rhs))
+           {
+             base2 = rhs;
+             offset2 += offset;
+             if (size != max_size
+                 || max_size == -1)
+               max_size2 = -1;
+             return decl_refs_may_alias_p (base1, offset1, max_size1,
+                                           base2, offset2, max_size2);
+           }
+
+         /* Do not continue looking through &p->x to limit time
+            complexity.  */
+         break;
+       }
+    }
+
   /* First defer to TBAA if possible.  */
   if (tbaa_p
       && flag_strict_aliasing
@@ -837,19 +908,12 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
     return true;
 
   /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
-  ind1_p = INDIRECT_REF_P (base1);
-  ind2_p = INDIRECT_REF_P (base2);
   set = tbaa_p ? -1 : 0;
   if (var1_p && ind2_p)
     return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
                                          offset2, max_size2, set,
                                          ref1->ref, base1,
                                          offset1, max_size1, set);
-  else if (ind1_p && var2_p)
-    return indirect_ref_may_alias_decl_p (ref1->ref, TREE_OPERAND (base1, 0),
-                                         offset1, max_size1, set,
-                                         ref2->ref, base2,
-                                         offset2, max_size2, set);
   else if (ind1_p && ind2_p)
     return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
                                      offset1, max_size1, set,
@@ -966,6 +1030,8 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
          }
        /* The following builtins do not read from memory.  */
        case BUILT_IN_FREE:
+       case BUILT_IN_MALLOC:
+       case BUILT_IN_CALLOC:
        case BUILT_IN_MEMSET:
        case BUILT_IN_FREXP:
        case BUILT_IN_FREXPF:
@@ -994,8 +1060,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
   /* Check if base is a global static variable that is not read
      by the function.  */
   if (TREE_CODE (base) == VAR_DECL
-      && TREE_STATIC (base)
-      && !TREE_PUBLIC (base))
+      && TREE_STATIC (base))
     {
       bitmap not_read;
 
@@ -1006,57 +1071,34 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
        goto process_args;
     }
 
-  /* If the base variable is call-used or call-clobbered then
-     it may be used.  */
-  if (flags & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
+  /* Check if the base variable is call-used.  */
+  if (DECL_P (base))
     {
-      if (DECL_P (base))
-       {
-         if (is_call_used (base))
-           return true;
-       }
-      else if (INDIRECT_REF_P (base)
-              && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
-       {
-         struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
-         if (!pi)
-           return true;
-
-         if (pt_solution_includes_global (&pi->pt)
-             || pt_solutions_intersect (&cfun->gimple_df->callused, &pi->pt)
-             || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt))
-           return true;
-       }
-      else
+      if (pt_solution_includes (gimple_call_use_set (call), base))
        return true;
     }
-  else
+  else if (INDIRECT_REF_P (base)
+          && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
     {
-      if (DECL_P (base))
-       {
-         if (is_call_clobbered (base))
-           return true;
-       }
-      else if (INDIRECT_REF_P (base)
-              && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
-       {
-         struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
-         if (!pi)
-           return true;
+      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
+      if (!pi)
+       return true;
 
-         if (pt_solution_includes_global (&pi->pt)
-             || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt))
-           return true;
-       }
-      else
+      if (pt_solutions_intersect (gimple_call_use_set (call), &pi->pt))
        return true;
     }
+  else
+    return true;
 
   /* Inspect call arguments for passed-by-value aliases.  */
 process_args:
   for (i = 0; i < gimple_call_num_args (call); ++i)
     {
       tree op = gimple_call_arg (call, i);
+      int flags = gimple_call_arg_flags (call, i);
+
+      if (flags & EAF_UNUSED)
+       continue;
 
       if (TREE_CODE (op) == WITH_SIZE_EXPR)
        op = TREE_OPERAND (op, 0);
@@ -1190,6 +1232,28 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
                                           size);
            return refs_may_alias_p_1 (&dref, ref, false);
          }
+       /* Allocating memory does not have any side-effects apart from
+          being the definition point for the pointer.  */
+       case BUILT_IN_MALLOC:
+       case BUILT_IN_CALLOC:
+         /* Unix98 specifies that errno is set on allocation failure.
+            Until we properly can track the errno location assume it
+            is not a local decl but external or anonymous storage in
+            a different translation unit.  Also assume it is of
+            type int as required by the standard.  */
+         if (flag_errno_math
+             && TREE_TYPE (base) == integer_type_node)
+           {
+             struct ptr_info_def *pi;
+             if (DECL_P (base)
+                 && !TREE_STATIC (base))
+               return true;
+             else if (INDIRECT_REF_P (base)
+                      && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
+                      && (pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0))))
+               return pi->pt.anything || pi->pt.nonlocal;
+           }
+         return false;
        /* Freeing memory kills the pointed-to memory.  More importantly
           the call has to serve as a barrier for moving loads and stores
           across it.  */
@@ -1250,8 +1314,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
      by the function.  */
   if (callee != NULL_TREE
       && TREE_CODE (base) == VAR_DECL
-      && TREE_STATIC (base)
-      && !TREE_PUBLIC (base))
+      && TREE_STATIC (base))
     {
       bitmap not_written;
 
@@ -1261,8 +1324,9 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
        return false;
     }
 
+  /* Check if the base variable is call-clobbered.  */
   if (DECL_P (base))
-    return is_call_clobbered (base);
+    return pt_solution_includes (gimple_call_clobber_set (call), base);
   else if (INDIRECT_REF_P (base)
           && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
     {
@@ -1270,14 +1334,16 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
       if (!pi)
        return true;
 
-      return (pt_solution_includes_global (&pi->pt)
-             || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt));
+      return pt_solutions_intersect (gimple_call_clobber_set (call), &pi->pt);
     }
 
   return true;
 }
 
-static bool ATTRIBUTE_UNUSED
+/* If the call in statement CALL may clobber the memory reference REF
+   return true, otherwise return false.  */
+
+bool
 call_may_clobber_ref_p (gimple call, tree ref)
 {
   bool res;