OSDN Git Service

2009-11-04 Kenneth Zadeck <zadeck@naturalbridge.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-alias.c
index ba5cbbc..4c052be 100644 (file)
@@ -776,12 +776,14 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
               || SSA_VAR_P (ref1->ref)
               || handled_component_p (ref1->ref)
               || INDIRECT_REF_P (ref1->ref)
-              || TREE_CODE (ref1->ref) == TARGET_MEM_REF)
+              || TREE_CODE (ref1->ref) == TARGET_MEM_REF
+              || TREE_CODE (ref1->ref) == CONST_DECL)
              && (!ref2->ref
                  || SSA_VAR_P (ref2->ref)
                  || handled_component_p (ref2->ref)
                  || INDIRECT_REF_P (ref2->ref)
-                 || TREE_CODE (ref2->ref) == TARGET_MEM_REF));
+                 || TREE_CODE (ref2->ref) == TARGET_MEM_REF
+                 || TREE_CODE (ref2->ref) == CONST_DECL));
 
   /* Decompose the references into their base objects and the access.  */
   base1 = ao_ref_base (ref1);
@@ -798,6 +800,8 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
      which is seen as a struct copy.  */
   if (TREE_CODE (base1) == SSA_NAME
       || TREE_CODE (base2) == SSA_NAME
+      || TREE_CODE (base1) == CONST_DECL
+      || TREE_CODE (base2) == CONST_DECL
       || is_gimple_min_invariant (base1)
       || is_gimple_min_invariant (base2))
     return false;
@@ -934,7 +938,6 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
           their first argument.  */
        case BUILT_IN_STRCPY:
        case BUILT_IN_STRNCPY:
-       case BUILT_IN_BCOPY:
        case BUILT_IN_MEMCPY:
        case BUILT_IN_MEMMOVE:
        case BUILT_IN_MEMPCPY:
@@ -952,6 +955,15 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
                                           size);
            return refs_may_alias_p_1 (&dref, ref, false);
          }
+       case BUILT_IN_BCOPY:
+         {
+           ao_ref dref;
+           tree size = gimple_call_arg (call, 2);
+           ao_ref_init_from_ptr_and_size (&dref,
+                                          gimple_call_arg (call, 0),
+                                          size);
+           return refs_may_alias_p_1 (&dref, ref, false);
+         }
        /* The following builtins do not read from memory.  */
        case BUILT_IN_FREE:
        case BUILT_IN_MEMSET:
@@ -1151,7 +1163,6 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
           their first argument.  */
        case BUILT_IN_STRCPY:
        case BUILT_IN_STRNCPY:
-       case BUILT_IN_BCOPY:
        case BUILT_IN_MEMCPY:
        case BUILT_IN_MEMMOVE:
        case BUILT_IN_MEMPCPY:
@@ -1170,6 +1181,15 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
                                           size);
            return refs_may_alias_p_1 (&dref, ref, false);
          }
+       case BUILT_IN_BCOPY:
+         {
+           ao_ref dref;
+           tree size = gimple_call_arg (call, 2);
+           ao_ref_init_from_ptr_and_size (&dref,
+                                          gimple_call_arg (call, 1),
+                                          size);
+           return refs_may_alias_p_1 (&dref, ref, 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.  */
@@ -1313,8 +1333,6 @@ stmt_may_clobber_ref_p (gimple stmt, tree ref)
 }
 
 
-static tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
-
 /* Walk the virtual use-def chain of VUSE until hitting the virtual operand
    TARGET or a statement clobbering the memory reference REF in which
    case false is returned.  The walk starts with VUSE, one argument of PHI.  */
@@ -1358,7 +1376,7 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
    clobber REF.  Returns NULL_TREE if no suitable virtual operand can
    be found.  */
 
-static tree
+tree
 get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
 {
   unsigned nargs = gimple_phi_num_args (phi);
@@ -1375,6 +1393,7 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
       tree arg1 = PHI_ARG_DEF (phi, 1);
       gimple def0 = SSA_NAME_DEF_STMT (arg0);
       gimple def1 = SSA_NAME_DEF_STMT (arg1);
+      tree common_vuse;
 
       if (arg0 == arg1)
        return arg0;
@@ -1393,6 +1412,26 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
          if (maybe_skip_until (phi, arg1, ref, arg0, visited))
            return arg1;
        }
+      /* Special case of a diamond:
+          MEM_1 = ...
+          goto (cond) ? L1 : L2
+          L1: store1 = ...    #MEM_2 = vuse(MEM_1)
+              goto L3
+          L2: store2 = ...    #MEM_3 = vuse(MEM_1)
+          L3: MEM_4 = PHI<MEM_2, MEM_3>
+        We were called with the PHI at L3, MEM_2 and MEM_3 don't
+        dominate each other, but still we can easily skip this PHI node
+        if we recognize that the vuse MEM operand is the same for both,
+        and that we can skip both statements (they don't clobber us).
+        This is still linear.  Don't use maybe_skip_until, that might
+        potentially be slow.  */
+      else if ((common_vuse = gimple_vuse (def0))
+              && common_vuse == gimple_vuse (def1))
+       {
+         if (!stmt_may_clobber_ref_p_1 (def0, ref)
+             && !stmt_may_clobber_ref_p_1 (def1, ref))
+           return common_vuse;
+       }
     }
 
   return NULL_TREE;