tree-ssa-forwprop.c (remove_prop_source_from_use): Robustify against already removed...
authorRichard Guenther <rguenther@suse.de>
Wed, 20 Jul 2011 15:13:58 +0000 (15:13 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 20 Jul 2011 15:13:58 +0000 (15:13 +0000)
2011-07-20  Richard Guenther  <rguenther@suse.de>

* tree-ssa-forwprop.c (remove_prop_source_from_use): Robustify
against already removed statements.
(forward_propagate_into_comparison): Remove dead defining stmts.
(forward_propagate_into_gimple_cond): Likewise.
(forward_propagate_into_cond): Simplify.
(ssa_forward_propagate_and_combine): Handle changed cfg from
forward_propagate_into_comparison.
* tree-ssa-phiopt.c (conditional_replacement): Use proper
locations for newly built statements.

From-SVN: r176517

gcc/ChangeLog
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-phiopt.c

index 6f09fc5bfe221250e19a84803902ab19f45ecf28..2df70f0aba5761e0d21d1549c83f357022a809f2 100644 (file)
@@ -1,3 +1,15 @@
+2011-07-20  Richard Guenther  <rguenther@suse.de>
+
+       * tree-ssa-forwprop.c (remove_prop_source_from_use): Robustify
+       against already removed statements.
+       (forward_propagate_into_comparison): Remove dead defining stmts.
+       (forward_propagate_into_gimple_cond): Likewise.
+       (forward_propagate_into_cond): Simplify.
+       (ssa_forward_propagate_and_combine): Handle changed cfg from
+       forward_propagate_into_comparison.
+       * tree-ssa-phiopt.c (conditional_replacement): Use proper
+       locations for newly built statements.
+
 2011-07-20  Georg-Johann Lay  <avr@gjlay.de>
 
        * config/avr/avr.c (avr_rtx_costs): Set cost of SYMBOL_REF to 0.
index 577609b20149a289a54b61fba316f6927b684868..5d04fc32ce4f75ddfcf820338152410d215c2b3f 100644 (file)
@@ -313,8 +313,10 @@ remove_prop_source_from_use (tree name)
       return cfg_changed;
 
     stmt = SSA_NAME_DEF_STMT (name);
-    gsi = gsi_for_stmt (stmt);
     bb = gimple_bb (stmt);
+    if (!bb)
+      return cfg_changed;
+    gsi = gsi_for_stmt (stmt);
     release_defs (stmt);
     gsi_remove (&gsi, true);
     cfg_changed |= gimple_purge_dead_eh_edges (bb);
@@ -437,29 +439,36 @@ forward_propagate_into_comparison_1 (location_t loc,
 
 /* Propagate from the ssa name definition statements of the assignment
    from a comparison at *GSI into the conditional if that simplifies it.
-   Returns true if the stmt was modified, false if not.  */
+   Returns 1 if the stmt was modified and 2 if the CFG needs cleanup,
+   otherwise returns 0.  */
 
-static bool
+static int 
 forward_propagate_into_comparison (gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
   tree tmp;
+  bool cfg_changed = false;
+  tree rhs1 = gimple_assign_rhs1 (stmt);
+  tree rhs2 = gimple_assign_rhs2 (stmt);
 
   /* Combine the comparison with defining statements.  */
   tmp = forward_propagate_into_comparison_1 (gimple_location (stmt),
                                             gimple_assign_rhs_code (stmt),
                                             TREE_TYPE
                                               (gimple_assign_lhs (stmt)),
-                                            gimple_assign_rhs1 (stmt),
-                                            gimple_assign_rhs2 (stmt));
+                                            rhs1, rhs2);
   if (tmp)
     {
       gimple_assign_set_rhs_from_tree (gsi, tmp);
       update_stmt (stmt);
-      return true;
+      if (TREE_CODE (rhs1) == SSA_NAME)
+       cfg_changed |= remove_prop_source_from_use (rhs1);
+      if (TREE_CODE (rhs2) == SSA_NAME)
+       cfg_changed |= remove_prop_source_from_use (rhs2);
+      return cfg_changed ? 2 : 1;
     }
 
-  return false;
+  return 0;
 }
 
 /* Propagate from the ssa name definition statements of COND_EXPR
@@ -472,10 +481,12 @@ forward_propagate_into_comparison (gimple_stmt_iterator *gsi)
 static int
 forward_propagate_into_gimple_cond (gimple stmt)
 {
-  int did_something = 0;
   location_t loc = gimple_location (stmt);
   tree tmp;
   enum tree_code code = gimple_cond_code (stmt);
+  bool cfg_changed = false;
+  tree rhs1 = gimple_cond_lhs (stmt);
+  tree rhs2 = gimple_cond_rhs (stmt);
 
   /* We can do tree combining on SSA_NAME and comparison expressions.  */
   if (TREE_CODE_CLASS (gimple_cond_code (stmt)) != tcc_comparison)
@@ -483,18 +494,13 @@ forward_propagate_into_gimple_cond (gimple stmt)
 
   tmp = forward_propagate_into_comparison_1 (loc, code,
                                             boolean_type_node,
-                                            gimple_cond_lhs (stmt),
-                                            gimple_cond_rhs (stmt));
+                                            rhs1, rhs2);
   if (tmp)
     {
       if (dump_file && tmp)
        {
-         tree cond = build2 (gimple_cond_code (stmt),
-                             boolean_type_node,
-                             gimple_cond_lhs (stmt),
-                             gimple_cond_rhs (stmt));
          fprintf (dump_file, "  Replaced '");
-         print_generic_expr (dump_file, cond, 0);
+         print_gimple_expr (dump_file, stmt, 0, 0);
          fprintf (dump_file, "' with '");
          print_generic_expr (dump_file, tmp, 0);
          fprintf (dump_file, "'\n");
@@ -503,14 +509,14 @@ forward_propagate_into_gimple_cond (gimple stmt)
       gimple_cond_set_condition_from_tree (stmt, unshare_expr (tmp));
       update_stmt (stmt);
 
-      /* Remove defining statements.  */
-      if (is_gimple_min_invariant (tmp))
-       did_something = 2;
-      else if (did_something == 0)
-       did_something = 1;
+      if (TREE_CODE (rhs1) == SSA_NAME)
+       cfg_changed |= remove_prop_source_from_use (rhs1);
+      if (TREE_CODE (rhs2) == SSA_NAME)
+       cfg_changed |= remove_prop_source_from_use (rhs2);
+      return (cfg_changed || is_gimple_min_invariant (tmp)) ? 2 : 1;
     }
 
-  return did_something;
+  return 0;
 }
 
 
@@ -526,7 +532,6 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
 {
   gimple stmt = gsi_stmt (*gsi_p);
   location_t loc = gimple_location (stmt);
-  int did_something = 0;
   tree tmp = NULL_TREE;
   tree cond = gimple_assign_rhs1 (stmt);
 
@@ -541,7 +546,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
       tree name = cond, rhs0;
       gimple def_stmt = get_prop_source_stmt (name, true, NULL);
       if (!def_stmt || !can_propagate_from (def_stmt))
-       return did_something;
+       return 0;
 
       rhs0 = gimple_assign_rhs1 (def_stmt);
       tmp = combine_cond_expr_cond (loc, NE_EXPR, boolean_type_node, rhs0,
@@ -564,14 +569,10 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
       stmt = gsi_stmt (*gsi_p);
       update_stmt (stmt);
 
-      /* Remove defining statements.  */
-      if (is_gimple_min_invariant (tmp))
-       did_something = 2;
-      else if (did_something == 0)
-       did_something = 1;
+      return is_gimple_min_invariant (tmp) ? 2 : 1;
     }
 
-  return did_something;
+  return 0;
 }
 
 /* We've just substituted an ADDR_EXPR into stmt.  Update all the
@@ -2441,11 +2442,15 @@ ssa_forward_propagate_and_combine (void)
                else if (TREE_CODE_CLASS (code) == tcc_comparison)
                  {
                    bool no_warning = gimple_no_warning_p (stmt);
+                   int did_something;
                    fold_defer_overflow_warnings ();
-                   changed = forward_propagate_into_comparison (&gsi);
+                   did_something = forward_propagate_into_comparison (&gsi);
+                   if (did_something == 2)
+                     cfg_changed = true;
                    fold_undefer_overflow_warnings
                        (!no_warning && changed,
                         stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
+                   changed = did_something != 0;
                  }
                else if (code == BIT_AND_EXPR
                         || code == BIT_IOR_EXPR
index 79e8e015fda22ce1021f8e5a343289ac1d8d71ab..ed8f9795e788fa65c70659de6229886162e070fe 100644 (file)
@@ -544,8 +544,9 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
   /* To handle special cases like floating point comparison, it is easier and
      less error-prone to build a tree and gimplify it on the fly though it is
      less efficient.  */
-  cond = fold_build2 (gimple_cond_code (stmt), boolean_type_node,
-                     gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
+  cond = fold_build2_loc (gimple_location (stmt),
+                         gimple_cond_code (stmt), boolean_type_node,
+                         gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
 
   /* We need to know which is the true edge and which is the false
      edge so that we know when to invert the condition below.  */
@@ -554,7 +555,8 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
       || (e0 == false_edge && integer_onep (arg0))
       || (e1 == true_edge && integer_zerop (arg1))
       || (e1 == false_edge && integer_onep (arg1)))
-    cond = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
+    cond = fold_build1_loc (gimple_location (stmt),
+                           TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
 
   /* Insert our new statements at the end of conditional block before the
      COND_STMT.  */