OSDN Git Service

Backport from mainline
[pf3gnuchains/gcc-fork.git] / gcc / ipa-reference.c
index 64ccb4e..7b45c65 100644 (file)
@@ -58,8 +58,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "diagnostic.h"
 #include "langhooks.h"
+#include "data-streamer.h"
 #include "lto-streamer.h"
-#include "toplev.h"
 
 static void remove_node_data (struct cgraph_node *node,
                              void *data ATTRIBUTE_UNUSED);
@@ -87,7 +87,7 @@ struct ipa_reference_global_vars_info_d
   bitmap statics_written;
 };
 
-/* Information we save about every function after ipa-reference is completted.  */
+/* Information we save about every function after ipa-reference is completed.  */
 
 struct ipa_reference_optimization_summary_d
 {
@@ -197,9 +197,11 @@ ipa_reference_get_not_read_global (struct cgraph_node *fn)
 {
   ipa_reference_optimization_summary_t info;
 
-  info = get_reference_optimization_summary (fn);
+  info = get_reference_optimization_summary (cgraph_function_node (fn, NULL));
   if (info)
     return info->statics_not_read;
+  else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
+    return all_module_statics;
   else
     return NULL;
 }
@@ -217,6 +219,8 @@ ipa_reference_get_not_written_global (struct cgraph_node *fn)
   info = get_reference_optimization_summary (fn);
   if (info)
     return info->statics_not_written;
+  else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
+    return all_module_statics;
   else
     return NULL;
 }
@@ -298,12 +302,17 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x
   struct cgraph_edge *e;
   for (e = x->callees; e; e = e->next_callee)
     {
-      struct cgraph_node *y = e->callee;
+      enum availability avail;
+      struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
 
+      if (!y)
+       continue;
       /* Only look into nodes we can propagate something.  */
-      if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
+      if (avail > AVAIL_OVERWRITABLE
+         || (avail == AVAIL_OVERWRITABLE
+             && (flags_from_decl_or_type (y->decl) & ECF_LEAF)))
        {
-         int flags = flags_from_decl_or_type (e->callee->decl);
+         int flags = flags_from_decl_or_type (y->decl);
          if (get_reference_vars_info (y))
            {
              ipa_reference_vars_info_t y_info
@@ -573,17 +582,28 @@ read_write_all_from_decl (struct cgraph_node *node, bool * read_all,
 {
   tree decl = node->decl;
   int flags = flags_from_decl_or_type (decl);
-  if (flags & ECF_CONST)
+  if ((flags & ECF_LEAF)
+      && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
+    ;
+  else if (flags & ECF_CONST)
     ;
   else if ((flags & ECF_PURE)
           || cgraph_node_cannot_return (node))
-    *read_all = true;
+    {
+      *read_all = true;
+      if (dump_file && (dump_flags & TDF_DETAILS))
+         fprintf (dump_file, "   %s/%i -> read all\n",
+                 cgraph_node_name (node), node->uid);
+    }
   else
     {
        /* TODO: To be able to produce sane results, we should also handle
          common builtins, in particular throw.  */
       *read_all = true;
       *write_all = true;
+      if (dump_file && (dump_flags & TDF_DETAILS))
+         fprintf (dump_file, "   %s/%i -> read all, write all\n",
+                 cgraph_node_name (node), node->uid);
     }
 }
 
@@ -597,7 +617,7 @@ propagate (void)
   struct cgraph_node *w;
   struct cgraph_node **order =
     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
-  int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
+  int order_pos;
   int i;
 
   if (dump_file)
@@ -610,9 +630,9 @@ propagate (void)
      the global information.  All the nodes within a cycle will have
      the same info so we collapse cycles first.  Then we can do the
      propagation in one pass from the leaves to the roots.  */
-  order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
+  order_pos = ipa_reduced_postorder (order, true, true, NULL);
   if (dump_file)
-    ipa_utils_print_order(dump_file, "reduced", order, order_pos);
+    ipa_print_order (dump_file, "reduced", order, order_pos);
 
   for (i = 0; i < order_pos; i++ )
     {
@@ -626,30 +646,47 @@ propagate (void)
       struct ipa_dfs_info * w_info;
 
       node = order[i];
+      if (node->alias)
+       continue;
       node_info = get_reference_vars_info (node);
       gcc_assert (node_info);
 
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Starting cycle with %s/%i\n",
+                 cgraph_node_name (node), node->uid);
+
       node_l = &node_info->local;
       node_g = &node_info->global;
 
       read_all = false;
       write_all = false;
 
-      /* When function is overwrittable, we can not assume anything.  */
+      /* When function is overwritable, we can not assume anything.  */
       if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
         read_write_all_from_decl (node, &read_all, &write_all);
 
       for (e = node->callees; e; e = e->next_callee)
-        if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
-          read_write_all_from_decl (e->callee, &read_all, &write_all);
+       {
+         enum availability avail;
+         struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
+          if (!callee || avail <= AVAIL_OVERWRITABLE)
+            read_write_all_from_decl (callee, &read_all, &write_all);
+       }
 
       for (ie = node->indirect_calls; ie; ie = ie->next_callee)
        if (!(ie->indirect_info->ecf_flags & ECF_CONST))
          {
            read_all = true;
+           if (dump_file && (dump_flags & TDF_DETAILS))
+              fprintf (dump_file, "   indirect call -> read all\n");
            if (!cgraph_edge_cannot_lead_to_return (ie)
                && !(ie->indirect_info->ecf_flags & ECF_PURE))
-             write_all = true;
+             {
+               if (dump_file && (dump_flags & TDF_DETAILS))
+                  fprintf (dump_file, "   indirect call -> write all\n");
+               write_all = true;
+             }
          }
 
 
@@ -659,21 +696,35 @@ propagate (void)
       w = w_info->next_cycle;
       while (w && (!read_all || !write_all))
        {
-         /* When function is overwrittable, we can not assume anything.  */
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "  Visiting %s/%i\n",
+                     cgraph_node_name (w), w->uid);
+         /* When function is overwritable, we can not assume anything.  */
          if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
            read_write_all_from_decl (w, &read_all, &write_all);
 
          for (e = w->callees; e; e = e->next_callee)
-           if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
-             read_write_all_from_decl (e->callee, &read_all, &write_all);
+           {
+             enum availability avail;
+             struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
+
+             if (avail <= AVAIL_OVERWRITABLE)
+               read_write_all_from_decl (callee, &read_all, &write_all);
+           }
 
          for (ie = w->indirect_calls; ie; ie = ie->next_callee)
            if (!(ie->indirect_info->ecf_flags & ECF_CONST))
              {
                read_all = true;
+               if (dump_file && (dump_flags & TDF_DETAILS))
+                  fprintf (dump_file, "   indirect call -> read all\n");
                if (!cgraph_edge_cannot_lead_to_return (ie)
                    && !(ie->indirect_info->ecf_flags & ECF_PURE))
-                 write_all = true;
+                 {
+                   write_all = true;
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                      fprintf (dump_file, "   indirect call -> write all\n");
+                 }
              }
 
          w_info = (struct ipa_dfs_info *) w->aux;
@@ -754,6 +805,8 @@ propagate (void)
          struct ipa_dfs_info * w_info;
 
          node = order[i];
+         if (node->alias)
+           continue;
          node_info = get_reference_vars_info (node);
          node_g = &node_info->global;
          node_l = &node_info->local;
@@ -837,11 +890,12 @@ propagate (void)
       ipa_reference_global_vars_info_t node_g;
       ipa_reference_optimization_summary_t opt;
 
-      if (!node->analyzed)
+      if (!node->analyzed || node->alias)
         continue;
 
       node_info = get_reference_vars_info (node);
-      if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
+      if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
+         || (flags_from_decl_or_type (node->decl) & ECF_LEAF))
        {
          node_g = &node_info->global;
 
@@ -874,15 +928,10 @@ propagate (void)
                                  node_g->statics_written);
            }
        }
-      if (node_info)
-       free (node_info);
-      if (node->aux)
-       {
-         free (node->aux);
-         node->aux = NULL;
-       }
+      free (node_info);
    }
 
+  ipa_free_postorder_info ();
   free (order);
 
   bitmap_obstack_release (&local_info_obstack);
@@ -944,17 +993,17 @@ stream_out_bitmap (struct lto_simple_output_block *ob,
   bitmap_iterator bi;
   if (bits == all_module_statics)
     {
-      lto_output_sleb128_stream (ob->main_stream, -1);
+      streamer_write_hwi_stream (ob->main_stream, -1);
       return;
     }
   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
     count ++;
   if (count == ltrans_statics_bitcount)
     {
-      lto_output_sleb128_stream (ob->main_stream, -1);
+      streamer_write_hwi_stream (ob->main_stream, -1);
       return;
     }
-  lto_output_sleb128_stream (ob->main_stream, count);
+  streamer_write_hwi_stream (ob->main_stream, count);
   if (!count)
     return;
   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
@@ -1006,7 +1055,7 @@ ipa_reference_write_optimization_summary (cgraph_node_set set,
                                set, vset, ltrans_statics))
          count++;
 
-  lto_output_uleb128_stream (ob->main_stream, count);
+  streamer_write_uhwi_stream (ob->main_stream, count);
   if (count)
     stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
                       -1);
@@ -1023,7 +1072,7 @@ ipa_reference_write_optimization_summary (cgraph_node_set set,
 
            info = get_reference_optimization_summary (node);
            node_ref = lto_cgraph_encoder_encode (encoder, node);
-           lto_output_uleb128_stream (ob->main_stream, node_ref);
+           streamer_write_uhwi_stream (ob->main_stream, node_ref);
 
            stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
                               ltrans_statics_bitcount);
@@ -1064,16 +1113,16 @@ ipa_reference_read_optimization_summary (void)
       if (ib)
        {
          unsigned int i;
-         unsigned int f_count = lto_input_uleb128 (ib);
+         unsigned int f_count = streamer_read_uhwi (ib);
          int b_count;
          if (!f_count)
            continue;
-         b_count = lto_input_sleb128 (ib);
+         b_count = streamer_read_hwi (ib);
          if (dump_file)
            fprintf (dump_file, "all module statics:");
          for (i = 0; i < (unsigned int)b_count; i++)
            {
-             unsigned int var_index = lto_input_uleb128 (ib);
+             unsigned int var_index = streamer_read_uhwi (ib);
              tree v_decl = lto_file_decl_data_get_var_decl (file_data,
                                                             var_index);
              bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
@@ -1090,7 +1139,7 @@ ipa_reference_read_optimization_summary (void)
              int v_count;
              lto_cgraph_encoder_t encoder;
 
-             index = lto_input_uleb128 (ib);
+             index = streamer_read_uhwi (ib);
              encoder = file_data->cgraph_node_encoder;
              node = lto_cgraph_encoder_deref (encoder, index);
              info = XCNEW (struct ipa_reference_optimization_summary_d);
@@ -1103,7 +1152,7 @@ ipa_reference_read_optimization_summary (void)
                         cgraph_node_name (node), node->uid);
 
              /* Set the statics not read.  */
-             v_count = lto_input_sleb128 (ib);
+             v_count = streamer_read_hwi (ib);
              if (v_count == -1)
                {
                  info->statics_not_read = all_module_statics;
@@ -1113,7 +1162,7 @@ ipa_reference_read_optimization_summary (void)
              else
                for (j = 0; j < (unsigned int)v_count; j++)
                  {
-                   unsigned int var_index = lto_input_uleb128 (ib);
+                   unsigned int var_index = streamer_read_uhwi (ib);
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
                                                                   var_index);
                    bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
@@ -1126,7 +1175,7 @@ ipa_reference_read_optimization_summary (void)
                fprintf (dump_file,
                         "\n  static not written:");
              /* Set the statics not written.  */
-             v_count = lto_input_sleb128 (ib);
+             v_count = streamer_read_hwi (ib);
              if (v_count == -1)
                {
                  info->statics_not_written = all_module_statics;
@@ -1136,7 +1185,7 @@ ipa_reference_read_optimization_summary (void)
              else
                for (j = 0; j < (unsigned int)v_count; j++)
                  {
-                   unsigned int var_index = lto_input_uleb128 (ib);
+                   unsigned int var_index = streamer_read_uhwi (ib);
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
                                                                   var_index);
                    bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));