OSDN Git Service

PR middle-end/41573
authormatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Oct 2009 16:03:11 +0000 (16:03 +0000)
committermatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Oct 2009 16:03:11 +0000 (16:03 +0000)
* builtins.c (fold_builtin_isascii): Use fold_build2.
(fold_builtin_isdigit): Ditto.
* except.c (duplicate_eh_regions_1): Tolerate NULL labels.
* tree-cfg.c (struct rus_data, remove_useless_stmts_warn_notreached,
remove_useless_stmts_cond, remove_useless_stmts_tf,
remove_useless_stmts_tc, remove_useless_stmts_bind,
remove_useless_stmts_goto, remove_useless_stmts_label,
remove_useless_stmts_1, remove_useless_stmts,
pass_remove_useless_stmts): Remove.
* tree-pass.h (pass_remove_useless_stmts): Don't declare.
* passes.c (init_optimization_passes): Don't add
pass_remove_useless_stmts.
* tree-eh.c (lower_eh_constructs_2): Handle empty cleanups.
* tree.c (free_lang_data_in_decl): Don't clear DECL_INITIAL of
static constants.
* lto-symtab.c (lto_symtab_register_decl): Accepts DECL_INITIAL
for static constants.
* lto-streamer-out.c (output_gimple_stmt): Handle GIMPLE_NOP.
* lto-streamer-in.c (input_gimple_stmt): Handle GIMPLE_NOP.

testsuite/
* gcc.dg/tree-ssa/foldstring-1.c: Use fre dump.
* gcc.dg/tree-ssa/useless-1.c: Use gimple dump.
* gcc.dg/pr41573.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152563 138bc75d-0d04-0410-961f-82ee72b054a4

15 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/except.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/lto-symtab.c
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr41573.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/foldstring-1.c
gcc/testsuite/gcc.dg/tree-ssa/useless-1.c
gcc/tree-cfg.c
gcc/tree-eh.c
gcc/tree-pass.h
gcc/tree.c

index 11eb0f8..b21fbc2 100644 (file)
@@ -1,3 +1,26 @@
+2009-10-08  Michael Matz  <matz@suse.de>
+
+       PR middle-end/41573
+       * builtins.c (fold_builtin_isascii): Use fold_build2.
+       (fold_builtin_isdigit): Ditto.
+       * except.c (duplicate_eh_regions_1): Tolerate NULL labels.
+       * tree-cfg.c (struct rus_data, remove_useless_stmts_warn_notreached,
+       remove_useless_stmts_cond, remove_useless_stmts_tf,
+       remove_useless_stmts_tc, remove_useless_stmts_bind,
+       remove_useless_stmts_goto, remove_useless_stmts_label,
+       remove_useless_stmts_1, remove_useless_stmts,
+       pass_remove_useless_stmts): Remove.
+       * tree-pass.h (pass_remove_useless_stmts): Don't declare.
+       * passes.c (init_optimization_passes): Don't add
+       pass_remove_useless_stmts.
+       * tree-eh.c (lower_eh_constructs_2): Handle empty cleanups.
+       * tree.c (free_lang_data_in_decl): Don't clear DECL_INITIAL of
+       static constants.
+       * lto-symtab.c (lto_symtab_register_decl): Accepts DECL_INITIAL
+       for static constants.
+       * lto-streamer-out.c (output_gimple_stmt): Handle GIMPLE_NOP.
+       * lto-streamer-in.c (input_gimple_stmt): Handle GIMPLE_NOP.
+
 2009-10-08  Richard Guenther  <rguenther@suse.de>
 
        * gimple.c (free_gimple_type_tables): New function.
index c9bc230..55228d2 100644 (file)
@@ -9238,9 +9238,9 @@ fold_builtin_isascii (location_t loc, tree arg)
   else
     {
       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
-      arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
-                   build_int_cst (NULL_TREE,
-                                  ~ (unsigned HOST_WIDE_INT) 0x7f));
+      arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
+                        build_int_cst (NULL_TREE,
+                                       ~ (unsigned HOST_WIDE_INT) 0x7f));
       return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
                          arg, integer_zero_node);
     }
@@ -9278,8 +9278,8 @@ fold_builtin_isdigit (location_t loc, tree arg)
        return NULL_TREE;
 
       arg = fold_convert_loc (loc, unsigned_type_node, arg);
-      arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
-                   build_int_cst (unsigned_type_node, target_digit0));
+      arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
+                        build_int_cst (unsigned_type_node, target_digit0));
       return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
                          build_int_cst (unsigned_type_node, 9));
     }
index c00bcd3..b25e48b 100644 (file)
@@ -552,8 +552,11 @@ duplicate_eh_regions_1 (struct duplicate_eh_regions_data *data,
 
     case ERT_ALLOWED_EXCEPTIONS:
       new_r->u.allowed.type_list = old_r->u.allowed.type_list;
-      new_r->u.allowed.label
-       = data->label_map (old_r->u.allowed.label, data->label_map_data);
+      if (old_r->u.allowed.label)
+       new_r->u.allowed.label
+           = data->label_map (old_r->u.allowed.label, data->label_map_data);
+      else
+       new_r->u.allowed.label = NULL_TREE;
       break;
 
     case ERT_MUST_NOT_THROW:
index 175a1e7..f41aa75 100644 (file)
@@ -942,6 +942,7 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        }
       break;
 
+    case GIMPLE_NOP:
     case GIMPLE_PREDICT:
       break;
 
index 6164867..499734f 100644 (file)
@@ -1692,6 +1692,7 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
        }
       break;
 
+    case GIMPLE_NOP:
     case GIMPLE_PREDICT:
       break;
 
index 7d30448..2a0783a 100644 (file)
@@ -323,8 +323,10 @@ lto_symtab_register_decl (tree decl,
              && (TREE_CODE (decl) == VAR_DECL
                  || TREE_CODE (decl) == FUNCTION_DECL)
              && DECL_ASSEMBLER_NAME_SET_P (decl));
-  if (TREE_CODE (decl) == VAR_DECL)
-    gcc_assert (!(DECL_EXTERNAL (decl) && DECL_INITIAL (decl)));
+  if (TREE_CODE (decl) == VAR_DECL
+      && DECL_INITIAL (decl))
+    gcc_assert (!DECL_EXTERNAL (decl)
+               || (TREE_STATIC (decl) && TREE_READONLY (decl)));
   if (TREE_CODE (decl) == FUNCTION_DECL)
     gcc_assert (!DECL_ABSTRACT (decl));
 
index 60a8509..5ed1206 100644 (file)
@@ -683,7 +683,6 @@ init_optimization_passes (void)
   p = &all_lowering_passes;
   NEXT_PASS (pass_warn_unused_result);
   NEXT_PASS (pass_diagnose_omp_blocks);
-  NEXT_PASS (pass_remove_useless_stmts);
   NEXT_PASS (pass_mudflap_1);
   NEXT_PASS (pass_lower_omp);
   NEXT_PASS (pass_lower_cf);
index 9b9b141..bf7e5ba 100644 (file)
@@ -1,3 +1,10 @@
+2009-10-08  Michael Matz  <matz@suse.de>
+
+       PR middle-end/41573
+       * gcc.dg/tree-ssa/foldstring-1.c: Use fre dump.
+       * gcc.dg/tree-ssa/useless-1.c: Use gimple dump.
+       * gcc.dg/pr41573.c: New test.
+
 2009-10-07  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/41182
diff --git a/gcc/testsuite/gcc.dg/pr41573.c b/gcc/testsuite/gcc.dg/pr41573.c
new file mode 100644 (file)
index 0000000..52961db
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+__inline __attribute__ ((__always_inline__)) char *
+strcpy (char *__dest, __const char *__src)
+{
+  return __builtin___strcpy_chk (__dest, __src, __builtin_object_size (__dest, 2 > 1));
+}
+
+const char* get_attr(unsigned attr)
+{
+    static char tmp[256];
+
+    strcpy(tmp, "");
+    return tmp;
+}
index 25a7ef4..fa64ae1 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-useless" } */
+/* { dg-options "-O1 -fdump-tree-fre" } */
 
 void
 arf ()
@@ -7,5 +7,5 @@ arf ()
   if (""[0] == 0)
     blah ();
 }
-/* { dg-final { scan-tree-dump-times "= 0;" 1 "useless"} } */ 
-/* { dg-final { cleanup-tree-dump "useless" } } */
+/* { dg-final { scan-tree-dump-times "= 0;" 1 "fre"} } */ 
+/* { dg-final { cleanup-tree-dump "fre" } } */
index 9170b7c..68eab70 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-useless" } */
+/* { dg-options "-O1 -fdump-tree-gimple" } */
 
 void
 foo (void)
@@ -13,5 +13,5 @@ foo (void)
    in the loop exit condition, it would be re-introduced during
    GIMPLE lowering, at the cost of an extra statement, label,
    and basic block.  */
-/* { dg-final { scan-tree-dump-times "goto" 3 "useless"} } */ 
-/* { dg-final { cleanup-tree-dump "useless" } } */
+/* { dg-final { scan-tree-dump-times "goto" 3 "gimple"} } */ 
+/* { dg-final { cleanup-tree-dump "gimple" } } */
index e392f48..1c820a3 100644 (file)
@@ -1715,423 +1715,6 @@ single_noncomplex_succ (basic_block bb)
   return bb;
 }
 
-
-/* Walk the function tree removing unnecessary statements.
-
-     * Empty statement nodes are removed
-
-     * Unnecessary TRY_FINALLY and TRY_CATCH blocks are removed
-
-     * Unnecessary COND_EXPRs are removed
-
-     * Some unnecessary BIND_EXPRs are removed
-
-     * GOTO_EXPRs immediately preceding destination are removed.
-
-   Clearly more work could be done.  The trick is doing the analysis
-   and removal fast enough to be a net improvement in compile times.
-
-   Note that when we remove a control structure such as a COND_EXPR
-   BIND_EXPR, or TRY block, we will need to repeat this optimization pass
-   to ensure we eliminate all the useless code.  */
-
-struct rus_data
-{
-  bool repeat;
-  bool may_throw;
-  bool may_branch;
-  bool has_label;
-  bool last_was_goto;
-  gimple_stmt_iterator last_goto_gsi;
-};
-
-
-static void remove_useless_stmts_1 (gimple_stmt_iterator *gsi, struct rus_data *);
-
-/* Given a statement sequence, find the first executable statement with
-   location information, and warn that it is unreachable.  When searching,
-   descend into containers in execution order.  */
-
-static bool
-remove_useless_stmts_warn_notreached (gimple_seq stmts)
-{
-  gimple_stmt_iterator gsi;
-
-  for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      gimple stmt = gsi_stmt (gsi);
-
-      if (gimple_no_warning_p (stmt)) return false;
-
-      if (gimple_has_location (stmt))
-        {
-          location_t loc = gimple_location (stmt);
-          if (LOCATION_LINE (loc) > 0)
-           {
-              warning_at (loc, OPT_Wunreachable_code, "will never be executed");
-              return true;
-            }
-        }
-
-      switch (gimple_code (stmt))
-        {
-        /* Unfortunately, we need the CFG now to detect unreachable
-           branches in a conditional, so conditionals are not handled here.  */
-
-        case GIMPLE_TRY:
-          if (remove_useless_stmts_warn_notreached (gimple_try_eval (stmt)))
-            return true;
-          if (remove_useless_stmts_warn_notreached (gimple_try_cleanup (stmt)))
-            return true;
-          break;
-
-        case GIMPLE_CATCH:
-          return remove_useless_stmts_warn_notreached (gimple_catch_handler (stmt));
-
-        case GIMPLE_EH_FILTER:
-          return remove_useless_stmts_warn_notreached (gimple_eh_filter_failure (stmt));
-
-        case GIMPLE_BIND:
-          return remove_useless_stmts_warn_notreached (gimple_bind_body (stmt));
-
-        default:
-          break;
-        }
-    }
-
-  return false;
-}
-
-/* Helper for remove_useless_stmts_1.  Handle GIMPLE_COND statements.  */
-
-static void
-remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  gimple stmt = gsi_stmt (*gsi);
-
-  /* The folded result must still be a conditional statement.  */
-  fold_stmt (gsi);
-  gcc_assert (gsi_stmt (*gsi) == stmt);
-
-  data->may_branch = true;
-
-  /* Replace trivial conditionals with gotos. */
-  if (gimple_cond_true_p (stmt))
-    {
-      /* Goto THEN label.  */
-      tree then_label = gimple_cond_true_label (stmt);
-
-      gsi_replace (gsi, gimple_build_goto (then_label), false);
-      data->last_goto_gsi = *gsi;
-      data->last_was_goto = true;
-      data->repeat = true;
-    }
-  else if (gimple_cond_false_p (stmt))
-    {
-      /* Goto ELSE label.  */
-      tree else_label = gimple_cond_false_label (stmt);
-
-      gsi_replace (gsi, gimple_build_goto (else_label), false);
-      data->last_goto_gsi = *gsi;
-      data->last_was_goto = true;
-      data->repeat = true;
-    }
-  else
-    {
-      tree then_label = gimple_cond_true_label (stmt);
-      tree else_label = gimple_cond_false_label (stmt);
-
-      if (then_label == else_label)
-        {
-          /* Goto common destination.  */
-          gsi_replace (gsi, gimple_build_goto (then_label), false);
-          data->last_goto_gsi = *gsi;
-          data->last_was_goto = true;
-         data->repeat = true;
-       }
-    }
-
-  gsi_next (gsi);
-
-  data->last_was_goto = false;
-}
-
-/* Helper for remove_useless_stmts_1. 
-   Handle the try-finally case for GIMPLE_TRY statements.  */
-
-static void
-remove_useless_stmts_tf (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  bool save_may_branch, save_may_throw;
-  bool this_may_branch, this_may_throw;
-
-  gimple_seq eval_seq, cleanup_seq;
-  gimple_stmt_iterator eval_gsi, cleanup_gsi;
-
-  gimple stmt = gsi_stmt (*gsi);
-
-  /* Collect may_branch and may_throw information for the body only.  */
-  save_may_branch = data->may_branch;
-  save_may_throw = data->may_throw;
-  data->may_branch = false;
-  data->may_throw = false;
-  data->last_was_goto = false;
-
-  eval_seq = gimple_try_eval (stmt);
-  eval_gsi = gsi_start (eval_seq);
-  remove_useless_stmts_1 (&eval_gsi, data);
-
-  this_may_branch = data->may_branch;
-  this_may_throw = data->may_throw;
-  data->may_branch |= save_may_branch;
-  data->may_throw |= save_may_throw;
-  data->last_was_goto = false;
-
-  cleanup_seq = gimple_try_cleanup (stmt);
-  cleanup_gsi = gsi_start (cleanup_seq);
-  remove_useless_stmts_1 (&cleanup_gsi, data);
-
-  /* If the body is empty, then we can emit the FINALLY block without
-     the enclosing TRY_FINALLY_EXPR.  */
-  if (gimple_seq_empty_p (eval_seq))
-    {
-      gsi_insert_seq_before (gsi, cleanup_seq, GSI_SAME_STMT);
-      gsi_remove (gsi, false);
-      data->repeat = true;
-    }
-
-  /* If the handler is empty, then we can emit the TRY block without
-     the enclosing TRY_FINALLY_EXPR.  */
-  else if (gimple_seq_empty_p (cleanup_seq))
-    {
-      gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
-      gsi_remove (gsi, false);
-      data->repeat = true;
-    }
-
-  /* If the body neither throws, nor branches, then we can safely
-     string the TRY and FINALLY blocks together.  */
-  else if (!this_may_branch && !this_may_throw)
-    {
-      gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
-      gsi_insert_seq_before (gsi, cleanup_seq, GSI_SAME_STMT);
-      gsi_remove (gsi, false);
-      data->repeat = true;
-    }
-  else
-    gsi_next (gsi);
-}
-
-/* Helper for remove_useless_stmts_1. 
-   Handle the try-catch case for GIMPLE_TRY statements.  */
-
-static void
-remove_useless_stmts_tc (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  bool save_may_throw, this_may_throw;
-
-  gimple_seq eval_seq, cleanup_seq, handler_seq, failure_seq;
-  gimple_stmt_iterator eval_gsi, cleanup_gsi, handler_gsi, failure_gsi;
-
-  gimple stmt = gsi_stmt (*gsi);
-
-  /* Collect may_throw information for the body only.  */
-  save_may_throw = data->may_throw;
-  data->may_throw = false;
-  data->last_was_goto = false;
-
-  eval_seq = gimple_try_eval (stmt);
-  eval_gsi = gsi_start (eval_seq);
-  remove_useless_stmts_1 (&eval_gsi, data);
-
-  this_may_throw = data->may_throw;
-  data->may_throw = save_may_throw;
-
-  cleanup_seq = gimple_try_cleanup (stmt);
-
-  /* If the body cannot throw, then we can drop the entire TRY_CATCH_EXPR.  */
-  if (!this_may_throw)
-    {
-      if (warn_notreached)
-        {
-          remove_useless_stmts_warn_notreached (cleanup_seq);
-        }
-      gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
-      gsi_remove (gsi, false);
-      data->repeat = true;
-      return;
-    }
-
-  /* Process the catch clause specially.  We may be able to tell that
-     no exceptions propagate past this point.  */
-
-  this_may_throw = true;
-  cleanup_gsi = gsi_start (cleanup_seq);
-  stmt = gsi_stmt (cleanup_gsi);
-  data->last_was_goto = false;
-
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_CATCH:
-      /* If the first element is a catch, they all must be.  */
-      while (!gsi_end_p (cleanup_gsi))
-        {
-         stmt = gsi_stmt (cleanup_gsi);
-         /* If we catch all exceptions, then the body does not
-            propagate exceptions past this point.  */
-         if (gimple_catch_types (stmt) == NULL)
-           this_may_throw = false;
-         data->last_was_goto = false;
-          handler_seq = gimple_catch_handler (stmt);
-          handler_gsi = gsi_start (handler_seq);
-         remove_useless_stmts_1 (&handler_gsi, data);
-          gsi_next (&cleanup_gsi);
-       }
-      gsi_next (gsi);
-      break;
-
-    case GIMPLE_EH_FILTER:
-      if (gimple_eh_filter_types (stmt) == NULL)
-       this_may_throw = false;
-      failure_seq = gimple_eh_filter_failure (stmt);
-      failure_gsi = gsi_start (failure_seq);
-      remove_useless_stmts_1 (&failure_gsi, data);
-      gsi_next (gsi);
-      break;
-
-    case GIMPLE_EH_MUST_NOT_THROW:
-      this_may_throw = false;
-      gsi_next (gsi);
-      break;
-
-    default:
-      /* Otherwise this is a list of cleanup statements.  */
-      remove_useless_stmts_1 (&cleanup_gsi, data);
-
-      /* If the cleanup is empty, then we can emit the TRY block without
-        the enclosing TRY_CATCH_EXPR.  */
-      if (gimple_seq_empty_p (cleanup_seq))
-       {
-          gsi_insert_seq_before (gsi, eval_seq, GSI_SAME_STMT);
-          gsi_remove(gsi, false);
-         data->repeat = true;
-       }
-      else
-        gsi_next (gsi);
-      break;
-    }
-
-  data->may_throw |= this_may_throw;
-}
-
-/* Helper for remove_useless_stmts_1.  Handle GIMPLE_BIND statements.  */
-
-static void
-remove_useless_stmts_bind (gimple_stmt_iterator *gsi, struct rus_data *data ATTRIBUTE_UNUSED)
-{
-  tree block;
-  gimple_seq body_seq, fn_body_seq;
-  gimple_stmt_iterator body_gsi;
-
-  gimple stmt = gsi_stmt (*gsi);
-
-  /* First remove anything underneath the BIND_EXPR.  */
-  
-  body_seq = gimple_bind_body (stmt);
-  body_gsi = gsi_start (body_seq);
-  remove_useless_stmts_1 (&body_gsi, data);
-
-  /* If the GIMPLE_BIND has no variables, then we can pull everything
-     up one level and remove the GIMPLE_BIND, unless this is the toplevel
-     GIMPLE_BIND for the current function or an inlined function.
-
-     When this situation occurs we will want to apply this
-     optimization again.  */
-  block = gimple_bind_block (stmt);
-  fn_body_seq = gimple_body (current_function_decl);
-  if (gimple_bind_vars (stmt) == NULL_TREE
-      && (gimple_seq_empty_p (fn_body_seq)
-          || stmt != gimple_seq_first_stmt (fn_body_seq))
-      && (! block
-         || ! BLOCK_ABSTRACT_ORIGIN (block)
-         || (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
-             != FUNCTION_DECL)))
-    {
-      tree var = NULL_TREE;
-      /* Even if there are no gimple_bind_vars, there might be other
-        decls in BLOCK_VARS rendering the GIMPLE_BIND not useless.  */
-      if (block && !BLOCK_NUM_NONLOCALIZED_VARS (block))
-       for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
-         if (TREE_CODE (var) == IMPORTED_DECL)
-           break;
-      if (var || (block && BLOCK_NUM_NONLOCALIZED_VARS (block)))
-       gsi_next (gsi);
-      else
-       {
-         gsi_insert_seq_before (gsi, body_seq, GSI_SAME_STMT);
-         gsi_remove (gsi, false);
-         data->repeat = true;
-       }
-    }
-  else
-    gsi_next (gsi);
-}
-
-/* Helper for remove_useless_stmts_1.  Handle GIMPLE_GOTO statements.  */
-
-static void
-remove_useless_stmts_goto (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  gimple stmt = gsi_stmt (*gsi);
-
-  tree dest = gimple_goto_dest (stmt);
-
-  data->may_branch = true;
-  data->last_was_goto = false;
-
-  /* Record iterator for last goto expr, so that we can delete it if unnecessary.  */
-  if (TREE_CODE (dest) == LABEL_DECL)
-    {
-      data->last_goto_gsi = *gsi;
-      data->last_was_goto = true;
-    }
-
-  gsi_next(gsi);
-}
-
-/* Helper for remove_useless_stmts_1.  Handle GIMPLE_LABEL statements.  */
-
-static void
-remove_useless_stmts_label (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  gimple stmt = gsi_stmt (*gsi);
-
-  tree label = gimple_label_label (stmt);
-
-  data->has_label = true;
-
-  /* We do want to jump across non-local label receiver code.  */
-  if (DECL_NONLOCAL (label))
-    data->last_was_goto = false;
-
-  else if (data->last_was_goto
-           && gimple_goto_dest (gsi_stmt (data->last_goto_gsi)) == label)
-    {
-      /* Replace the preceding GIMPLE_GOTO statement with
-         a GIMPLE_NOP, which will be subsequently removed.
-         In this way, we avoid invalidating other iterators
-         active on the statement sequence.  */
-      gsi_replace(&data->last_goto_gsi, gimple_build_nop(), false);
-      data->last_was_goto = false;
-      data->repeat = true;
-    }
-
-  /* ??? Add something here to delete unused labels.  */
-
-  gsi_next (gsi);
-}
-
-
 /* T is CALL_EXPR.  Set current_function_calls_* flags.  */
 
 void
@@ -2156,188 +1739,6 @@ clear_special_calls (void)
   cfun->calls_setjmp = false;
 }
 
-/* Remove useless statements from a statement sequence, and perform
-   some preliminary simplifications.  */
-
-static void
-remove_useless_stmts_1 (gimple_stmt_iterator *gsi, struct rus_data *data)
-{
-  while (!gsi_end_p (*gsi))
-    {
-      gimple stmt = gsi_stmt (*gsi);
-
-      switch (gimple_code (stmt))
-        {
-        case GIMPLE_COND:
-          remove_useless_stmts_cond (gsi, data);
-          break;
-
-        case GIMPLE_GOTO:
-          remove_useless_stmts_goto (gsi, data);
-          break;
-
-        case GIMPLE_LABEL:
-          remove_useless_stmts_label (gsi, data);
-          break;
-
-        case GIMPLE_ASSIGN:
-          fold_stmt (gsi);
-          stmt = gsi_stmt (*gsi);
-          data->last_was_goto = false;
-          if (stmt_could_throw_p (stmt))
-            data->may_throw = true;
-          gsi_next (gsi);
-          break;
-
-        case GIMPLE_ASM:
-          fold_stmt (gsi);
-          data->last_was_goto = false;
-          gsi_next (gsi);
-          break;
-
-        case GIMPLE_CALL:
-          fold_stmt (gsi);
-          stmt = gsi_stmt (*gsi);
-          data->last_was_goto = false;
-          if (is_gimple_call (stmt))
-            notice_special_calls (stmt);
-
-          /* We used to call update_gimple_call_flags here,
-             which copied side-effects and nothrows status
-             from the function decl to the call.  In the new
-             tuplified GIMPLE, the accessors for this information
-             always consult the function decl, so this copying
-             is no longer necessary.  */
-          if (stmt_could_throw_p (stmt))
-            data->may_throw = true;
-          gsi_next (gsi);
-          break;
-
-        case GIMPLE_RETURN:
-          fold_stmt (gsi);
-          data->last_was_goto = false;
-          data->may_branch = true;
-          gsi_next (gsi);
-          break;
-
-        case GIMPLE_BIND:
-          remove_useless_stmts_bind (gsi, data);
-          break;
-
-        case GIMPLE_TRY:
-          if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
-            remove_useless_stmts_tc (gsi, data);
-          else if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
-            remove_useless_stmts_tf (gsi, data);
-          else
-            gcc_unreachable ();
-          break;
-
-        case GIMPLE_CATCH:
-          gcc_unreachable ();
-          break;
-
-        case GIMPLE_NOP:
-          gsi_remove (gsi, false);
-          break;
-
-        case GIMPLE_OMP_FOR:
-          {
-            gimple_seq pre_body_seq = gimple_omp_for_pre_body (stmt);
-            gimple_stmt_iterator pre_body_gsi = gsi_start (pre_body_seq);
-
-            remove_useless_stmts_1 (&pre_body_gsi, data);
-           data->last_was_goto = false;
-          }
-          /* FALLTHROUGH */
-        case GIMPLE_OMP_CRITICAL:
-        case GIMPLE_OMP_CONTINUE:
-        case GIMPLE_OMP_MASTER:
-        case GIMPLE_OMP_ORDERED:
-        case GIMPLE_OMP_SECTION:
-        case GIMPLE_OMP_SECTIONS:
-        case GIMPLE_OMP_SINGLE:
-          {
-            gimple_seq body_seq = gimple_omp_body (stmt);
-            gimple_stmt_iterator body_gsi = gsi_start (body_seq);
-
-            remove_useless_stmts_1 (&body_gsi, data);
-           data->last_was_goto = false;
-           gsi_next (gsi);
-          }
-          break;
-
-        case GIMPLE_OMP_PARALLEL:
-       case GIMPLE_OMP_TASK:
-          {
-           /* Make sure the outermost GIMPLE_BIND isn't removed
-              as useless.  */
-            gimple_seq body_seq = gimple_omp_body (stmt);
-            gimple bind = gimple_seq_first_stmt (body_seq);
-            gimple_seq bind_seq = gimple_bind_body (bind);
-            gimple_stmt_iterator bind_gsi = gsi_start (bind_seq);
-
-            remove_useless_stmts_1 (&bind_gsi, data);
-           data->last_was_goto = false;
-           gsi_next (gsi);
-          }
-          break;
-
-        default:
-          data->last_was_goto = false;
-          gsi_next (gsi);
-          break;
-        }
-    }
-}
-
-/* Walk the function tree, removing useless statements and performing
-   some preliminary simplifications.  */
-
-static unsigned int
-remove_useless_stmts (void)
-{
-  struct rus_data data;
-
-  clear_special_calls ();
-
-  do
-    {
-      gimple_stmt_iterator gsi;
-
-      gsi = gsi_start (gimple_body (current_function_decl));
-      memset (&data, 0, sizeof (data));
-      remove_useless_stmts_1 (&gsi, &data);
-    }
-  while (data.repeat);
-
-#ifdef ENABLE_TYPES_CHECKING
-  verify_types_in_gimple_seq (gimple_body (current_function_decl));
-#endif
-
-  return 0;
-}
-
-
-struct gimple_opt_pass pass_remove_useless_stmts =
-{
- {
-  GIMPLE_PASS,
-  "useless",                           /* name */
-  NULL,                                        /* gate */
-  remove_useless_stmts,                        /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
-  PROP_gimple_any,                     /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
- }
-};
-
 /* Remove PHI nodes associated with basic block BB and all edges out of BB.  */
 
 static void
index 3ed92a5..e782738 100644 (file)
@@ -1919,21 +1919,27 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
       else
        {
          x = gimple_seq_first_stmt (gimple_try_cleanup (stmt));
-         switch (gimple_code (x))
+         if (!x)
            {
-           case GIMPLE_CATCH:
-             replace = lower_catch (state, stmt);
-             break;
-           case GIMPLE_EH_FILTER:
-             replace = lower_eh_filter (state, stmt);
-             break;
-           case GIMPLE_EH_MUST_NOT_THROW:
-             replace = lower_eh_must_not_throw (state, stmt);
-             break;
-           default:
-             replace = lower_cleanup (state, stmt);
-             break;
+             replace = gimple_try_eval (stmt);
+             lower_eh_constructs_1 (state, replace);
            }
+         else
+           switch (gimple_code (x))
+             {
+               case GIMPLE_CATCH:
+                   replace = lower_catch (state, stmt);
+                   break;
+               case GIMPLE_EH_FILTER:
+                   replace = lower_eh_filter (state, stmt);
+                   break;
+               case GIMPLE_EH_MUST_NOT_THROW:
+                   replace = lower_eh_must_not_throw (state, stmt);
+                   break;
+               default:
+                   replace = lower_cleanup (state, stmt);
+                   break;
+             }
        }
 
       /* Remove the old stmt and insert the transformed sequence
index 2cbe3e4..b829cee 100644 (file)
@@ -333,7 +333,6 @@ extern void tree_lowering_passes (tree decl);
 
 extern struct gimple_opt_pass pass_mudflap_1;
 extern struct gimple_opt_pass pass_mudflap_2;
-extern struct gimple_opt_pass pass_remove_useless_stmts;
 extern struct gimple_opt_pass pass_lower_cf;
 extern struct gimple_opt_pass pass_refactor_eh;
 extern struct gimple_opt_pass pass_lower_eh;
index 77ba3f8..4c3f52b 100644 (file)
@@ -4438,7 +4438,8 @@ free_lang_data_in_decl (tree decl)
          && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
        SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
 
-      if (DECL_EXTERNAL (decl))
+      if (DECL_EXTERNAL (decl)
+         && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
        DECL_INITIAL (decl) = NULL_TREE;
     }
   else if (TREE_CODE (decl) == TYPE_DECL)