OSDN Git Service

2007-07-02 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / ipa-reference.c
index ec8d3b8..62b1c1d 100644 (file)
@@ -286,7 +286,7 @@ check_operand (ipa_reference_local_vars_info_t local,
 {
   if (!t) return;
 
-  if ((TREE_CODE (t) == VAR_DECL)
+  if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
       && (has_proper_scope_for_analysis (t))) 
     {
       if (checking_write)
@@ -343,7 +343,7 @@ look_for_address_of (tree t)
   if (TREE_CODE (t) == ADDR_EXPR)
     {
       tree x = get_base_var (t);
-      if (TREE_CODE (x) == VAR_DECL) 
+      if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL
        if (has_proper_scope_for_analysis (x))
          bitmap_set_bit (module_statics_escape, DECL_UID (x));
     }
@@ -436,18 +436,13 @@ static void
 check_call (ipa_reference_local_vars_info_t local, tree call_expr) 
 {
   int flags = call_expr_flags (call_expr);
-  tree operand_list = TREE_OPERAND (call_expr, 1);
   tree operand;
   tree callee_t = get_callee_fndecl (call_expr);
   enum availability avail = AVAIL_NOT_AVAILABLE;
+  call_expr_arg_iterator iter;
 
-  for (operand = operand_list;
-       operand != NULL_TREE;
-       operand = TREE_CHAIN (operand))
-    {
-      tree argument = TREE_VALUE (operand);
-      check_rhs_var (local, argument);
-    }
+  FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
+    check_rhs_var (local, operand);
 
   if (callee_t)
     {
@@ -480,7 +475,7 @@ scan_for_static_refs (tree *tp,
                      int *walk_subtrees, 
                      void *data)
 {
-  struct cgraph_node *fn = data;
+  struct cgraph_node *fn = (struct cgraph_node *) data;
   tree t = *tp;
   ipa_reference_local_vars_info_t local = NULL;
   if (fn)
@@ -494,11 +489,11 @@ scan_for_static_refs (tree *tp,
       *walk_subtrees = 0;
       break;
 
-    case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
       {
        /* First look on the lhs and see what variable is stored to */
-       tree lhs = TREE_OPERAND (t, 0);
-       tree rhs = TREE_OPERAND (t, 1);
+       tree lhs = GIMPLE_STMT_OPERAND (t, 0);
+       tree rhs = GIMPLE_STMT_OPERAND (t, 1);
        check_lhs_var (local, lhs);
 
        /* For the purposes of figuring out what the cast affects */
@@ -507,6 +502,7 @@ scan_for_static_refs (tree *tp,
        switch (TREE_CODE_CLASS (TREE_CODE (rhs))) 
          {
          case tcc_binary:          
+         case tcc_comparison:      
            {
              tree op0 = TREE_OPERAND (rhs, 0);
              tree op1 = TREE_OPERAND (rhs, 1);
@@ -533,7 +529,14 @@ scan_for_static_refs (tree *tp,
              case ADDR_EXPR:
                check_rhs_var (local, rhs);
                break;
-             case CALL_EXPR: 
+             default:
+               break;
+             }
+           break;
+         case tcc_vl_exp:
+           switch (TREE_CODE (rhs))
+             {
+             case CALL_EXPR:
                check_call (local, rhs);
                break;
              default:
@@ -689,7 +692,7 @@ merge_callee_local_info (struct cgraph_node *target,
     get_reference_vars_info_from_cgraph (target)->local;
 
   /* Make the world safe for tail recursion.  */
-  struct ipa_dfs_info *node_info = x->aux;
+  struct ipa_dfs_info *node_info = (struct ipa_dfs_info *) x->aux;
   
   if (node_info->aux) 
     return;
@@ -741,6 +744,7 @@ merge_callee_local_info (struct cgraph_node *target,
 static void 
 ipa_init (void) 
 {
+  struct cgraph_node *node;
   memory_identifier_string = build_string(7, "memory");
 
   reference_vars_to_consider =
@@ -751,6 +755,10 @@ ipa_init (void)
   module_statics_written = BITMAP_ALLOC (&ipa_obstack);
   all_module_statics = BITMAP_ALLOC (&ipa_obstack);
 
+  /* This will add NODE->DECL to the splay trees.  */
+  for (node = cgraph_nodes; node; node = node->next)
+    has_proper_scope_for_analysis (node->decl);
+
   /* There are some shared nodes, in particular the initializers on
      static declarations.  We do not need to scan them more than once
      since all we would be interested in are the addressof
@@ -765,16 +773,11 @@ ipa_init (void)
    to variables defined within this unit.  */
 
 static void 
-analyze_variable (struct cgraph_varpool_node *vnode)
+analyze_variable (struct varpool_node *vnode)
 {
   tree global = vnode->decl;
-  if (TREE_CODE (global) == VAR_DECL)
-    {
-      if (DECL_INITIAL (global)) 
-       walk_tree (&DECL_INITIAL (global), scan_for_static_refs, 
-                  NULL, visited_nodes);
-    } 
-  else gcc_unreachable ();
+  walk_tree (&DECL_INITIAL (global), scan_for_static_refs, 
+             NULL, visited_nodes);
 }
 
 /* This is the main routine for finding the reference patterns for
@@ -784,9 +787,9 @@ static void
 analyze_function (struct cgraph_node *fn)
 {
   ipa_reference_vars_info_t info 
-    = xcalloc (1, sizeof (struct ipa_reference_vars_info_d));
+    = XCNEW (struct ipa_reference_vars_info_d);
   ipa_reference_local_vars_info_t l
-    = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d));
+    = XCNEW (struct ipa_reference_local_vars_info_d);
   tree decl = fn->decl;
 
   /* Add the info to the tree's annotation.  */
@@ -806,6 +809,21 @@ analyze_function (struct cgraph_node *fn)
     FOR_EACH_BB_FN (this_block, this_cfun)
       {
        block_stmt_iterator bsi;
+       tree phi, op;
+       use_operand_p use;
+       ssa_op_iter iter;
+
+       /* Find the addresses taken in phi node arguments.  */
+       for (phi = phi_nodes (this_block); phi; phi = PHI_CHAIN (phi))
+         {
+           FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
+             {
+               op = USE_FROM_PTR (use);
+               if (TREE_CODE (op) == ADDR_EXPR)
+                 check_rhs_var (l, op);
+             }
+         }
+
        for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
          walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs, 
                     fn, visited_nodes);
@@ -883,21 +901,21 @@ clean_function (struct cgraph_node *fn)
    on the local information that was produced by ipa_analyze_function
    and ipa_analyze_variable.  */
 
-static void
+static unsigned int
 static_execute (void)
 {
   struct cgraph_node *node;
-  struct cgraph_varpool_node *vnode;
+  struct varpool_node *vnode;
   struct cgraph_node *w;
   struct cgraph_node **order =
-    xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
-  int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true);
+    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+  int order_pos = ipa_utils_reduced_inorder (order, false, true);
   int i;
 
   ipa_init ();
 
   /* Process all of the variables first.  */
-  for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+  FOR_EACH_STATIC_INITIALIZER (vnode)
     analyze_variable (vnode);
 
   /* Process all of the functions next. 
@@ -964,6 +982,11 @@ static_execute (void)
       {
        tree var = get_static_decl (index);
 
+       /* Readonly on a function decl is very different from the
+          variable.  */
+       if (TREE_CODE (var) == FUNCTION_DECL)
+         continue;
+
        /* Ignore variables in named sections - changing TREE_READONLY
           changes the section flags, potentially causing conflicts with
           other variables in the same named section.  */
@@ -1057,7 +1080,7 @@ static_execute (void)
     {
       ipa_reference_vars_info_t node_info;
       ipa_reference_global_vars_info_t node_g = 
-       xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d));
+       XCNEW (struct ipa_reference_global_vars_info_d);
       ipa_reference_local_vars_info_t node_l;
       
       bool read_all;
@@ -1081,7 +1104,7 @@ static_execute (void)
 
       /* If any node in a cycle is calls_read_all or calls_write_all
         they all are. */
-      w_info = node->aux;
+      w_info = (struct ipa_dfs_info *) node->aux;
       w = w_info->next_cycle;
       while (w)
        {
@@ -1090,7 +1113,7 @@ static_execute (void)
          read_all |= w_l->calls_read_all;
          write_all |= w_l->calls_write_all;
 
-         w_info = w->aux;
+         w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
 
@@ -1113,7 +1136,7 @@ static_execute (void)
                       node_l->statics_written);
        }
 
-      w_info = node->aux;
+      w_info = (struct ipa_dfs_info *) node->aux;
       w = w_info->next_cycle;
       while (w)
        {
@@ -1134,7 +1157,7 @@ static_execute (void)
          if (!write_all)
            bitmap_ior_into (node_g->statics_written,
                             w_l->statics_written);
-         w_info = w->aux;
+         w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
 
@@ -1142,7 +1165,7 @@ static_execute (void)
       while (w)
        {
          propagate_bits (w);
-         w_info = w->aux;
+         w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
     }
@@ -1159,12 +1182,12 @@ static_execute (void)
       node = order[i];
       merge_callee_local_info (node, node);
       
-      w_info = node->aux;
+      w_info = (struct ipa_dfs_info *) node->aux;
       w = w_info->next_cycle;
       while (w)
        {
          merge_callee_local_info (w, w);
-         w_info = w->aux;
+         w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
     }
@@ -1202,7 +1225,7 @@ static_execute (void)
                      get_static_name (index));
            }
 
-         w_info = node->aux;
+         w_info = (struct ipa_dfs_info *) node->aux;
          w = w_info->next_cycle;
          while (w) 
            {
@@ -1228,7 +1251,7 @@ static_execute (void)
                }
              
 
-             w_info = w->aux;
+             w_info = (struct ipa_dfs_info *) w->aux;
              w = w_info->next_cycle;
            }
          fprintf (dump_file, "\n  globals read: ");
@@ -1292,6 +1315,7 @@ static_execute (void)
          && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
        clean_function (node);
     }
+  return 0;
 }