OSDN Git Service

PR target/11327
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dom.c
index d88d683..67446b1 100644 (file)
@@ -550,6 +550,16 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
     {
       tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
       tree dst = PHI_RESULT (phi);
+
+      /* If the desired argument is not the same as this PHI's result 
+        and it is set by a PHI in this block, then we can not thread
+        through this block.  */
+      if (src != dst
+         && TREE_CODE (src) == SSA_NAME
+         && TREE_CODE (SSA_NAME_DEF_STMT (src)) == PHI_NODE
+         && bb_for_stmt (SSA_NAME_DEF_STMT (src)) == e->dest)
+       return;
+
       record_const_or_copy (dst, src);
       register_new_def (dst, &block_defs_stack);
     }
@@ -653,7 +663,7 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
       if (SSA_NAME_VAR (cached_lhs) != SSA_NAME_VAR (lhs))
        break;
 
-      /* If CACHED_LHS does not represent the current value of the undering
+      /* If CACHED_LHS does not represent the current value of the underlying
         variable in CACHED_LHS/LHS, then we can not ignore this statement.  */
       if (var_ann (SSA_NAME_VAR (lhs))->current_def != cached_lhs)
        break;
@@ -676,22 +686,6 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
          || TREE_CODE (stmt) == SWITCH_EXPR))
     {
       tree cond, cached_lhs;
-      edge e1;
-      edge_iterator ei;
-
-      /* Do not forward entry edges into the loop.  In the case loop
-        has multiple entry edges we may end up in constructing irreducible
-        region.  
-        ??? We may consider forwarding the edges in the case all incoming
-        edges forward to the same destination block.  */
-      if (!e->flags & EDGE_DFS_BACK)
-       {
-         FOR_EACH_EDGE (e1, ei, e->dest->preds)
-           if (e1->flags & EDGE_DFS_BACK)
-             break;
-         if (e1)
-           return;
-       }
 
       /* Now temporarily cprop the operands and try to find the resulting
         expression in the hash tables.  */
@@ -745,12 +739,12 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
             otherwise look it up in the hash tables.  */
          cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
          if (! is_gimple_min_invariant (cached_lhs))
-           cached_lhs = lookup_avail_expr (dummy_cond, false);
-         if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
            {
-             cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
-                                                               NULL,
-                                                               false);
+             cached_lhs = lookup_avail_expr (dummy_cond, false);
+             if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
+               cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
+                                                                 NULL,
+                                                                 false);
            }
        }
       /* We can have conditionals which just test the state of a
@@ -962,7 +956,7 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
 {
   tree last;
 
-  /* If we are at a leaf node in the dominator graph, see if we can thread
+  /* If we are at a leaf node in the dominator tree, see if we can thread
      the edge from BB through its successor.
 
      Do this before we remove entries from our equivalence tables.  */
@@ -1177,23 +1171,20 @@ record_equivalences_from_phis (basic_block bb)
        {
          tree t = PHI_ARG_DEF (phi, i);
 
-         if (TREE_CODE (t) == SSA_NAME || is_gimple_min_invariant (t))
-           {
-             /* Ignore alternatives which are the same as our LHS.  */
-             if (operand_equal_p (lhs, t, 0))
-               continue;
-
-             /* If we have not processed an alternative yet, then set
-                RHS to this alternative.  */
-             if (rhs == NULL)
-               rhs = t;
-             /* If we have processed an alternative (stored in RHS), then
-                see if it is equal to this one.  If it isn't, then stop
-                the search.  */
-             else if (! operand_equal_p (rhs, t, 0))
-               break;
-           }
-         else
+         /* Ignore alternatives which are the same as our LHS.  Since
+            LHS is a PHI_RESULT, it is known to be a SSA_NAME, so we
+            can simply compare pointers.  */
+         if (lhs == t)
+           continue;
+
+         /* If we have not processed an alternative yet, then set
+            RHS to this alternative.  */
+         if (rhs == NULL)
+           rhs = t;
+         /* If we have processed an alternative (stored in RHS), then
+            see if it is equal to this one.  If it isn't, then stop
+            the search.  */
+         else if (! operand_equal_for_phi_arg_p (rhs, t))
            break;
        }
 
@@ -2290,8 +2281,7 @@ cprop_into_successor_phis (basic_block bb, bitmap nonzero_vars)
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
       tree phi;
-      int phi_num_args;
-      int hint;
+      int indx;
 
       /* If this is an abnormal edge, then we do not want to copy propagate
         into the PHI alternative associated with this edge.  */
@@ -2302,46 +2292,16 @@ cprop_into_successor_phis (basic_block bb, bitmap nonzero_vars)
       if (! phi)
        continue;
 
-      /* There is no guarantee that for any two PHI nodes in a block that
-        the phi alternative associated with a particular edge will be
-        at the same index in the phi alternative array.
-
-        However, it is very likely they will be the same.  So we keep
-        track of the index of the alternative where we found the edge in
-        the previous phi node and check that index first in the next
-        phi node.  If that hint fails, then we actually search all
-        the entries.  */
-      phi_num_args = PHI_NUM_ARGS (phi);
-      hint = phi_num_args;
+      indx = e->dest_idx;
       for ( ; phi; phi = PHI_CHAIN (phi))
        {
-         int i;
          tree new;
          use_operand_p orig_p;
          tree orig;
 
-         /* If the hint is valid (!= phi_num_args), see if it points
-            us to the desired phi alternative.  */
-         if (hint != phi_num_args && PHI_ARG_EDGE (phi, hint) == e)
-           ;
-         else
-           {
-             /* The hint was either invalid or did not point to the
-                correct phi alternative.  Search all the alternatives
-                for the correct one.  Update the hint.  */
-             for (i = 0; i < phi_num_args; i++)
-               if (PHI_ARG_EDGE (phi, i) == e)
-                 break;
-             hint = i;
-           }
-
-         /* If we did not find the proper alternative, then something is
-            horribly wrong.  */
-         gcc_assert (hint != phi_num_args);
-
          /* The alternative may be associated with a constant, so verify
             it is an SSA_NAME before doing anything with it.  */
-         orig_p = PHI_ARG_DEF_PTR (phi, hint);
+         orig_p = PHI_ARG_DEF_PTR (phi, indx);
          orig = USE_FROM_PTR (orig_p);
          if (TREE_CODE (orig) != SSA_NAME)
            continue;
@@ -2349,7 +2309,7 @@ cprop_into_successor_phis (basic_block bb, bitmap nonzero_vars)
          /* If the alternative is known to have a nonzero value, record
             that fact in the PHI node itself for future use.  */
          if (bitmap_bit_p (nonzero_vars, SSA_NAME_VERSION (orig)))
-           PHI_ARG_NONZERO (phi, hint) = true;
+           PHI_ARG_NONZERO (phi, indx) = true;
 
          /* If we have *ORIG_P in our constant/copy table, then replace
             ORIG_P with its value in our constant/copy table.  */
@@ -2487,9 +2447,9 @@ record_edge_info (basic_block bb)
                    }
                }
 
-             if (is_gimple_min_invariant (op0)
-                 && (TREE_CODE (op1) == SSA_NAME
-                      || is_gimple_min_invariant (op1)))
+             else if (is_gimple_min_invariant (op0)
+                      && (TREE_CODE (op1) == SSA_NAME
+                          || is_gimple_min_invariant (op1)))
                {
                  tree inverted = invert_truthvalue (cond);
                  struct edge_info *edge_info;
@@ -2513,9 +2473,9 @@ record_edge_info (basic_block bb)
                    }
                }
 
-             if (TREE_CODE (op0) == SSA_NAME
-                 && (is_gimple_min_invariant (op1)
-                     || TREE_CODE (op1) == SSA_NAME))
+             else if (TREE_CODE (op0) == SSA_NAME
+                      && (is_gimple_min_invariant (op1)
+                          || TREE_CODE (op1) == SSA_NAME))
                {
                  tree inverted = invert_truthvalue (cond);
                  struct edge_info *edge_info;