OSDN Git Service

Add BMI2 support.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-alias.c
index 315a252..bac1181 100644 (file)
@@ -1,5 +1,5 @@
 /* Alias analysis for trees.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -718,8 +718,9 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
                               alias_set_type base2_alias_set, bool tbaa_p)
 {
   tree ptr1;
-  tree ptrtype1;
+  tree ptrtype1, dbase2;
   HOST_WIDE_INT offset1p = offset1, offset2p = offset2;
+  HOST_WIDE_INT doffset1, doffset2;
   double_int moff;
 
   gcc_checking_assert ((TREE_CODE (base1) == MEM_REF
@@ -744,11 +745,12 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
      the pointer access is beyond the extent of the variable access.
      (the pointer base cannot validly point to an offset less than zero
      of the variable).
-     They also cannot alias if the pointer may not point to the decl.  */
-  if ((TREE_CODE (base1) != TARGET_MEM_REF
-       || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
+     ???  IVOPTs creates bases that do not honor this restriction,
+     so do not apply this optimization for TARGET_MEM_REFs.  */
+  if (TREE_CODE (base1) != TARGET_MEM_REF
       && !ranges_overlap_p (MAX (0, offset1p), -1, offset2p, max_size2))
     return false;
+  /* They also cannot alias if the pointer may not point to the decl.  */
   if (!ptr_deref_may_alias_decl_p (ptr1, base2))
     return false;
 
@@ -766,20 +768,6 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
   if (base2_alias_set == -1)
     base2_alias_set = get_alias_set (base2);
 
-  /* If both references are through the same type, they do not alias
-     if the accesses do not overlap.  This does extra disambiguation
-     for mixed/pointer accesses but requires strict aliasing.
-     For MEM_REFs we require that the component-ref offset we computed
-     is relative to the start of the type which we ensure by
-     comparing rvalue and access type and disregarding the constant
-     pointer offset.  */
-  if ((TREE_CODE (base1) != TARGET_MEM_REF
-       || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
-      && (TREE_CODE (base1) != MEM_REF
-         || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1)
-      && same_type_for_tbaa (TREE_TYPE (ptrtype1), TREE_TYPE (base2)) == 1)
-    return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
-
   /* When we are trying to disambiguate an access with a pointer dereference
      as base versus one with a decl as base we can use both the size
      of the decl and its dynamic type for extra disambiguation.
@@ -809,13 +797,51 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
       && tree_int_cst_lt (DECL_SIZE (base2), TYPE_SIZE (TREE_TYPE (ptrtype1))))
     return false;
 
+  if (!ref2)
+    return true;
+
+  /* If the decl is accessed via a MEM_REF, reconstruct the base
+     we can use for TBAA and an appropriately adjusted offset.  */
+  dbase2 = ref2;
+  while (handled_component_p (dbase2))
+    dbase2 = TREE_OPERAND (dbase2, 0);
+  doffset1 = offset1;
+  doffset2 = offset2;
+  if (TREE_CODE (dbase2) == MEM_REF
+      || TREE_CODE (dbase2) == TARGET_MEM_REF)
+    {
+      double_int moff = mem_ref_offset (dbase2);
+      moff = double_int_lshift (moff,
+                               BITS_PER_UNIT == 8
+                               ? 3 : exact_log2 (BITS_PER_UNIT),
+                               HOST_BITS_PER_DOUBLE_INT, true);
+      if (double_int_negative_p (moff))
+       doffset1 -= double_int_neg (moff).low;
+      else
+       doffset2 -= moff.low;
+    }
+
+  /* If either reference is view-converted, give up now.  */
+  if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
+      || same_type_for_tbaa (TREE_TYPE (dbase2),
+                            TREE_TYPE (reference_alias_ptr_type (dbase2))) != 1)
+    return true;
+
+  /* If both references are through the same type, they do not alias
+     if the accesses do not overlap.  This does extra disambiguation
+     for mixed/pointer accesses but requires strict aliasing.
+     For MEM_REFs we require that the component-ref offset we computed
+     is relative to the start of the type which we ensure by
+     comparing rvalue and access type and disregarding the constant
+     pointer offset.  */
+  if ((TREE_CODE (base1) != TARGET_MEM_REF
+       || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
+      && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1)
+    return ranges_overlap_p (doffset1, max_size1, doffset2, max_size2);
+
   /* Do access-path based disambiguation.  */
   if (ref1 && ref2
-      && handled_component_p (ref1)
-      && handled_component_p (ref2)
-      && TREE_CODE (base1) != TARGET_MEM_REF
-      && (TREE_CODE (base1) != MEM_REF
-         || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1))
+      && (handled_component_p (ref1) || handled_component_p (ref2)))
     return aliasing_component_refs_p (ref1,
                                      ref1_alias_set, base1_alias_set,
                                      offset1, max_size1,
@@ -1173,6 +1199,24 @@ 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_STRCPY_CHK:
+       case BUILT_IN_STRNCPY_CHK:
+       case BUILT_IN_MEMCPY_CHK:
+       case BUILT_IN_MEMMOVE_CHK:
+       case BUILT_IN_MEMPCPY_CHK:
+       case BUILT_IN_STPCPY_CHK:
+       case BUILT_IN_STRCAT_CHK:
+       case BUILT_IN_STRNCAT_CHK:
+         {
+           ao_ref dref;
+           tree size = NULL_TREE;
+           if (gimple_call_num_args (call) == 4)
+             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);
+         }
        case BUILT_IN_BCOPY:
          {
            ao_ref dref;
@@ -1190,6 +1234,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_STACK_RESTORE:
        case BUILT_IN_MEMSET:
+       case BUILT_IN_MEMSET_CHK:
        case BUILT_IN_FREXP:
        case BUILT_IN_FREXPF:
        case BUILT_IN_FREXPL:
@@ -1208,6 +1253,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
        case BUILT_IN_SINCOS:
        case BUILT_IN_SINCOSF:
        case BUILT_IN_SINCOSL:
+       case BUILT_IN_ASSUME_ALIGNED:
          return false;
        /* __sync_* builtins and some OpenMP builtins act as threading
           barriers.  */
@@ -1427,6 +1473,25 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
                                           size);
            return refs_may_alias_p_1 (&dref, ref, false);
          }
+       case BUILT_IN_STRCPY_CHK:
+       case BUILT_IN_STRNCPY_CHK:
+       case BUILT_IN_MEMCPY_CHK:
+       case BUILT_IN_MEMMOVE_CHK:
+       case BUILT_IN_MEMPCPY_CHK:
+       case BUILT_IN_STPCPY_CHK:
+       case BUILT_IN_STRCAT_CHK:
+       case BUILT_IN_STRNCAT_CHK:
+       case BUILT_IN_MEMSET_CHK:
+         {
+           ao_ref dref;
+           tree size = NULL_TREE;
+           if (gimple_call_num_args (call) == 4)
+             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);
+         }
        case BUILT_IN_BCOPY:
          {
            ao_ref dref;
@@ -1447,6 +1512,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
          return false;
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_ALLOCA:
+       case BUILT_IN_ASSUME_ALIGNED:
          return false;
        /* Freeing memory kills the pointed-to memory.  More importantly
           the call has to serve as a barrier for moving loads and stores
@@ -1633,7 +1699,14 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
     return false;
 
   if (gimple_has_lhs (stmt)
-      && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME)
+      && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME
+      /* The assignment is not necessarily carried out if it can throw
+        and we can catch it in the current function where we could inspect
+        the previous value.
+        ???  We only need to care about the RHS throwing.  For aggregate
+        assignments or similar calls and non-call exceptions the LHS
+        might throw as well.  */
+      && !stmt_can_throw_internal (stmt))
     {
       tree base, lhs = gimple_get_lhs (stmt);
       HOST_WIDE_INT size, offset, max_size;
@@ -1664,6 +1737,10 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
          case BUILT_IN_MEMPCPY:
          case BUILT_IN_MEMMOVE:
          case BUILT_IN_MEMSET:
+         case BUILT_IN_MEMCPY_CHK:
+         case BUILT_IN_MEMPCPY_CHK:
+         case BUILT_IN_MEMMOVE_CHK:
+         case BUILT_IN_MEMSET_CHK:
            {
              tree dest = gimple_call_arg (stmt, 0);
              tree len = gimple_call_arg (stmt, 2);