passes.c (init_optimization_passes): Add simple dce and addressable passes.
authorJan Hubicka <jh@suse.cz>
Fri, 7 Sep 2007 11:28:35 +0000 (13:28 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 7 Sep 2007 11:28:35 +0000 (11:28 +0000)
* passes.c (init_optimization_passes): Add simple dce and addressable
passes.
* tree-ssa.c (execute_update_addresses_taken): New function.
(pass_update_address_taken): New.
* tree-ssa-dse.c (execute_simple_dse): New function.
(pass_simple_dse): New.
* tree-pass.h (pass_simple_dse, pass_update_address_taken): Declare.

From-SVN: r128239

gcc/ChangeLog
gcc/passes.c
gcc/tree-pass.h
gcc/tree-ssa-dse.c
gcc/tree-ssa.c

index bf2bc14575ea1db83053e39d90f9142e98b59a5f..be49cf50e604f51cd5315c9439a02b52f41aa0a3 100644 (file)
@@ -1,3 +1,13 @@
+2007-09-07  Jan Hubicka  <jh@suse.cz>
+
+       * passes.c (init_optimization_passes): Add simple dce and addressable
+       passes.
+       * tree-ssa.c (execute_update_addresses_taken): New function.
+       (pass_update_address_taken): New.
+       * tree-ssa-dse.c (execute_simple_dse): New function.
+       (pass_simple_dse): New.
+       * tree-pass.h (pass_simple_dse, pass_update_address_taken): Declare.
+
 2007-09-07  Tobias Burnus  <burnus@net-b.de>
 
        PR middle-end/33321
index 29ec8e282ebc0b40a3cf4c94e7b4fee6b5cd78cf..1b88414dd0120240783b012a75bb14debc612c38 100644 (file)
@@ -523,10 +523,14 @@ init_optimization_passes (void)
          NEXT_PASS (pass_rename_ssa_copies);
          NEXT_PASS (pass_ccp);
          NEXT_PASS (pass_forwprop);
+         NEXT_PASS (pass_update_address_taken);
+         NEXT_PASS (pass_simple_dse);
          NEXT_PASS (pass_sra_early);
          NEXT_PASS (pass_copy_prop);
          NEXT_PASS (pass_merge_phi);
          NEXT_PASS (pass_dce);
+         NEXT_PASS (pass_update_address_taken);
+         NEXT_PASS (pass_simple_dse);
          NEXT_PASS (pass_tail_recursion);
           NEXT_PASS (pass_profile);
          NEXT_PASS (pass_release_ssa_names);
index a7de71700b274458e41aa52e1cafb6fa5822ed14..19bda7cf4b7281755804521ba60ddcd4a98bb72b 100644 (file)
@@ -306,6 +306,7 @@ extern struct tree_opt_pass pass_forwprop;
 extern struct tree_opt_pass pass_phiprop;
 extern struct tree_opt_pass pass_tree_ifcombine;
 extern struct tree_opt_pass pass_dse;
+extern struct tree_opt_pass pass_simple_dse;
 extern struct tree_opt_pass pass_nrv;
 extern struct tree_opt_pass pass_mark_used_blocks;
 extern struct tree_opt_pass pass_rename_ssa_copies;
@@ -445,6 +446,7 @@ extern struct tree_opt_pass pass_early_inline;
 extern struct tree_opt_pass pass_inline_parameters;
 extern struct tree_opt_pass pass_apply_inline;
 extern struct tree_opt_pass pass_all_early_optimizations;
+extern struct tree_opt_pass pass_update_address_taken;
 
 /* The root of the compilation pass tree, once constructed.  */
 extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes;
index 68fa4458e644ff16bf23d3544d12a0a7ea79b64a..4416f7dc45d5fba6994314690c030d38a18de4e8 100644 (file)
@@ -918,3 +918,137 @@ struct tree_opt_pass pass_dse = {
     | TODO_verify_ssa,         /* todo_flags_finish */
   0                            /* letter */
 };
+
+/* A very simple dead store pass eliminating write only local variables.
+   The pass does not require alias information and thus can be run before
+   inlining to quickly eliminate artifacts of some common C++ constructs.  */
+
+static unsigned int
+execute_simple_dse (void)
+{
+  block_stmt_iterator bsi;
+  basic_block bb;
+  bitmap variables_loaded = BITMAP_ALLOC (NULL);
+  unsigned int todo = 0;
+
+  /* Collect into VARIABLES LOADED all variables that are read in function
+     body.  */
+  FOR_EACH_BB (bb)
+    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+      if (LOADED_SYMS (bsi_stmt (bsi)))
+       bitmap_ior_into (variables_loaded,
+                        LOADED_SYMS (bsi_stmt (bsi)));
+
+  /* Look for statements writting into the write only variables.
+     And try to remove them.  */
+
+  FOR_EACH_BB (bb)
+    for (bsi = bsi_start (bb); !bsi_end_p (bsi);)
+      {
+       tree stmt = bsi_stmt (bsi), op;
+       bool removed = false;
+        ssa_op_iter iter;
+
+       if (STORED_SYMS (stmt) && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+           && TREE_CODE (stmt) != RETURN_EXPR
+           && !bitmap_intersect_p (STORED_SYMS (stmt), variables_loaded))
+         {
+           unsigned int i;
+           bitmap_iterator bi;
+           bool dead = true;
+
+
+
+           /* See if STMT only stores to write-only variables and
+              verify that there are no volatile operands.  tree-ssa-operands
+              sets has_volatile_ops flag for all statements involving
+              reads and writes when aliases are not built to prevent passes
+              from removing them as dead.  The flag thus has no use for us
+              and we need to look into all operands.  */
+             
+           EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
+             {
+               tree var = referenced_var_lookup (i);
+               if (TREE_ADDRESSABLE (var)
+                   || is_global_var (var)
+                   || TREE_THIS_VOLATILE (var))
+                 dead = false;
+             }
+
+           if (dead && LOADED_SYMS (stmt))
+             EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
+               if (TREE_THIS_VOLATILE (referenced_var_lookup (i)))
+                 dead = false;
+
+           if (dead)
+             FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
+               if (TREE_THIS_VOLATILE (op))
+                 dead = false;
+
+           /* Look for possible occurence var = indirect_ref (...) where
+              indirect_ref itself is volatile.  */
+
+           if (dead && TREE_THIS_VOLATILE (GIMPLE_STMT_OPERAND (stmt, 1)))
+             dead = false;
+
+           if (dead)
+             {
+               tree call = get_call_expr_in (stmt);
+
+               /* When LHS of var = call (); is dead, simplify it into
+                  call (); saving one operand.  */
+               if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+                   && call
+                   && TREE_SIDE_EFFECTS (call))
+                 {
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                     {
+                       fprintf (dump_file, "Deleted LHS of call: ");
+                       print_generic_stmt (dump_file, stmt, TDF_SLIM);
+                       fprintf (dump_file, "\n");
+                     }
+                   push_stmt_changes (bsi_stmt_ptr (bsi));
+                   TREE_BLOCK (call) = TREE_BLOCK (stmt);
+                   bsi_replace (&bsi, call, false);
+                   maybe_clean_or_replace_eh_stmt (stmt, call);
+                   mark_symbols_for_renaming (call);
+                   pop_stmt_changes (bsi_stmt_ptr (bsi));
+                 }
+               else
+                 {
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                     {
+                       fprintf (dump_file, "  Deleted dead store '");
+                       print_generic_expr (dump_file, stmt, dump_flags);
+                       fprintf (dump_file, "'\n");
+                     }
+                   removed = true;
+                   bsi_remove (&bsi, true);
+                   todo |= TODO_cleanup_cfg;
+                 }
+               todo |= TODO_remove_unused_locals | TODO_ggc_collect;
+             }
+         }
+       if (!removed)
+         bsi_next (&bsi);
+      }
+  BITMAP_FREE (variables_loaded);
+  return todo;
+}
+
+struct tree_opt_pass pass_simple_dse =
+{
+  "sdse",                              /* name */
+  NULL,                                        /* gate */
+  execute_simple_dse,                  /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  PROP_ssa,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func,                      /* todo_flags_finish */
+  0                                    /* letter */
+};
index 633e446fe1a098b6eadf01c05a616c3776623d65..9723afb0eec3d19232717528ef2efc07af10b3eb 100644 (file)
@@ -1378,3 +1378,99 @@ struct tree_opt_pass pass_late_warn_uninitialized =
   0,                                    /* todo_flags_finish */
   0                                    /* letter */
 };
+
+/* Compute TREE_ADDRESSABLE for local variables.  */
+
+static unsigned int
+execute_update_addresses_taken (void)
+{
+  tree var;
+  referenced_var_iterator rvi;
+  block_stmt_iterator bsi;
+  basic_block bb;
+  bitmap addresses_taken = BITMAP_ALLOC (NULL);
+  bitmap vars_updated = BITMAP_ALLOC (NULL);
+  bool update_vops;
+  tree phi;
+
+  /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
+     the function body.  */
+  FOR_EACH_BB (bb)
+    {
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+       {
+         stmt_ann_t s_ann = stmt_ann (bsi_stmt (bsi));
+
+         if (s_ann->addresses_taken)
+           bitmap_ior_into (addresses_taken, s_ann->addresses_taken);
+       }
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         unsigned i, phi_num_args = PHI_NUM_ARGS (phi);
+         for (i = 0; i < phi_num_args; i++)
+           {
+             tree op = PHI_ARG_DEF (phi, i), var;
+             if (TREE_CODE (op) == ADDR_EXPR
+                 && (var = get_base_address (TREE_OPERAND (op, 0))) != NULL_TREE
+                 && DECL_P (var))
+               bitmap_set_bit (addresses_taken, DECL_UID (var));
+           }
+       }
+    }
+
+  /* When possible, clear ADDRESSABLE bit and mark variable for conversion into
+     SSA.  */
+  FOR_EACH_REFERENCED_VAR (var, rvi)
+    if (!is_global_var (var)
+       && TREE_CODE (var) != RESULT_DECL
+       && TREE_ADDRESSABLE (var)
+       && !bitmap_bit_p (addresses_taken, DECL_UID (var)))
+      {
+        TREE_ADDRESSABLE (var) = 0;
+       if (is_gimple_reg (var))
+         mark_sym_for_renaming (var);
+       update_vops = true;
+       bitmap_set_bit (vars_updated, DECL_UID (var));
+       if (dump_file)
+         {
+           fprintf (dump_file, "No longer having address taken ");
+           print_generic_expr (dump_file, var, 0);
+           fprintf (dump_file, "\n");
+         }
+      }
+
+  /* Operand caches needs to be recomputed for operands referencing the updated
+     variables.  */
+  if (update_vops)
+    FOR_EACH_BB (bb)
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+       {
+         tree stmt = bsi_stmt (bsi);
+
+         if ((LOADED_SYMS (stmt)
+              && bitmap_intersect_p (LOADED_SYMS (stmt), vars_updated))
+             || (STORED_SYMS (stmt)
+                 && bitmap_intersect_p (STORED_SYMS (stmt), vars_updated)))
+           update_stmt (stmt);
+       }
+  BITMAP_FREE (addresses_taken);
+  BITMAP_FREE (vars_updated);
+  return 0;
+}
+
+struct tree_opt_pass pass_update_address_taken =
+{
+  "addressables",                      /* name */
+  NULL,                                        /* gate */
+  execute_update_addresses_taken,      /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  PROP_ssa,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_update_ssa,                      /* todo_flags_finish */
+  0                                    /* letter */
+};