re PR target/60693 (ICE on funny memcpy)
[gcc.git] / gcc / ipa-pure-const.c
index 52be4bf8869f9c54f84a9bdbbbb730fa4c0c064f..7d35880996503f1ba44590c6862876cf67428f72 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph based analysis of static variables.
-   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+   Copyright (C) 2004-2014 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
 
 This file is part of GCC.
@@ -36,6 +36,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "print-tree.h"
+#include "calls.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
 #include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
@@ -44,8 +52,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "tree-pass.h"
 #include "langhooks.h"
-#include "pointer-set.h"
-#include "ggc.h"
 #include "ipa-utils.h"
 #include "flags.h"
 #include "diagnostic.h"
@@ -583,7 +589,7 @@ check_call (funct_state local, gimple call, bool ipa)
 /* Wrapper around check_decl for loads in local more.  */
 
 static bool
-check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_load (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, false, false);
@@ -595,7 +601,7 @@ check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for stores in local more.  */
 
 static bool
-check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_store (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, true, false);
@@ -607,7 +613,7 @@ check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for loads in ipa mode.  */
 
 static bool
-check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_load (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, false, true);
@@ -619,7 +625,7 @@ check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for stores in ipa mode.  */
 
 static bool
-check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_store (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, true, true);
@@ -748,7 +754,7 @@ analyze_function (struct cgraph_node *fn, bool ipa)
 
   push_cfun (DECL_STRUCT_FUNCTION (decl));
 
-  FOR_EACH_BB (this_block)
+  FOR_EACH_BB_FN (this_block, cfun)
     {
       gimple_stmt_iterator gsi;
       struct walk_stmt_info wi;
@@ -789,17 +795,16 @@ end:
            }
          else
            {
-             loop_iterator li;
              struct loop *loop;
              scev_initialize ();
-             FOR_EACH_LOOP (li, loop, 0)
+             FOR_EACH_LOOP (loop, 0)
                if (!finite_loop_p (loop))
                  {
                    if (dump_file)
                      fprintf (dump_file, "    can not prove finiteness of "
                               "loop %i\n", loop->num);
                    l->looping =true;
-                   FOR_EACH_LOOP_BREAK (li);
+                   break;
                  }
              scev_finalize ();
            }
@@ -1322,35 +1327,39 @@ propagate_pure_const (void)
          w_l->pure_const_state = this_state;
          w_l->looping = this_looping;
 
-         switch (this_state)
-           {
-           case IPA_CONST:
-             if (!TREE_READONLY (w->decl))
-               {
-                 warn_function_const (w->decl, !this_looping);
-                 if (dump_file)
-                   fprintf (dump_file, "Function found to be %sconst: %s\n",
-                            this_looping ? "looping " : "",
-                            w->name ());
-               }
-             cgraph_set_const_flag (w, true, this_looping);
-             break;
+         /* Inline clones share declaration with their offline copies;
+            do not modify their declarations since the offline copy may
+            be different.  */
+         if (!w->global.inlined_to)
+           switch (this_state)
+             {
+             case IPA_CONST:
+               if (!TREE_READONLY (w->decl))
+                 {
+                   warn_function_const (w->decl, !this_looping);
+                   if (dump_file)
+                     fprintf (dump_file, "Function found to be %sconst: %s\n",
+                              this_looping ? "looping " : "",
+                              w->name ());
+                 }
+               cgraph_set_const_flag (w, true, this_looping);
+               break;
 
-           case IPA_PURE:
-             if (!DECL_PURE_P (w->decl))
-               {
-                 warn_function_pure (w->decl, !this_looping);
-                 if (dump_file)
-                   fprintf (dump_file, "Function found to be %spure: %s\n",
-                            this_looping ? "looping " : "",
-                            w->name ());
-               }
-             cgraph_set_pure_flag (w, true, this_looping);
-             break;
+             case IPA_PURE:
+               if (!DECL_PURE_P (w->decl))
+                 {
+                   warn_function_pure (w->decl, !this_looping);
+                   if (dump_file)
+                     fprintf (dump_file, "Function found to be %spure: %s\n",
+                              this_looping ? "looping " : "",
+                              w->name ());
+                 }
+               cgraph_set_pure_flag (w, true, this_looping);
+               break;
 
-           default:
-             break;
-           }
+             default:
+               break;
+             }
          w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
@@ -1443,10 +1452,16 @@ propagate_nothrow (void)
          funct_state w_l = get_function_state (w);
          if (!can_throw && !TREE_NOTHROW (w->decl))
            {
-             cgraph_set_nothrow_flag (w, true);
-             if (dump_file)
-               fprintf (dump_file, "Function found to be nothrow: %s\n",
-                        w->name ());
+             /* Inline clones share declaration with their offline copies;
+                do not modify their declarations since the offline copy may
+                be different.  */
+             if (!w->global.inlined_to)
+               {
+                 cgraph_set_nothrow_flag (w, true);
+                 if (dump_file)
+                   fprintf (dump_file, "Function found to be nothrow: %s\n",
+                            w->name ());
+               }
            }
          else if (can_throw && !TREE_NOTHROW (w->decl))
            w_l->can_throw = true;
@@ -1586,7 +1601,7 @@ local_pure_const (void)
 
   /* Do NORETURN discovery.  */
   if (!skip && !TREE_THIS_VOLATILE (current_function_decl)
-      && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
+      && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 0)
     {
       warn_function_noreturn (cfun->decl);
       if (dump_file)
@@ -1722,7 +1737,7 @@ static unsigned int
 execute_warn_function_noreturn (void)
 {
   if (!TREE_THIS_VOLATILE (current_function_decl)
-      && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
+      && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 0)
     warn_function_noreturn (current_function_decl);
   return 0;
 }