OSDN Git Service

* common.opt (N, Q, Qn, Qy, Z, n, r, s, t): New options.
[pf3gnuchains/gcc-fork.git] / gcc / ipa-pure-const.c
index bc17b0c..101e8c9 100644 (file)
@@ -49,7 +49,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "flags.h"
 #include "timevar.h"
-#include "toplev.h"
 #include "diagnostic.h"
 #include "gimple-pretty-print.h"
 #include "langhooks.h"
@@ -95,6 +94,11 @@ struct funct_state_d
   bool can_throw;
 };
 
+/* State used when we know nothing about function.  */
+static struct funct_state_d varying_state
+   = { IPA_NEITHER, IPA_NEITHER, true, true, true };
+
+
 typedef struct funct_state_d * funct_state;
 
 /* The storage of the funct_state is abstracted because there is the
@@ -133,7 +137,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
                   struct pointer_set_t *warned_about,
                   const char * attrib_name)
 {
-  if (!option_enabled (option))
+  if (!option_enabled (option, &global_options))
     return warned_about;
   if (TREE_THIS_VOLATILE (decl)
       || (known_finite && function_always_visible_to_compiler_p (decl)))
@@ -212,13 +216,12 @@ has_function_state (struct cgraph_node *node)
 static inline funct_state
 get_function_state (struct cgraph_node *node)
 {
-  static struct funct_state_d varying
-    = { IPA_NEITHER, IPA_NEITHER, true, true, true };
   if (!funct_state_vec
-      || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
+      || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid
+      || !VEC_index (funct_state, funct_state_vec, node->uid))
     /* We might want to put correct previously_known state into varying.  */
-    return &varying;
 return VEC_index (funct_state, funct_state_vec, node->uid);
+    return &varying_state;
+ return VEC_index (funct_state, funct_state_vec, node->uid);
 }
 
 /* Set the function state S for NODE.  */
@@ -324,7 +327,7 @@ check_op (funct_state local, tree t, bool checking_write)
       return;
     }
   else if (t
-          && INDIRECT_REF_P (t)
+          && (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF)
           && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
           && !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0)))
     {
@@ -423,7 +426,7 @@ worse_state (enum pure_const_state_e *state, bool *looping,
 /* Recognize special cases of builtins that are by themself not pure or const
    but function using them is.  */
 static bool
-special_builtlin_state (enum pure_const_state_e *state, bool *looping,
+special_builtin_state (enum pure_const_state_e *state, bool *looping,
                        tree callee)
 {
   if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
@@ -442,7 +445,6 @@ special_builtlin_state (enum pure_const_state_e *state, bool *looping,
        case BUILT_IN_FRAME_ADDRESS:
        case BUILT_IN_APPLY:
        case BUILT_IN_APPLY_ARGS:
-       case BUILT_IN_ARGS_INFO:
          *looping = false;
          *state = IPA_CONST;
          return true;
@@ -507,7 +509,7 @@ check_call (funct_state local, gimple call, bool ipa)
       enum pure_const_state_e call_state;
       bool call_looping;
 
-      if (special_builtlin_state (&call_state, &call_looping, callee_t))
+      if (special_builtin_state (&call_state, &call_looping, callee_t))
        {
          worse_state (&local->pure_const_state, &local->looping,
                       call_state, call_looping);
@@ -648,6 +650,13 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
       print_gimple_stmt (dump_file, stmt, 0, 0);
     }
 
+  if (gimple_has_volatile_ops (stmt))
+    {
+      local->pure_const_state = IPA_NEITHER;
+      if (dump_file)
+       fprintf (dump_file, "    Volatile stmt is not const/pure\n");
+    }
+
   /* Look for loads and stores.  */
   walk_stmt_load_store_ops (stmt, local,
                            ipa ? check_ipa_load : check_load,
@@ -860,7 +869,9 @@ remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
 {
   if (has_function_state (node))
     {
-      free (get_function_state (node));
+      funct_state l = get_function_state (node);
+      if (l != &varying_state)
+        free (l);
       set_function_state (node, NULL);
     }
 }
@@ -1191,7 +1202,7 @@ propagate_pure_const (void)
                      edge_looping = y_l->looping;
                    }
                }
-             else if (special_builtlin_state (&edge_state, &edge_looping,
+             else if (special_builtin_state (&edge_state, &edge_looping,
                                               y->decl))
                ;
              else
@@ -1310,8 +1321,7 @@ propagate_pure_const (void)
                             this_looping ? "looping " : "",
                             cgraph_node_name (w));
                }
-             cgraph_set_readonly_flag (w, true);
-             cgraph_set_looping_const_or_pure_flag (w, this_looping);
+             cgraph_set_const_flag (w, true, this_looping);
              break;
 
            case IPA_PURE:
@@ -1323,8 +1333,7 @@ propagate_pure_const (void)
                             this_looping ? "looping " : "",
                             cgraph_node_name (w));
                }
-             cgraph_set_pure_flag (w, true);
-             cgraph_set_looping_const_or_pure_flag (w, this_looping);
+             cgraph_set_pure_flag (w, true, this_looping);
              break;
 
            default:
@@ -1561,7 +1570,9 @@ local_pure_const (void)
       && skip)
     return 0;
 
-  /* First do NORETURN discovery.  */
+  l = analyze_function (node, false);
+
+  /* Do NORETURN discovery.  */
   if (!skip && !TREE_THIS_VOLATILE (current_function_decl)
       && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
     {
@@ -1577,7 +1588,6 @@ local_pure_const (void)
 
       changed = true;
     }
-  l = analyze_function (node, false);
 
   switch (l->pure_const_state)
     {
@@ -1587,8 +1597,7 @@ local_pure_const (void)
          warn_function_const (current_function_decl, !l->looping);
          if (!skip)
            {
-             cgraph_set_readonly_flag (node, true);
-             cgraph_set_looping_const_or_pure_flag (node, l->looping);
+             cgraph_set_const_flag (node, true, l->looping);
              changed = true;
            }
          if (dump_file)
@@ -1602,7 +1611,7 @@ local_pure_const (void)
        {
          if (!skip)
            {
-             cgraph_set_looping_const_or_pure_flag (node, false);
+             cgraph_set_const_flag (node, true, false);
              changed = true;
            }
          if (dump_file)
@@ -1617,8 +1626,7 @@ local_pure_const (void)
        {
          if (!skip)
            {
-             cgraph_set_pure_flag (node, true);
-             cgraph_set_looping_const_or_pure_flag (node, l->looping);
+             cgraph_set_pure_flag (node, true, l->looping);
              changed = true;
            }
          warn_function_pure (current_function_decl, !l->looping);
@@ -1633,7 +1641,7 @@ local_pure_const (void)
        {
          if (!skip)
            {
-             cgraph_set_looping_const_or_pure_flag (node, false);
+             cgraph_set_pure_flag (node, true, false);
              changed = true;
            }
          if (dump_file)