OSDN Git Service

* cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index 0eee6d9..bb832d2 100644 (file)
@@ -1,5 +1,5 @@
 /* If-conversion for vectorizer.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    Contributed by Devang Patel <dpatel@apple.com>
 
 This file is part of GCC.
@@ -126,7 +126,7 @@ static void combine_blocks (struct loop *);
 static tree ifc_temp_var (tree, tree);
 static bool pred_blocks_visited_p (basic_block, bitmap *);
 static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop);
-static bool bb_with_exit_edge_p (basic_block);
+static bool bb_with_exit_edge_p (struct loop *, basic_block);
 
 /* List of basic blocks in if-conversion-suitable order.  */
 static basic_block *ifc_bbs;
@@ -312,7 +312,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
   /* Now this conditional statement is redundant. Remove it.
      But, do not remove exit condition! Update exit condition
      using new condition.  */
-  if (!bb_with_exit_edge_p (bb_for_stmt (stmt)))
+  if (!bb_with_exit_edge_p (loop, bb_for_stmt (stmt)))
     {
       bsi_remove (bsi);
       cond = NULL_TREE;
@@ -405,7 +405,7 @@ if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr)
 
   if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME
       && bb != loop->header
-      && !bb_with_exit_edge_p (bb))
+      && !bb_with_exit_edge_p (loop, bb))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -534,8 +534,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
       return false;
     }
 
-  flow_loop_scan (loop, LOOP_ALL);
-
   /* If only one block, no need for if-conversion.  */
   if (loop->num_nodes <= 2)
     {
@@ -545,7 +543,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
     }
 
   /* More than one loop exit is too much to handle.  */
-  if (loop->num_exits > 1)
+  if (!loop->single_exit)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "multiple exits\n");
@@ -557,8 +555,10 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
   /* If one of the loop header's edge is exit edge then do not apply
      if-conversion.  */
   FOR_EACH_EDGE (e, ei, loop->header->succs)
-    if ( e->flags & EDGE_LOOP_EXIT)
-      return false;
+    {
+      if (loop_exit_edge_p (loop, e))
+       return false;
+    }
 
   compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL);
 
@@ -593,7 +593,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
        if (!if_convertible_phi_p (loop, bb, phi))
          return false;
 
-      if (bb_with_exit_edge_p (bb))
+      if (bb_with_exit_edge_p (loop, bb))
        exit_bb_seen = true;
     }
 
@@ -639,10 +639,23 @@ add_to_dst_predicate_list (struct loop * loop, basic_block bb,
     new_cond = unshare_expr (cond);
   else
     {
-      tree tmp_stmt;
+      tree tmp;
+      tree tmp_stmt = NULL_TREE;
+      tree tmp_stmts1 = NULL_TREE;
+      tree tmp_stmts2 = NULL_TREE;
+      prev_cond = force_gimple_operand (unshare_expr (prev_cond),
+                                       &tmp_stmts1, true, NULL);
+      if (tmp_stmts1)
+        bsi_insert_before (bsi, tmp_stmts1, BSI_SAME_STMT);
+
+      cond = force_gimple_operand (unshare_expr (cond),
+                                  &tmp_stmts2, true, NULL);
+      if (tmp_stmts2)
+        bsi_insert_before (bsi, tmp_stmts2, BSI_SAME_STMT);
+
       /* new_cond == prev_cond AND cond */
-      tree tmp = build (TRUTH_AND_EXPR, boolean_type_node,
-                       unshare_expr (prev_cond), cond);
+      tmp = build (TRUTH_AND_EXPR, boolean_type_node,
+                  unshare_expr (prev_cond), cond);
       tmp_stmt = ifc_temp_var (boolean_type_node, tmp);
       bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT);
       new_cond = TREE_OPERAND (tmp_stmt, 0);
@@ -757,7 +770,7 @@ replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb,
   arg_1 = NULL_TREE;
 
   /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr.  */
-  if (PHI_ARG_EDGE(phi, 1)->src == true_bb)
+  if (EDGE_PRED (bb, 1)->src == true_bb)
     {
       arg_0 = PHI_ARG_DEF (phi, 1);
       arg_1 = PHI_ARG_DEF (phi, 0);
@@ -817,7 +830,7 @@ process_phi_nodes (struct loop *loop)
        continue;
 
       phi = phi_nodes (bb);
-      bsi = bsi_start (bb);
+      bsi = bsi_after_labels (bb);
 
       /* BB has two predecessors. Using predecessor's aux field, set
         appropriate condition for the PHI node replacement.  */
@@ -861,7 +874,7 @@ combine_blocks (struct loop *loop)
 
       bb = ifc_bbs[i];
 
-      if (!exit_bb && bb_with_exit_edge_p (bb))
+      if (!exit_bb && bb_with_exit_edge_p (loop, bb))
          exit_bb = bb;
 
       if (bb == exit_bb)
@@ -877,11 +890,13 @@ combine_blocks (struct loop *loop)
            {
              /* Redirect non-exit edge to loop->latch.  */
              FOR_EACH_EDGE (e, ei, bb->succs)
-               if (!(e->flags & EDGE_LOOP_EXIT))
-                 {
-                   redirect_edge_and_branch (e, loop->latch);
-                   set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
-                 }
+               {
+                 if (!loop_exit_edge_p (loop, e))
+                   {
+                     redirect_edge_and_branch (e, loop->latch);
+                     set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
+                   }
+               }
            }
          continue;
        }
@@ -961,7 +976,7 @@ ifc_temp_var (tree type, tree exp)
   stmt = build (MODIFY_EXPR, type, var, exp);
 
   /* Get SSA name for the new variable and set make new statement
-     its definition statment.  */
+     its definition statement.  */
   new_name = make_ssa_name (var, stmt);
   TREE_OPERAND (stmt, 0) = new_name;
   SSA_NAME_DEF_STMT (new_name) = stmt;
@@ -1004,7 +1019,7 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
   gcc_assert (loop->latch != EXIT_BLOCK_PTR);
 
   blocks = xcalloc (loop->num_nodes, sizeof (basic_block));
-  visited = BITMAP_XMALLOC ();
+  visited = BITMAP_ALLOC (NULL);
 
   blocks_in_bfs_order = get_loop_body_in_bfs_order (loop);
 
@@ -1016,7 +1031,7 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
       if (bb->flags & BB_IRREDUCIBLE_LOOP)
        {
          free (blocks_in_bfs_order);
-         BITMAP_XFREE (visited);
+         BITMAP_FREE (visited);
          free (blocks);
          return NULL;
        }
@@ -1039,21 +1054,21 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
        }
     }
   free (blocks_in_bfs_order);
-  BITMAP_XFREE (visited);
+  BITMAP_FREE (visited);
   return blocks;
 }
 
-/* Return true if one of the basic block BB edge is loop exit.  */
+/* Return true if one of the basic block BB edge is exit of LOOP.  */
 
 static bool
-bb_with_exit_edge_p (basic_block bb)
+bb_with_exit_edge_p (struct loop *loop, basic_block bb)
 {
   edge e;
   edge_iterator ei;
   bool exit_edge_found = false;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->flags & EDGE_LOOP_EXIT)
+    if (loop_exit_edge_p (loop, e))
       {
        exit_edge_found = true;
        break;