OSDN Git Service

- fix whitespace in laste gcc/ChangeLog entry
[pf3gnuchains/gcc-fork.git] / gcc / tree-dfa.c
index 37e15bf..2dacd44 100644 (file)
@@ -23,7 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "toplev.h"
 #include "hashtab.h"
 #include "pointer-set.h"
 #include "tree.h"
@@ -219,7 +218,7 @@ dump_referenced_vars (FILE *file)
   fprintf (file, "\nReferenced variables in %s: %u\n\n",
           get_name (current_function_decl), (unsigned) num_referenced_vars);
 
-  FOR_EACH_REFERENCED_VAR (var, rvi)
+  FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
     {
       fprintf (file, "Variable: ");
       dump_variable (file, var);
@@ -401,7 +400,7 @@ collect_dfa_stats (struct dfa_stats_d *dfa_stats_p ATTRIBUTE_UNUSED)
   memset ((void *)dfa_stats_p, 0, sizeof (struct dfa_stats_d));
 
   /* Count all the variable annotations.  */
-  FOR_EACH_REFERENCED_VAR (var, vi)
+  FOR_EACH_REFERENCED_VAR (cfun, var, vi)
     if (var_ann (var))
       dfa_stats_p->num_var_anns++;
 
@@ -489,13 +488,12 @@ find_referenced_vars_in (gimple stmt)
    variable.  */
 
 tree
-referenced_var_lookup (unsigned int uid)
+referenced_var_lookup (struct function *fn, unsigned int uid)
 {
   tree h;
   struct tree_decl_minimal in;
   in.uid = uid;
-  h = (tree) htab_find_with_hash (gimple_referenced_vars (cfun), &in, uid);
-  gcc_assert (h || uid == 0);
+  h = (tree) htab_find_with_hash (gimple_referenced_vars (fn), &in, uid);
   return h;
 }
 
@@ -711,6 +709,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
   tree size_tree = NULL_TREE;
   HOST_WIDE_INT bit_offset = 0;
   bool seen_variable_array_ref = false;
+  tree base_type;
 
   /* First get the final access size from just the outermost expression.  */
   if (TREE_CODE (exp) == COMPONENT_REF)
@@ -741,6 +740,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
      and find the ultimate containing object.  */
   while (1)
     {
+      base_type = TREE_TYPE (exp);
+
       switch (TREE_CODE (exp))
        {
        case BIT_FIELD_REF:
@@ -879,6 +880,38 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
            }
          goto done;
 
+       case TARGET_MEM_REF:
+         /* Hand back the decl for MEM[&decl, off].  */
+         if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
+           {
+             /* Via the variable index or index2 we can reach the
+                whole object.  */
+             if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+               {
+                 exp = TREE_OPERAND (TMR_BASE (exp), 0);
+                 bit_offset = 0;
+                 maxsize = -1;
+                 goto done;
+               }
+             if (integer_zerop (TMR_OFFSET (exp)))
+               exp = TREE_OPERAND (TMR_BASE (exp), 0);
+             else
+               {
+                 double_int off = mem_ref_offset (exp);
+                 off = double_int_lshift (off,
+                                          BITS_PER_UNIT == 8
+                                          ? 3 : exact_log2 (BITS_PER_UNIT),
+                                          HOST_BITS_PER_DOUBLE_INT, true);
+                 off = double_int_add (off, shwi_to_double_int (bit_offset));
+                 if (double_int_fits_in_shwi_p (off))
+                   {
+                     bit_offset = double_int_to_shwi (off);
+                     exp = TREE_OPERAND (TMR_BASE (exp), 0);
+                   }
+               }
+           }
+         goto done;
+
        default:
          goto done;
        }
@@ -896,9 +929,16 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
      the array.  The simplest way to conservatively deal with this
      is to punt in the case that offset + maxsize reaches the
      base type boundary.  This needs to include possible trailing padding
-     that is there for alignment purposes.
+     that is there for alignment purposes.  */
+
+  if (seen_variable_array_ref
+      && maxsize != -1
+      && (!host_integerp (TYPE_SIZE (base_type), 1)
+         || (bit_offset + maxsize
+             == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
+    maxsize = -1;
 
-     That is of course only true if the base object is not a decl.  */
+  /* In case of a decl or constant base object we can do better.  */
 
   if (DECL_P (exp))
     {
@@ -908,12 +948,14 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
          && host_integerp (DECL_SIZE (exp), 1))
        maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset;
     }
-  else if (seen_variable_array_ref
-          && maxsize != -1
-          && (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
-              || (bit_offset + maxsize
-                  == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
-    maxsize = -1;
+  else if (CONSTANT_CLASS_P (exp))
+    {
+      /* If maxsize is unknown adjust it according to the size of the
+         base type constant.  */
+      if (maxsize == -1
+         && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1))
+       maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - bit_offset;
+    }
 
   /* ???  Due to negative offsets in ARRAY_REF we can end up with
      negative bit_offset here.  We might want to store a zero offset
@@ -1011,6 +1053,22 @@ get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset)
            }
          goto done;
 
+       case TARGET_MEM_REF:
+         /* Hand back the decl for MEM[&decl, off].  */
+         if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
+           {
+             if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+               return NULL_TREE;
+             if (!integer_zerop (TMR_OFFSET (exp)))
+               {
+                 double_int off = mem_ref_offset (exp);
+                 gcc_assert (off.high == -1 || off.high == 0);
+                 byte_offset += double_int_to_shwi (off);
+               }
+             exp = TREE_OPERAND (TMR_BASE (exp), 0);
+           }
+         goto done;
+
        default:
          goto done;
        }