OSDN Git Service

Removed, no longer used.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-operands.c
index a647786..0af1995 100644 (file)
@@ -15,8 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -26,14 +26,14 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "function.h"
 #include "diagnostic.h"
-#include "errors.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
 #include "tree-pass.h"
 #include "ggc.h"
 #include "timevar.h"
-
+#include "toplev.h"
 #include "langhooks.h"
+#include "ipa-reference.h"
 
 /* This file contains the code required to manage the operands cache of the 
    SSA optimizer.  For every stmt, we maintain an operand cache in the stmt 
@@ -148,16 +148,16 @@ static bool ops_active = false;
 static GTY (()) struct ssa_operand_memory_d *operand_memory = NULL;
 static unsigned operand_memory_index;
 
-static void note_addressable (tree, stmt_ann_t);
 static void get_expr_operands (tree, tree *, int);
 static void get_asm_expr_operands (tree);
 static void get_indirect_ref_operands (tree, tree, int);
+static void get_tmr_operands (tree, tree, int);
 static void get_call_expr_operands (tree, tree);
 static inline void append_def (tree *);
 static inline void append_use (tree *);
 static void append_v_may_def (tree);
 static void append_v_must_def (tree);
-static void add_call_clobber_ops (tree);
+static void add_call_clobber_ops (tree, tree);
 static void add_call_read_ops (tree);
 static void add_stmt_operand (tree *, stmt_ann_t, int);
 static void build_ssa_operands (tree stmt);
@@ -459,10 +459,10 @@ ssa_operand_alloc (unsigned size)
 }
 
 
-/* Make sure PTR is inn the correct immediate use list.  Since uses are simply
+/* Make sure PTR is in the correct immediate use list.  Since uses are simply
    pointers into the stmt TREE, there is no way of telling if anyone has
    changed what this pointer points to via TREE_OPERANDS (exp, 0) = <...>.
-   THe contents are different, but the the pointer is still the same.  This
+   The contents are different, but the pointer is still the same.  This
    routine will check to make sure PTR is in the correct list, and if it isn't
    put it in the correct list.  We cannot simply check the previous node 
    because all nodes in the same stmt might have be changed.  */
@@ -482,7 +482,7 @@ correct_use_link (use_operand_p ptr, tree stmt)
     {
       bool stmt_mod = true;
       /* Find the first element which isn't a SAFE iterator, is in a different
-        stmt, and is not a a modified stmt,  That node is in the correct list,
+        stmt, and is not a modified stmt.  That node is in the correct list,
         see if we are too.  */
 
       while (stmt_mod)
@@ -897,7 +897,8 @@ parse_ssa_operands (tree stmt)
        if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
          lhs = TREE_OPERAND (lhs, 0);
 
-       if (TREE_CODE (lhs) != ARRAY_REF && TREE_CODE (lhs) != ARRAY_RANGE_REF
+       if (TREE_CODE (lhs) != ARRAY_REF
+           && TREE_CODE (lhs) != ARRAY_RANGE_REF
            && TREE_CODE (lhs) != BIT_FIELD_REF
            && TREE_CODE (lhs) != REALPART_EXPR
            && TREE_CODE (lhs) != IMAGPART_EXPR)
@@ -997,8 +998,7 @@ build_ssa_operands (tree stmt)
 
 
 /* Free any operands vectors in OPS.  */
-#if 0
-static void 
+void 
 free_ssa_operands (stmt_operands_p ops)
 {
   ops->def_ops = NULL;
@@ -1006,14 +1006,7 @@ free_ssa_operands (stmt_operands_p ops)
   ops->maydef_ops = NULL;
   ops->mustdef_ops = NULL;
   ops->vuse_ops = NULL;
-  while (ops->memory.next != NULL)
-    {
-      operand_memory_p tmp = ops->memory.next;
-      ops->memory.next = tmp->next;
-      ggc_free (tmp);
-    }
 }
-#endif
 
 
 /* Get the operands of statement STMT.  Note that repeated calls to
@@ -1214,9 +1207,9 @@ swap_tree_operands (tree stmt, tree *exp0, tree *exp1)
 }
 
 
-/* Recursively scan the expression pointed by EXPR_P in statement referred to
-   by INFO.  FLAGS is one of the OPF_* constants modifying how to interpret the
-   operands found.  */
+/* Recursively scan the expression pointed to by EXPR_P in statement referred
+   to by INFO.  FLAGS is one of the OPF_* constants modifying how to interpret
+   the operands found.  */
 
 static void
 get_expr_operands (tree stmt, tree *expr_p, int flags)
@@ -1289,6 +1282,10 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       get_indirect_ref_operands (stmt, expr, flags);
       return;
 
+    case TARGET_MEM_REF:
+      get_tmr_operands (stmt, expr, flags);
+      return;
+
     case ARRAY_REF:
     case ARRAY_RANGE_REF:
       /* Treat array references as references to the virtual variable
@@ -1313,7 +1310,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
     case IMAGPART_EXPR:
       {
        tree ref;
-       HOST_WIDE_INT offset, size;
+       unsigned HOST_WIDE_INT offset, size;
        /* This component ref becomes an access to all of the subvariables
           it can touch,  if we can determine that, but *NOT* the real one.
           If we can't determine which fields we could touch, the recursion
@@ -1330,9 +1327,10 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
                bool exact;             
                if (overlap_subvar (offset, size, sv, &exact))
                  {
+                   int subvar_flags = flags;
                    if (!exact)
-                     flags &= ~opf_kill_def;
-                   add_stmt_operand (&sv->var, s_ann, flags);
+                     subvar_flags &= ~opf_kill_def;
+                   add_stmt_operand (&sv->var, s_ann, subvar_flags);
                  }
              }
          }
@@ -1341,7 +1339,11 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
                             flags & ~opf_kill_def);
        
        if (code == COMPONENT_REF)
-         get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+         {
+           if (s_ann && TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1)))
+             s_ann->has_volatile_ops = true; 
+           get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+         }
        return;
       }
     case WITH_SIZE_EXPR:
@@ -1388,10 +1390,13 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       {
        /* General aggregate CONSTRUCTORs have been decomposed, but they
           are still in use as the COMPLEX_EXPR equivalent for vectors.  */
+       constructor_elt *ce;
+       unsigned HOST_WIDE_INT idx;
 
-       tree t;
-       for (t = TREE_OPERAND (expr, 0); t ; t = TREE_CHAIN (t))
-         get_expr_operands (stmt, &TREE_VALUE (t), opf_none);
+       for (idx = 0;
+            VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce);
+            idx++)
+         get_expr_operands (stmt, &ce->value, opf_none);
 
        return;
       }
@@ -1514,8 +1519,8 @@ get_asm_expr_operands (tree stmt)
       if (!allows_reg && allows_mem)
        {
          tree t = get_base_address (TREE_VALUE (link));
-         if (t && DECL_P (t))
-           note_addressable (t, s_ann);
+         if (t && DECL_P (t) && s_ann)
+           add_to_addressable_set (t, &s_ann->addresses_taken);
        }
 
       get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
@@ -1533,8 +1538,8 @@ get_asm_expr_operands (tree stmt)
       if (!allows_reg && allows_mem)
        {
          tree t = get_base_address (TREE_VALUE (link));
-         if (t && DECL_P (t))
-           note_addressable (t, s_ann);
+         if (t && DECL_P (t) && s_ann)
+           add_to_addressable_set (t, &s_ann->addresses_taken);
        }
 
       get_expr_operands (stmt, &TREE_VALUE (link), 0);
@@ -1554,10 +1559,10 @@ get_asm_expr_operands (tree stmt)
          add_stmt_operand (&global_var, s_ann, opf_is_def);
        else
          EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
-             {
-               tree var = referenced_var (i);
-               add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
-             }
+           {
+             tree var = referenced_var (i);
+             add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
+           }
 
        /* Now clobber all addressables.  */
        EXECUTE_IF_SET_IN_BITMAP (addressable_vars, 0, i, bi)
@@ -1672,6 +1677,33 @@ get_indirect_ref_operands (tree stmt, tree expr, int flags)
   get_expr_operands (stmt, pptr, opf_none);
 }
 
+/* A subroutine of get_expr_operands to handle TARGET_MEM_REF.  */
+
+static void
+get_tmr_operands (tree stmt, tree expr, int flags)
+{
+  tree tag = TMR_TAG (expr);
+
+  /* First record the real operands.  */
+  get_expr_operands (stmt, &TMR_BASE (expr), opf_none);
+  get_expr_operands (stmt, &TMR_INDEX (expr), opf_none);
+
+  /* MEM_REFs should never be killing.  */
+  flags &= ~opf_kill_def;
+
+  if (TMR_SYMBOL (expr))
+    {
+      stmt_ann_t ann = stmt_ann (stmt);
+      add_to_addressable_set (TMR_SYMBOL (expr), &ann->addresses_taken);
+    }
+
+  if (tag)
+    get_expr_operands (stmt, &tag, flags);
+  else
+    /* Something weird, so ensure that we will be careful.  */
+    stmt_ann (stmt)->has_volatile_ops = true;
+}
+
 /* A subroutine of get_expr_operands to handle CALL_EXPR.  */
 
 static void
@@ -1699,7 +1731,7 @@ get_call_expr_operands (tree stmt, tree expr)
         there is no point in recording that.  */ 
       if (TREE_SIDE_EFFECTS (expr)
          && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
-       add_call_clobber_ops (stmt);
+       add_call_clobber_ops (stmt, get_callee_fndecl (expr));
       else if (!(call_flags & ECF_CONST))
        add_call_read_ops (stmt);
     }
@@ -1732,9 +1764,9 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 
   /* If the operand is an ADDR_EXPR, add its operand to the list of
      variables that have had their address taken in this statement.  */
-  if (TREE_CODE (var) == ADDR_EXPR)
+  if (TREE_CODE (var) == ADDR_EXPR && s_ann)
     {
-      note_addressable (TREE_OPERAND (var, 0), s_ann);
+      add_to_addressable_set (TREE_OPERAND (var, 0), &s_ann->addresses_taken);
       return;
     }
 
@@ -1759,7 +1791,7 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 
   /* If the variable cannot be modified and this is a V_MAY_DEF change
      it into a VUSE.  This happens when read-only variables are marked
-     call-clobbered and/or aliased to writeable variables.  So we only
+     call-clobbered and/or aliased to writable variables.  So we only
      check that this only happens on non-specific stores.
 
      Note that if this is a specific store, i.e. associated with a
@@ -1836,35 +1868,17 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 
          if (flags & opf_is_def)
            {
-             bool added_may_defs_p = false;
-
              /* If the variable is also an alias tag, add a virtual
                 operand for it, otherwise we will miss representing
                 references to the members of the variable's alias set.
                 This fixes the bug in gcc.c-torture/execute/20020503-1.c.  */
              if (v_ann->is_alias_tag)
-               {
-                 added_may_defs_p = true;
-                 append_v_may_def (var);
-               }
+               append_v_may_def (var);
 
              for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
-               {
-                 /* While VAR may be modifiable, some of its aliases
-                    may not be.  If that's the case, we don't really
-                    need to add them a V_MAY_DEF for them.  */
-                 tree alias = VARRAY_TREE (aliases, i);
-
-                 if (unmodifiable_var_p (alias))
-                   append_vuse (alias);
-                 else
-                   {
-                     append_v_may_def (alias);
-                     added_may_defs_p = true;
-                   }
-               }
+               append_v_may_def (VARRAY_TREE (aliases, i));
 
-             if (s_ann && added_may_defs_p)
+             if (s_ann)
                s_ann->makes_aliased_stores = 1;
            }
          else
@@ -1885,45 +1899,56 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
 }
 
   
-/* Record that VAR had its address taken in the statement with annotations
-   S_ANN.  */
+/* Add the base address of REF to the set *ADDRESSES_TAKEN.  If
+   *ADDRESSES_TAKEN is NULL, a new set is created.  REF may be
+   a single variable whose address has been taken or any other valid
+   GIMPLE memory reference (structure reference, array, etc).  If the
+   base address of REF is a decl that has sub-variables, also add all
+   of its sub-variables.  */
 
-static void
-note_addressable (tree var, stmt_ann_t s_ann)
+void
+add_to_addressable_set (tree ref, bitmap *addresses_taken)
 {
+  tree var;
   subvar_t svars;
 
-  if (!s_ann)
-    return;
-  
+  gcc_assert (addresses_taken);
+
   /* Note that it is *NOT OKAY* to use the target of a COMPONENT_REF
-     as the only thing we take the address of.
-     See PR 21407 and the ensuing mailing list discussion.  */
-  
-  var = get_base_address (var);
+     as the only thing we take the address of.  If VAR is a structure,
+     taking the address of a field means that the whole structure may
+     be referenced using pointer arithmetic.  See PR 21407 and the
+     ensuing mailing list discussion.  */
+  var = get_base_address (ref);
   if (var && SSA_VAR_P (var))
     {
-      if (s_ann->addresses_taken == NULL)
-       s_ann->addresses_taken = BITMAP_GGC_ALLOC ();      
+      if (*addresses_taken == NULL)
+       *addresses_taken = BITMAP_GGC_ALLOC ();      
       
-
       if (var_can_have_subvars (var)
          && (svars = get_subvars_for_var (var)))
        {
          subvar_t sv;
          for (sv = svars; sv; sv = sv->next)
-           bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
+           {
+             bitmap_set_bit (*addresses_taken, DECL_UID (sv->var));
+             TREE_ADDRESSABLE (sv->var) = 1;
+           }
        }
       else
-       bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
+       {
+         bitmap_set_bit (*addresses_taken, DECL_UID (var));
+         TREE_ADDRESSABLE (var) = 1;
+       }
     }
 }
 
+
 /* Add clobbering definitions for .GLOBAL_VAR or for each of the call
    clobbered variables in the function.  */
 
 static void
-add_call_clobber_ops (tree stmt)
+add_call_clobber_ops (tree stmt, tree callee)
 {
   int i;
   unsigned u;
@@ -1931,6 +1956,7 @@ add_call_clobber_ops (tree stmt)
   bitmap_iterator bi;
   stmt_ann_t s_ann = stmt_ann (stmt);
   struct stmt_ann_d empty_ann;
+  bitmap not_read_b, not_written_b;
 
   /* Functions that are not const, pure or never return may clobber
      call-clobbered variables.  */
@@ -1945,8 +1971,22 @@ add_call_clobber_ops (tree stmt)
       return;
     }
 
+  /* FIXME - if we have better information from the static vars
+     analysis, we need to make the cache call site specific.  This way
+     we can have the performance benefits even if we are doing good
+     optimization.  */
+
+  /* Get info for local and module level statics.  There is a bit
+     set for each static if the call being processed does not read
+     or write that variable.  */
+
+  not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL; 
+  not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL; 
+
   /* If cache is valid, copy the elements into the build vectors.  */
-  if (ssa_call_clobbered_cache_valid)
+  if (ssa_call_clobbered_cache_valid
+      && (!not_read_b || bitmap_empty_p (not_read_b))
+      && (!not_written_b || bitmap_empty_p (not_written_b)))
     {
       /* Process the caches in reverse order so we are always inserting at
          the head of the list.  */
@@ -1981,43 +2021,62 @@ add_call_clobber_ops (tree stmt)
       if (unmodifiable_var_p (var))
        add_stmt_operand (&var, &empty_ann, opf_none);
       else
-       add_stmt_operand (&var, &empty_ann, opf_is_def | opf_non_specific);
+       {
+         bool not_read
+           = not_read_b ? bitmap_bit_p (not_read_b, u) : false;
+         bool not_written
+           = not_written_b ? bitmap_bit_p (not_written_b, u) : false;
+
+         if ((TREE_READONLY (var)
+              && (TREE_STATIC (var) || DECL_EXTERNAL (var)))
+             || not_written)
+           {
+             if (!not_read)
+               add_stmt_operand (&var, &empty_ann, opf_none);
+           }
+         else
+           add_stmt_operand (&var, &empty_ann, opf_is_def);
+       }
     }
 
-  clobbered_aliased_loads = empty_ann.makes_aliased_loads;
-  clobbered_aliased_stores = empty_ann.makes_aliased_stores;
-
-  /* Set the flags for a stmt's annotation.  */
-  if (s_ann)
+  if ((!not_read_b || bitmap_empty_p (not_read_b))
+      && (!not_written_b || bitmap_empty_p (not_written_b)))
     {
-      s_ann->makes_aliased_loads = empty_ann.makes_aliased_loads;
-      s_ann->makes_aliased_stores = empty_ann.makes_aliased_stores;
-    }
+      clobbered_aliased_loads = empty_ann.makes_aliased_loads;
+      clobbered_aliased_stores = empty_ann.makes_aliased_stores;
 
-  /* Prepare empty cache vectors.  */
-  VEC_truncate (tree, clobbered_vuses, 0);
-  VEC_truncate (tree, clobbered_v_may_defs, 0);
+      /* Set the flags for a stmt's annotation.  */
+      if (s_ann)
+       {
+         s_ann->makes_aliased_loads = empty_ann.makes_aliased_loads;
+         s_ann->makes_aliased_stores = empty_ann.makes_aliased_stores;
+       }
 
-  /* Now fill the clobbered cache with the values that have been found.  */
-  for (i = opbuild_first (&build_vuses);
-       i != OPBUILD_LAST;
-       i = opbuild_next (&build_vuses, i))
-    VEC_safe_push (tree, heap, clobbered_vuses,
-                  opbuild_elem_virtual (&build_vuses, i));
+      /* Prepare empty cache vectors.  */
+      VEC_truncate (tree, clobbered_vuses, 0);
+      VEC_truncate (tree, clobbered_v_may_defs, 0);
 
-  gcc_assert (opbuild_num_elems (&build_vuses) 
-             == VEC_length (tree, clobbered_vuses));
+      /* Now fill the clobbered cache with the values that have been found.  */
+      for (i = opbuild_first (&build_vuses);
+          i != OPBUILD_LAST;
+          i = opbuild_next (&build_vuses, i))
+       VEC_safe_push (tree, heap, clobbered_vuses,
+                      opbuild_elem_virtual (&build_vuses, i));
 
-  for (i = opbuild_first (&build_v_may_defs);
-       i != OPBUILD_LAST;
-       i = opbuild_next (&build_v_may_defs, i))
-    VEC_safe_push (tree, heap, clobbered_v_may_defs, 
-                  opbuild_elem_virtual (&build_v_may_defs, i));
+      gcc_assert (opbuild_num_elems (&build_vuses) 
+                 == VEC_length (tree, clobbered_vuses));
 
-  gcc_assert (opbuild_num_elems (&build_v_may_defs) 
-             == VEC_length (tree, clobbered_v_may_defs));
+      for (i = opbuild_first (&build_v_may_defs);
+          i != OPBUILD_LAST;
+          i = opbuild_next (&build_v_may_defs, i))
+       VEC_safe_push (tree, heap, clobbered_v_may_defs, 
+                      opbuild_elem_virtual (&build_v_may_defs, i));
 
-  ssa_call_clobbered_cache_valid = true;
+      gcc_assert (opbuild_num_elems (&build_v_may_defs) 
+                 == VEC_length (tree, clobbered_v_may_defs));
+
+      ssa_call_clobbered_cache_valid = true;
+    }
 }