OSDN Git Service

* ada/gcc-interface/Make-lang.in, alias.c, attribs.c, auto-inc-dec.c,
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dom.c
index 4bad3dd..c3f259d 100644 (file)
@@ -1,5 +1,5 @@
 /* SSA Dominator optimizations for trees
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -83,7 +83,7 @@ struct cond_equivalence
 
    Computing and storing the edge equivalences instead of creating
    them on-demand can save significant amounts of time, particularly
-   for pathological cases involving switch statements.  
+   for pathological cases involving switch statements.
 
    These structures live for a single iteration of the dominator
    optimizer in the edge's AUX field.  At the end of an iteration we
@@ -210,7 +210,7 @@ initialize_hash_element (gimple stmt, tree lhs,
       enum tree_code subcode = gimple_assign_rhs_code (stmt);
 
       expr->type = NULL_TREE;
-      
+
       switch (get_gimple_rhs_class (subcode))
         {
         case GIMPLE_SINGLE_RHS:
@@ -255,7 +255,7 @@ initialize_hash_element (gimple stmt, tree lhs,
 
       if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
         expr->ops.call.pure = true;
-      else 
+      else
         expr->ops.call.pure = false;
 
       expr->ops.call.nargs = nargs;
@@ -293,7 +293,7 @@ static void
 initialize_expr_from_cond (tree cond, struct hashable_expr *expr)
 {
   expr->type = boolean_type_node;
-  
+
   if (COMPARISON_CLASS_P (cond))
     {
       expr->kind = EXPR_BINARY;
@@ -415,7 +415,7 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
 
         return true;
       }
-     
+
     default:
       gcc_unreachable ();
     }
@@ -473,7 +473,7 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
           val = iterative_hash_expr (expr->ops.call.args[i], val);
       }
       break;
-     
+
     default:
       gcc_unreachable ();
     }
@@ -496,7 +496,7 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
       print_generic_expr (stream, element->lhs, 0);
       fprintf (stream, " = ");
     }
-  
+
   switch (element->expr.kind)
     {
       case EXPR_SINGLE:
@@ -597,7 +597,7 @@ free_all_edge_infos (void)
     }
 }
 
-/* Jump threading, redundancy elimination and const/copy propagation. 
+/* Jump threading, redundancy elimination and const/copy propagation.
 
    This pass may expose new symbols that need to be renamed into SSA.  For
    every new symbol exposed, its corresponding bit will be set in
@@ -646,7 +646,7 @@ tree_ssa_dominator_optimize (void)
      for jump threading; this may include back edges that are not part of
      a single loop.  */
   mark_dfs_back_edges ();
-      
+
   /* Recursively walk the dominator tree optimizing statements.  */
   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
 
@@ -720,10 +720,10 @@ tree_ssa_dominator_optimize (void)
 
   /* Free asserted bitmaps and stacks.  */
   BITMAP_FREE (need_eh_cleanup);
-  
+
   VEC_free (expr_hash_elt_t, heap, avail_exprs_stack);
   VEC_free (tree, heap, const_and_copies_stack);
-  
+
   /* Free the value-handle array.  */
   threadedge_finalize_values ();
   ssa_name_values = NULL;
@@ -737,7 +737,7 @@ gate_dominator (void)
   return flag_tree_dom != 0;
 }
 
-struct gimple_opt_pass pass_dominator = 
+struct gimple_opt_pass pass_dominator =
 {
  {
   GIMPLE_PASS,
@@ -816,24 +816,25 @@ remove_local_expressions_from_table (void)
   /* Remove all the expressions made available in this block.  */
   while (VEC_length (expr_hash_elt_t, avail_exprs_stack) > 0)
     {
-      struct expr_hash_elt element;
       expr_hash_elt_t victim = VEC_pop (expr_hash_elt_t, avail_exprs_stack);
+      void **slot;
 
       if (victim == NULL)
        break;
 
-      element = *victim;
-
       /* This must precede the actual removal from the hash table,
          as ELEMENT and the table entry may share a call argument
          vector which will be freed during removal.  */
       if (dump_file && (dump_flags & TDF_DETAILS))
         {
           fprintf (dump_file, "<<<< ");
-          print_expr_hash_elt (dump_file, &element);
+          print_expr_hash_elt (dump_file, victim);
         }
 
-      htab_remove_elt_with_hash (avail_exprs, &element, element.hash);
+      slot = htab_find_slot_with_hash (avail_exprs,
+                                      victim, victim->hash, NO_INSERT);
+      gcc_assert (slot && *slot == (void *) victim);
+      htab_clear_slot (avail_exprs, slot);
     }
 }
 
@@ -907,7 +908,7 @@ static void
 record_equivalences_from_phis (basic_block bb)
 {
   gimple_stmt_iterator gsi;
-  
+
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
       gimple phi = gsi_stmt (gsi);
@@ -1093,7 +1094,7 @@ record_cond (struct cond_equivalence *p)
 
 /* Build a cond_equivalence record indicating that the comparison
    CODE holds between operands OP0 and OP1.  */
-   
+
 static void
 build_and_record_new_cond (enum tree_code code,
                            tree op0, tree op1,
@@ -1370,7 +1371,7 @@ record_equality (tree x, tree y)
 
 /* Returns true when STMT is a simple iv increment.  It detects the
    following situation:
-   
+
    i_1 = phi (..., i_2)
    i_2 = i_1 +/- ...  */
 
@@ -1409,7 +1410,7 @@ simple_iv_increment_p (gimple stmt)
 }
 
 /* CONST_AND_COPIES is a table which maps an SSA_NAME to the current
-   known value for that SSA_NAME (or NULL if no value is known).  
+   known value for that SSA_NAME (or NULL if no value is known).
 
    Propagate values from CONST_AND_COPIES into the PHI nodes of the
    successors of BB.  */
@@ -1845,7 +1846,7 @@ eliminate_redundant_computations (gimple_stmt_iterator* gsi)
        }
 
       opt_stats.num_re++;
-      
+
       if (assigns_var_p
          && !useless_type_conversion_p (expr_type, TREE_TYPE (cached_lhs)))
        cached_lhs = fold_convert (expr_type, cached_lhs);
@@ -1880,7 +1881,7 @@ record_equivalences_from_stmt (gimple stmt, int may_optimize_p)
       && gimple_assign_single_p (stmt))
     {
       tree rhs = gimple_assign_rhs1 (stmt);
-               
+
       /* If the RHS of the assignment is a constant or another variable that
         may be propagated, register it in the CONST_AND_COPIES table.  We
         do not need to record unwind data for this, since this is a true
@@ -2030,7 +2031,7 @@ cprop_operand (gimple stmt, use_operand_p op_p)
 }
 
 /* CONST_AND_COPIES is a table which maps an SSA_NAME to the current
-   known value for that SSA_NAME (or NULL if no value is known).  
+   known value for that SSA_NAME (or NULL if no value is known).
 
    Propagate values from CONST_AND_COPIES into the uses, vuses and
    vdef_ops of STMT.  */
@@ -2049,7 +2050,7 @@ cprop_into_stmt (gimple stmt)
 }
 
 /* Optimize the statement pointed to by iterator SI.
-   
+
    We try to perform some simplistic global redundancy elimination and
    constant propagation:
 
@@ -2071,10 +2072,10 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
   bool modified_p = false;
 
   old_stmt = stmt = gsi_stmt (si);
-  
+
   if (gimple_code (stmt) == GIMPLE_COND)
     canonicalize_comparison (stmt);
-  
+
   update_stmt_if_modified (stmt);
   opt_stats.num_stmts++;
 
@@ -2098,6 +2099,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
       if (fold_stmt (&si))
        {
          stmt = gsi_stmt (si);
+         gimple_set_modified (stmt, true);
 
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@ -2137,8 +2139,6 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
 
   if (may_optimize_p)
     {
-      eliminate_redundant_computations (&si);
-      stmt = gsi_stmt (si);
       if (gimple_code (stmt) == GIMPLE_CALL)
        {
          /* Resolve __builtin_constant_p.  If it hasn't been
@@ -2153,6 +2153,10 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
              stmt = gsi_stmt (si);
            }
        }
+
+      update_stmt_if_modified (stmt);
+      eliminate_redundant_computations (&si);
+      stmt = gsi_stmt (si);
     }
 
   /* Record any additional equivalences created by this statement.  */
@@ -2163,7 +2167,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
      where it goes.  If that is the case, then mark the CFG as altered.
 
      This will cause us to later call remove_unreachable_blocks and
-     cleanup_tree_cfg when it is safe to do so.  It is not safe to 
+     cleanup_tree_cfg when it is safe to do so.  It is not safe to
      clean things up here since removal of edges and such can trigger
      the removal of PHI nodes, which in turn can release SSA_NAMEs to
      the manager.
@@ -2187,8 +2191,8 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
   if (gimple_modified_p (stmt) || modified_p)
     {
       tree val = NULL;
-      
-      update_stmt (stmt);
+
+      update_stmt_if_modified (stmt);
 
       if (gimple_code (stmt) == GIMPLE_COND)
         val = fold_binary_loc (gimple_location (stmt),
@@ -2225,50 +2229,47 @@ lookup_avail_expr (gimple stmt, bool insert)
   void **slot;
   tree lhs;
   tree temp;
-  struct expr_hash_elt *element = XNEW (struct expr_hash_elt);
+  struct expr_hash_elt element;
 
   /* Get LHS of assignment or call, else NULL_TREE.  */
   lhs = gimple_get_lhs (stmt);
 
-  initialize_hash_element (stmt, lhs, element);
+  initialize_hash_element (stmt, lhs, &element);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "LKUP ");
-      print_expr_hash_elt (dump_file, element);
+      print_expr_hash_elt (dump_file, &element);
     }
 
   /* Don't bother remembering constant assignments and copy operations.
      Constants and copy operations are handled by the constant/copy propagator
      in optimize_stmt.  */
-  if (element->expr.kind == EXPR_SINGLE
-      && (TREE_CODE (element->expr.ops.single.rhs) == SSA_NAME
-          || is_gimple_min_invariant (element->expr.ops.single.rhs)))
-    {
-      free (element);
-      return NULL_TREE;
-    }
+  if (element.expr.kind == EXPR_SINGLE
+      && (TREE_CODE (element.expr.ops.single.rhs) == SSA_NAME
+          || is_gimple_min_invariant (element.expr.ops.single.rhs)))
+    return NULL_TREE;
 
   /* Finally try to find the expression in the main expression hash table.  */
-  slot = htab_find_slot_with_hash (avail_exprs, element, element->hash,
+  slot = htab_find_slot_with_hash (avail_exprs, &element, element.hash,
                                   (insert ? INSERT : NO_INSERT));
   if (slot == NULL)
-    {
-      free (element);
-      return NULL_TREE;  
-    }
+    return NULL_TREE;
 
   if (*slot == NULL)
     {
-      *slot = (void *) element;
+      struct expr_hash_elt *element2 = XNEW (struct expr_hash_elt);
+      *element2 = element;
+      element2->stamp = element2;
+      *slot = (void *) element2;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
         {
           fprintf (dump_file, "2>>> ");
-          print_expr_hash_elt (dump_file, element);
+          print_expr_hash_elt (dump_file, element2);
         }
 
-      VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, element);
+      VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, element2);
       return NULL_TREE;
     }
 
@@ -2285,8 +2286,6 @@ lookup_avail_expr (gimple stmt, bool insert)
        lhs = temp;
     }
 
-  free (element);
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "FIND: ");
@@ -2392,9 +2391,18 @@ degenerate_phi_result (gimple phi)
 
       if (arg == lhs)
        continue;
+      else if (!arg)
+       break;
       else if (!val)
        val = arg;
-      else if (!operand_equal_p (arg, val, 0))
+      else if (arg == val)
+       continue;
+      /* We bring in some of operand_equal_p not only to speed things
+        up, but also to avoid crashing when dereferencing the type of
+        a released SSA name.  */
+      else if (TREE_CODE (val) != TREE_CODE (arg)
+              || TREE_CODE (val) == SSA_NAME
+              || !operand_equal_p (arg, val, 0))
        break;
     }
   return (i == gimple_phi_num_args (phi) ? val : NULL);
@@ -2458,7 +2466,7 @@ get_lhs_or_phi_result (gimple stmt)
    nodes as well in an effort to pick up secondary optimization
    opportunities.  */
 
-static void 
+static void
 propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_names)
 {
   /* First verify that propagation is valid and isn't going to move a
@@ -2485,7 +2493,7 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
          fprintf (dump_file, "'\n");
        }
 
-      /* Walk over every use of LHS and try to replace the use with RHS. 
+      /* Walk over every use of LHS and try to replace the use with RHS.
         At this point the only reason why such a propagation would not
         be successful would be if the use occurs in an ASM_EXPR.  */
       FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
@@ -2495,7 +2503,7 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
             into debug stmts will occur then.  */
          if (gimple_debug_bind_p (use_stmt))
            continue;
-       
+
          /* It's not always safe to propagate into an ASM_EXPR.  */
          if (gimple_code (use_stmt) == GIMPLE_ASM
               && ! may_propagate_copy_into_asm (lhs))
@@ -2548,7 +2556,7 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
              continue;
            }
 
-         /* From this point onward we are propagating into a 
+         /* From this point onward we are propagating into a
             real statement.  Folding may (or may not) be possible,
             we may expose new operands, expose dead EH edges,
             etc.  */
@@ -2669,7 +2677,7 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
            }
        }
 
-      /* Ensure there is nothing else to do. */ 
+      /* Ensure there is nothing else to do. */
       gcc_assert (!all || has_zero_uses (lhs));
 
       /* If we were able to propagate away all uses of LHS, then
@@ -2793,7 +2801,7 @@ eliminate_degenerate_phis (void)
      A set bit indicates that the statement or PHI node which
      defines the SSA_NAME should be (re)examined to determine if
      it has become a degenerate PHI or trivial const/copy propagation
-     opportunity. 
+     opportunity.
 
      Experiments have show we generally get better compilation
      time behavior with bitmaps rather than sbitmaps.  */
@@ -2871,7 +2879,7 @@ struct gimple_opt_pass pass_phi_only_cprop =
   0,                                   /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_cleanup_cfg
-    | TODO_dump_func 
+    | TODO_dump_func
     | TODO_ggc_collect
     | TODO_verify_ssa
     | TODO_verify_stmts